diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/test/formatted_json_test.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/test/formatted_json_test.cpp')
-rw-r--r-- | source/test/formatted_json_test.cpp | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/source/test/formatted_json_test.cpp b/source/test/formatted_json_test.cpp new file mode 100644 index 0000000..a2af0c5 --- /dev/null +++ b/source/test/formatted_json_test.cpp @@ -0,0 +1,371 @@ +#include "StarFormattedJson.hpp" +#include "StarJsonPath.hpp" + +#include "gtest/gtest.h" + +using namespace Star; + +TEST(FormattedJsonTest, JsonInterop) { + Json array1 = JsonArray{1, 2, 3, 4}; + Json array2 = JsonArray{4, 3, 2, 1}; + FormattedJson farray1 = array1; + FormattedJson farray2 = array2; + + EXPECT_EQ(farray1.toJson(), array1); + EXPECT_EQ(farray2.toJson(), array2); + EXPECT_NE(farray1.toJson(), array2); + EXPECT_NE(farray2.toJson(), array1); +} + +TEST(FormattedJsonTest, Parsing) { + FormattedJson json1 = FormattedJson::parse(R"JSON( + { + "foo": "bar", + "hello" : "world", + "abc" :123 + // Comment + ,"wat": { + "thing": [ + 49, + 27] + } + } +)JSON"); + FormattedJson::ElementList expectedElements = { + WhitespaceElement{"\n "}, + ObjectKeyElement{"foo"}, + ColonElement{}, + WhitespaceElement{" "}, + ValueElement{Json{"bar"}}, + CommaElement{}, + WhitespaceElement{"\n "}, + ObjectKeyElement{"hello"}, + WhitespaceElement{" "}, + ColonElement{}, + WhitespaceElement{" "}, + ValueElement{Json{"world"}}, + CommaElement{}, + WhitespaceElement{"\n "}, + ObjectKeyElement{"abc"}, + WhitespaceElement{" "}, + ColonElement{}, + ValueElement{Json{123}}, + WhitespaceElement{"\n // Comment\n "}, + CommaElement{}, + ObjectKeyElement{"wat"}, + ColonElement{}, + WhitespaceElement{" "}, + ValueElement{Json{JsonObject{{"thing", JsonArray{49, 27}}}}}, + WhitespaceElement{"\n "} + }; + EXPECT_EQ(json1.elements(), expectedElements); + EXPECT_EQ(json1.get("foo"), FormattedJson{"bar"}); + EXPECT_EQ(json1.get("abc"), FormattedJson{123}); + EXPECT_EQ(json1.get("wat").get("thing").get(1), FormattedJson{27}); + EXPECT_NE(json1.get("wat").get("thing").get(0), FormattedJson{66}); + + ASSERT_THROW(FormattedJson::parse(" "), JsonParsingException); + ASSERT_THROW(FormattedJson::parse("/* */"), JsonParsingException); + ASSERT_THROW(FormattedJson::parse("x"), JsonParsingException); + ASSERT_THROW(FormattedJson::parseJson("123"), JsonParsingException); + ASSERT_THROW(FormattedJson::parseJson("\"foo\""), JsonParsingException); + EXPECT_TRUE(FormattedJson::parse("123").isType(Json::Type::Int)); + EXPECT_TRUE(FormattedJson::parse("\"foo\"").isType(Json::Type::String)); +} + +List<String> keyOrder(FormattedJson const& json) { + List<String> keys; + for (JsonElement const& elem : json.elements()) { + if (elem.is<ObjectKeyElement>()) + keys.append(elem.get<ObjectKeyElement>().key); + } + return keys; +} + +TEST(FormattedJsonTest, ObjectInsertion) { + FormattedJson json = FormattedJson::ofType(Json::Type::Object); + List<String> expectedKeys; + + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.set("foo", Json{"bar"}); + expectedKeys.append("foo"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.set("baz", Json{"..."}); + expectedKeys.append("baz"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.prepend("hello", Json{"world"}); + expectedKeys.insertAt(0, "hello"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.insertBefore("lala", Json{"alal"}, "foo"); + expectedKeys.insertAt(1, "lala"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.insertAfter("lorem", Json{"ipsum"}, "foo"); + expectedKeys.insertAt(3, "lorem"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + json = json.append("dolor", Json{"sit amet"}); + expectedKeys.append("dolor"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + // If the key already exists, the key order doesn't change. + json = json.set("foo", Json{123}).append("hello", Json{123}).insertAfter("dolor", Json{123}, "baz"); + EXPECT_EQ(keyOrder(json), expectedKeys); + + FormattedJson::ElementList expectedElements = {ObjectKeyElement{"hello"}, + ColonElement{}, + ValueElement{Json{123}}, + CommaElement{}, + ObjectKeyElement{"lala"}, + ColonElement{}, + ValueElement{Json{"alal"}}, + CommaElement{}, + ObjectKeyElement{"foo"}, + ColonElement{}, + ValueElement{Json{123}}, + CommaElement{}, + ObjectKeyElement{"lorem"}, + ColonElement{}, + ValueElement{Json{"ipsum"}}, + CommaElement{}, + ObjectKeyElement{"baz"}, + ColonElement{}, + ValueElement{Json{"..."}}, + CommaElement{}, + ObjectKeyElement{"dolor"}, + ColonElement{}, + ValueElement{Json{123}}}; + EXPECT_EQ(json.elements(), expectedElements); + + FormattedJson emptyObject = FormattedJson::ofType(Json::Type::Object); + ASSERT_THROW(emptyObject.insertBefore("foo", Json{}, "bar"), JsonException); + ASSERT_THROW(emptyObject.insertAfter("foo", Json{}, "bar"), JsonException); + ASSERT_THROW(FormattedJson::ofType(Json::Type::Array).set("foo", Json{}), JsonException); +} + +TEST(FormattedJsonTest, ObjectInsertionWithWhitespace) { + FormattedJson json = FormattedJson::parse(" { \"foo\": 123 } "); + json = json.append("hello", Json{"world"}); + json = json.prepend("lorem", Json{"ipsum"}); + EXPECT_EQ(json.repr(), + R"JSON({ "lorem": "ipsum", "foo": 123, "hello": "world" })JSON"); +} + +TEST(FormattedJsonTest, ArrayInsertion) { + FormattedJson json = FormattedJson::parse(R"JSON([ + 12, + 34 + ])JSON"); + json = json.insert(1, Json{23}); + json = json.append(Json{45}); + json = json.set(0, Json{"01"}); + json = json.insert(0, Json{0}); + char const* expected = R"JSON([ + 0, + "01", + 23, + 34, + 45 + ])JSON"; + EXPECT_EQ(json.repr(), expected); + + FormattedJson emptyArray = FormattedJson::ofType(Json::Type::Array); + EXPECT_EQ(emptyArray.insert(0, Json{}).size(), 1u); + ASSERT_THROW(emptyArray.insert(1, Json{}), JsonException); + ASSERT_THROW(FormattedJson::ofType(Json::Type::Object).insert(0, Json{}), JsonException); +} + +TEST(FormattedJsonTest, ObjectErase) { + FormattedJson json = FormattedJson::parse(R"JSON({ + "zzz": 123, + "mmm": 456, + "aaa": 789 + })JSON"); + json = json.eraseKey("mmm"); + char const* expected = R"JSON({ + "zzz": 123, + "aaa": 789 + })JSON"; + EXPECT_EQ(json.repr(), expected); + + FormattedJson jsonNoZ = json.eraseKey("zzz"); + expected = R"JSON({ + "aaa": 789 + })JSON"; + EXPECT_EQ(jsonNoZ.repr(), expected); + + FormattedJson jsonNoA = json.eraseKey("aaa"); + expected = R"JSON({ + "zzz": 123 + })JSON"; + EXPECT_EQ(jsonNoA.repr(), expected); + + ASSERT_EQ(json.eraseKey("bbb"), json); + ASSERT_THROW(FormattedJson::ofType(Json::Type::Array).eraseKey("foo"), JsonException); +} + +TEST(FormattedJsonTest, ArrayErase) { + FormattedJson json = FormattedJson::parse("[123, 456, 789]"); + EXPECT_EQ(json.eraseIndex(0).repr(), "[456, 789]"); + EXPECT_EQ(json.eraseIndex(1).repr(), "[123, 789]"); + EXPECT_EQ(json.eraseIndex(2).repr(), "[123, 456]"); + EXPECT_EQ(json.eraseIndex(0).eraseIndex(0).repr(), "[789]"); + EXPECT_EQ(json.eraseIndex(0).eraseIndex(0).eraseIndex(0).repr(), "[]"); + + ASSERT_THROW(FormattedJson::ofType(Json::Type::Object).eraseIndex(0), JsonException); +} + +TEST(FormattedJsonTest, CommentPreservation) { + FormattedJson json = FormattedJson::parse(R"JSON({ + // This is a comment + "hello": 1, + "world": 2 + })JSON"); + json = json.insertBefore("goodbye", Json{1}, "world"); + json = json.eraseKey("hello"); + char const* expected = R"JSON({ + // This is a comment + "goodbye": 1, + "world": 2 + })JSON"; + EXPECT_EQ(json.repr(), expected); +} + +TEST(FormattedJsonTest, StylePreservation) { + FormattedJson json = FormattedJson::parse(R"JSON({ + + "hello" : 1234 + + })JSON"); + json = json.append("world", Json{5678}); + char const* expected = R"JSON({ + + "hello" : 1234, + + "world" : 5678 + + })JSON"; + EXPECT_EQ(json.repr(), expected); +} + +TEST(FormattedJsonTest, Queries) { + FormattedJson json0 = FormattedJson::parse("[]"); + FormattedJson json1 = FormattedJson::parse("{\"a\":1}"); + FormattedJson json2 = FormattedJson::parse("[1,2]"); + FormattedJson json3 = FormattedJson::parse(R"({"a":1,"b":2,"c":3})"); + + EXPECT_EQ(json0.size(), 0u); + EXPECT_EQ(json1.size(), 1u); + EXPECT_EQ(json2.size(), 2u); + EXPECT_EQ(json3.size(), 3u); + + EXPECT_TRUE(json1.contains("a")); + EXPECT_FALSE(json1.contains("b")); + EXPECT_TRUE(json3.contains("c")); + EXPECT_TRUE(json3.contains("b")); + + ASSERT_THROW(FormattedJson::parse("123").size(), JsonException); + ASSERT_THROW(json2.contains("1"), JsonException); +} + +TEST(FormattedJsonTest, Types) { + FormattedJson jsonNull = Json{}; + FormattedJson jsonBool = Json{true}; + FormattedJson jsonInt = Json{1}; + FormattedJson jsonFloat = Json{2.0}; + FormattedJson jsonString = Json{"foo"}; + FormattedJson jsonArray = Json::ofType(Json::Type::Array); + FormattedJson jsonObject = Json::ofType(Json::Type::Object); + + EXPECT_EQ(jsonNull.type(), Json::Type::Null); + EXPECT_TRUE(jsonNull.isType(Json::Type::Null)); + EXPECT_EQ(jsonNull.typeName(), "null"); + + EXPECT_EQ(jsonBool.type(), Json::Type::Bool); + EXPECT_TRUE(jsonBool.isType(Json::Type::Bool)); + EXPECT_EQ(jsonBool.typeName(), "bool"); + + EXPECT_EQ(jsonInt.type(), Json::Type::Int); + EXPECT_TRUE(jsonInt.isType(Json::Type::Int)); + EXPECT_EQ(jsonInt.typeName(), "int"); + + EXPECT_EQ(jsonFloat.type(), Json::Type::Float); + EXPECT_TRUE(jsonFloat.isType(Json::Type::Float)); + EXPECT_EQ(jsonFloat.typeName(), "float"); + + EXPECT_EQ(jsonString.type(), Json::Type::String); + EXPECT_TRUE(jsonString.isType(Json::Type::String)); + EXPECT_EQ(jsonString.typeName(), "string"); + + EXPECT_EQ(jsonArray.type(), Json::Type::Array); + EXPECT_TRUE(jsonArray.isType(Json::Type::Array)); + EXPECT_EQ(jsonArray.typeName(), "array"); + + EXPECT_EQ(jsonObject.type(), Json::Type::Object); + EXPECT_TRUE(jsonObject.isType(Json::Type::Object)); + EXPECT_EQ(jsonObject.typeName(), "object"); +} + +TEST(FormattedJsonTest, JsonPath) { + FormattedJson json = FormattedJson::parse(R"JSON({ + "foo": { + "bar": [ + 12, + { + "hello": "world" + }, + 45 + ] + }, + "baz": [{"a":1}, {"a":2}, {"a":3}] + })JSON"); + + FormattedJson expectedHelloWorld = Json{JsonObject{{"hello", "world"}}}; + EXPECT_EQ(JsonPath::Pointer("/foo/bar/1").get(json), expectedHelloWorld); + EXPECT_EQ(JsonPath::QueryPath("foo.bar[1]").get(json), expectedHelloWorld); + EXPECT_EQ(JsonPath::Pointer("/baz/0/a").get(json), FormattedJson{Json{1}}); + EXPECT_EQ(JsonPath::QueryPath("baz[0].a").get(json), FormattedJson{Json{1}}); + + json = JsonPath::Pointer("/baz/0/a").set(json, FormattedJson{Json{0}}); + json = JsonPath::QueryPath("baz[1].a").set(json, FormattedJson{Json{4}}); + + json = JsonPath::Pointer("/baz/1").add(json, FormattedJson::parse("{\"b\":1}")); + json = JsonPath::QueryPath("baz[1]").add(json, FormattedJson::parse("{\"c\":0.5}")); + + EXPECT_EQ(json.get("baz").repr(), + R"([{"a":0},{"c":0.5},{"b":1}, {"a":4}, {"a":3}])"); + + json = JsonPath::Pointer("/plz").set(json, FormattedJson{JsonArray{}}); + json = JsonPath::Pointer("/plz/-").set(json, FormattedJson{Json{"thx"}}); + json = JsonPath::Pointer("/plz/-").add(json, FormattedJson{Json{"bye"}}); + FormattedJson expectedThxBye = Json{JsonArray{"thx", "bye"}}; + EXPECT_EQ(json.get("plz"), expectedThxBye); + + // Set and add are almost the same, but: + // Set 0 => replaces the first array element + json = JsonPath::Pointer("/plz/0").set(json, FormattedJson{Json{"kthx"}}); + // Add 0 => inserts a new element at the beginning + json = JsonPath::Pointer("/plz/0").add(json, FormattedJson{Json{"kbye"}}); + FormattedJson expectedKByeKThxBye = Json{JsonArray{"kbye", "kthx", "bye"}}; + EXPECT_EQ(json.get("plz"), expectedKByeKThxBye); + + json = JsonPath::Pointer("/foo/bar/1").remove(json); + FormattedJson expectedBar = Json{JsonArray{12, 45}}; + EXPECT_EQ(JsonPath::Pointer("/foo/bar").get(json), expectedBar); + json = JsonPath::QueryPath("foo.bar[1]").remove(json); + EXPECT_EQ(JsonPath::QueryPath("foo.bar").get(json).toJson(), JsonArray{12}); +} + +TEST(FormattedJsonTest, NumberFormatPreservation) { + EXPECT_EQ(FormattedJson::parse("1.0").repr(), "1.0"); + EXPECT_EQ(FormattedJson::parse("1").repr(), "1"); + EXPECT_EQ(FormattedJson::parse("-0").repr(), "-0"); + EXPECT_EQ(FormattedJson::parse("0").repr(), "0"); + + EXPECT_EQ(FormattedJson::parseJson("[-0.0,1.0,-0]").repr(), "[-0.0,1.0,-0]"); + EXPECT_EQ(FormattedJson::parseJson("[1,0]").repr(), "[1,0]"); +} |