Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/test/formatted_json_test.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/test/formatted_json_test.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/test/formatted_json_test.cpp')
-rw-r--r--source/test/formatted_json_test.cpp371
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]");
+}