Skip to content

Commit

Permalink
Add more test cases to json dump tests
Browse files Browse the repository at this point in the history
  • Loading branch information
st235 committed Jul 1, 2024
1 parent 6b19949 commit b38f213
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 67 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ FetchContent_MakeAvailable(googletest)
enable_testing()

add_executable(jsonc_tests
# Utils.
tests/integration/test_utils.h

# Unit tests.
# Testing types.
tests/unit/json_null_tests.cpp
Expand Down
41 changes: 30 additions & 11 deletions tests/integration/json_dump_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,49 @@
#include <gtest/gtest.h>

#include <string>
#include <memory>
#include <utility>
#include <gmock/gmock.h>

#include "json.h"
#include "test_utils.h"

using ::test_utils::TestData;
using ::test_utils::PrepareTestData;
using ::testing::AnyOfArray;

class JsonDumpsTestingFixture: public ::testing::TestWithParam<std::pair<json::Json, std::string>> {};
class JsonDumpsTestingFixture: public ::testing::TestWithParam<TestData<json::Json>> {};

INSTANTIATE_TEST_SUITE_P(
JsonDumpTests,
JsonDumpsTestingFixture,
::testing::Values(
std::make_pair(json::Json::null(), "null"),
std::make_pair(json::Json(2.0), "2"),
std::make_pair(json::Json({ json::Json(true), json::Json(5.0), json::Json(static_cast<std::string>("Hello")) }), R"([true,5,"Hello"])")
// Primitives.
PrepareTestData<json::Json>(json::Json::null(), { "null" }),
PrepareTestData<json::Json>(json::Json(2.0), { "2" }),
PrepareTestData<json::Json>(json::Json(-1.5), { "-1.5" }),
PrepareTestData<json::Json>(json::Json(true), { "true" }),
PrepareTestData<json::Json>(json::Json(false), { "false" }),
PrepareTestData<json::Json>(json::Json("Hello world"), { R"("Hello world")" }),
PrepareTestData<json::Json>(json::Json::array(), { "[]" }),
PrepareTestData<json::Json>(json::Json::object(), { "{}" }),

// Arrays.
PrepareTestData<json::Json>(json::Json({ json::Json(true), json::Json(5.0), json::Json(static_cast<std::string>("Hello")) }), { R"([true,5,"Hello"])" }),

// Objects.
PrepareTestData<json::Json>(json::Json({
std::make_pair("a", json::Json(true)),
std::make_pair("b", json::Json({ json::Json(0.0), json::Json::null() })),
}), {
R"({"a":true,"b":[0,null]})",
R"({"b":[0,null],"a":true})"
})
)
);

TEST_P(JsonDumpsTestingFixture, JsonYieldsValidDump) {
const auto& pair = GetParam();

const auto& json = pair.first;
const auto& expected_json = pair.second;
const auto& expected_jsons = pair.second;

const auto& opt_dumped_json = json::Json::toJson(json);

EXPECT_EQ(expected_json, opt_dumped_json);
EXPECT_THAT(opt_dumped_json, AnyOfArray(expected_jsons));
}
97 changes: 41 additions & 56 deletions tests/integration/json_valid_json_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,72 @@
#include <gmock/gmock.h>

#include <string>
#include <memory>
#include <utility>
#include <vector>

#include "json.h"
#include "test_utils.h"

using ::test_utils::TestData;
using ::test_utils::PrepareTestData;
using ::testing::AnyOfArray;

namespace {

// Expected value is a vector of strings as JSON specification
// does not provide any gurantees on how keys are ordered within a
// JSON Object, therefore we provide all permutations of keys and
// expect that one of them matches.
using TestsData = std::pair<std::string, std::vector<std::string>>;

TestsData PrepareTestsData(const std::string& actual,
const std::vector<std::string>& expected) {
return std::make_pair(actual, expected);
}

} // namespace

class ValidJsonTestingFixture: public ::testing::TestWithParam<TestsData> {};
class ValidJsonTestingFixture: public ::testing::TestWithParam<TestData<std::string>> {};

INSTANTIATE_TEST_SUITE_P(
ValidJsonTests,
ValidJsonTestingFixture,
::testing::Values(
// Primitives.
PrepareTestsData("null", { "null" }),
PrepareTestsData("true", { "true" }),
PrepareTestsData("false", { "false" }),
PrepareTestsData(R"("hello world")", { R"("hello world")" }),
PrepareTestsData(R"("special character: \b ")", { R"("special character: \b ")" }),
PrepareTestsData(R"("special character: \uAF22 ")", { R"("special character: \uAF22 ")" }),
PrepareTestsData(R"("special character: \\ ")", { R"("special character: \\ ")" }),
PrepareTestsData("0", { "0" }),
PrepareTestsData("-1", { "-1" }),
PrepareTestsData("122", { "122" }),
PrepareTestsData("15", { "15" }),
PrepareTestsData("0.55", { "0.55" }),
PrepareTestsData("-0.27", { "-0.27" }),
PrepareTestsData("89.11", { "89.11" }),
PrepareTestsData("-2.7e-32", { "-2.7e-32" }),
PrepareTestsData("-5.4e+29", { "-5.4e+29" }),
PrepareTestData<std::string>("null", { "null" }),
PrepareTestData<std::string>("true", { "true" }),
PrepareTestData<std::string>("false", { "false" }),
PrepareTestData<std::string>(R"("hello world")", { R"("hello world")" }),
PrepareTestData<std::string>(R"("special character: \b ")", { R"("special character: \b ")" }),
PrepareTestData<std::string>(R"("special character: \uAF22 ")", { R"("special character: \uAF22 ")" }),
PrepareTestData<std::string>(R"("special character: \\ ")", { R"("special character: \\ ")" }),
PrepareTestData<std::string>("0", { "0" }),
PrepareTestData<std::string>("-1", { "-1" }),
PrepareTestData<std::string>("122", { "122" }),
PrepareTestData<std::string>("15", { "15" }),
PrepareTestData<std::string>("0.55", { "0.55" }),
PrepareTestData<std::string>("-0.27", { "-0.27" }),
PrepareTestData<std::string>("89.11", { "89.11" }),
PrepareTestData<std::string>("-2.7e-32", { "-2.7e-32" }),
PrepareTestData<std::string>("-5.4e+29", { "-5.4e+29" }),

// Whitespaces.
PrepareTestsData("\t \t \n \n null \t \t \n\n\n\n", { "null" }),
PrepareTestsData("\n \t \t \n false ", { "false" }),
PrepareTestData<std::string>("\t \t \n \n null \t \t \n\n\n\n", { "null" }),
PrepareTestData<std::string>("\n \t \t \n false ", { "false" }),

// Empty objects.
PrepareTestsData("{}", { "{}" }),
PrepareTestsData("[]", { "[]" }),
PrepareTestsData("[{},{},{}]", { "[{},{},{}]" }),
PrepareTestsData("[\n\n\t\t\n \n ]", { "[]" }),
PrepareTestsData("{\n \t\t\r\n \n }", { "{}" }),
PrepareTestData<std::string>("{}", { "{}" }),
PrepareTestData<std::string>("[]", { "[]" }),
PrepareTestData<std::string>("[{},{},{}]", { "[{},{},{}]" }),
PrepareTestData<std::string>("[\n\n\t\t\n \n ]", { "[]" }),
PrepareTestData<std::string>("{\n \t\t\r\n \n }", { "{}" }),

// Arrays.
// Keys separated with whitespaces are fine.
PrepareTestsData("[1, null \t , \t \n \"a\", true \t, \"c\" \n\n\n \t]", { "[1,null,\"a\",true,\"c\"]" }),
PrepareTestData<std::string>("[1, null \t , \t \n \"a\", true \t, \"c\" \n\n\n \t]", { "[1,null,\"a\",true,\"c\"]" }),

// Check that ordering is preserved.
PrepareTestsData("[1, 3, 6, true]", { "[1,3,6,true]" }),
PrepareTestsData(R"(["a", false, 5.6, "b"])", { R"(["a",false,5.6,"b"])" }),
PrepareTestData<std::string>("[1, 3, 6, true]", { "[1,3,6,true]" }),
PrepareTestData<std::string>(R"(["a", false, 5.6, "b"])", { R"(["a",false,5.6,"b"])" }),

// Compound arrays.
PrepareTestsData(R"(["a", [1, 2, 7, 9],"c", "hello"])", { R"(["a",[1,2,7,9],"c","hello"])" }),
PrepareTestsData(R"([[true, true, false], [1, 2, 3], "c", ["a", "b", "c"]])", { R"([[true,true,false],[1,2,3],"c",["a","b","c"]])" }),
PrepareTestData<std::string>(R"(["a", [1, 2, 7, 9],"c", "hello"])", { R"(["a",[1,2,7,9],"c","hello"])" }),
PrepareTestData<std::string>(R"([[true, true, false], [1, 2, 3], "c", ["a", "b", "c"]])", { R"([[true,true,false],[1,2,3],"c",["a","b","c"]])" }),

// Objects.
// Whitespaces between keys and values are fine.
PrepareTestsData("{\"a\" : \t\n 5 \n}", { "{\"a\":5}" }),
PrepareTestData<std::string>("{\"a\" : \t\n 5 \n}", { "{\"a\":5}" }),
// Keys separated with whitespaces are fine.
PrepareTestsData("{\"a\":5, \t\n \"b\": true}", { "{\"a\":5,\"b\":true}", "{\"b\":true,\"a\":5}" }),
PrepareTestData<std::string>("{\"a\":5, \t\n \"b\": true}", { "{\"a\":5,\"b\":true}", "{\"b\":true,\"a\":5}" }),

// Compound objects.
PrepareTestsData("\n \t true \t", { "true" }),
PrepareTestsData("[5, true]", { "[5,true]" }),
PrepareTestsData(R"({ "a": "hello world!"})", { R"({"a":"hello world!"})" }),
PrepareTestsData(
PrepareTestData<std::string>("\n \t true \t", { "true" }),
PrepareTestData<std::string>("[5, true]", { "[5,true]" }),
PrepareTestData<std::string>(R"({ "a": "hello world!"})", { R"({"a":"hello world!"})" }),
PrepareTestData<std::string>(
R"([{"a":{"a":false,"b":19.3235},"c":[19,20]},{"c":[14,15,17,14]}])",
{
R"([{"a":{"a":false,"b":19.3235},"c":[19,20]},{"c":[14,15,17,14]}])",
Expand All @@ -95,7 +80,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([{"c":[19,20],"a":{"b":19.3235,"a":false}},{"c":[14,15,17,14]}])"
}
),
PrepareTestsData(
PrepareTestData<std::string>(
R"([ { "a": { "a": ["hello" , 5, true], "c": ["a"] }, "c": [19, 20] }, { "b": null } ])",
{
R"([{"a":{"a":["hello",5,true],"c":["a"]},"c":[19,20]},{"b":null}])",
Expand All @@ -104,7 +89,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([{"c":[19,20],"a":{"c":["a"],"a":["hello",5,true]}},{"b":null}])"
}
),
PrepareTestsData(
PrepareTestData<std::string>(
R"([{"index":0,"isActive":true,"balance":"$3,496.62"}])",
{
R"([{"index":0,"isActive":true,"balance":"$3,496.62"}])",
Expand All @@ -115,7 +100,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([{"balance":"$3,496.62","isActive":true,"index":0}])"
}
),
PrepareTestsData(
PrepareTestData<std::string>(
R"([{"a":0},{"a":1,"b":true},{"a":2,"b":"hello world","c":[1,2,3]}])",
{
R"([{"a":0},{"a":1,"b":true},{"a":2,"b":"hello world","c":[1,2,3]}])",
Expand Down
26 changes: 26 additions & 0 deletions tests/integration/test_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef __JSONC_TEST_UTILS_H__
#define __JSONC_TEST_UTILS_H__

#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace test_utils {

// Expected value is a vector of strings as JSON specification
// does not provide any gurantees on how keys are ordered within a
// JSON Object, therefore we provide all permutations of keys and
// expect that one of them matches.
template<typename T>
using TestData = std::pair<T, std::vector<std::string>>;

template<typename T>
inline TestData<T> PrepareTestData(const T& actual,
const std::vector<std::string>& expected) {
return std::make_pair(actual, expected);
}

} // namespace test_utils

#endif // __JSONC_TEST_UTILS_H__

0 comments on commit b38f213

Please sign in to comment.