Riyyi
2 years ago
1 changed files with 570 additions and 0 deletions
@ -0,0 +1,570 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: MIT |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <cstddef> // nullptr_t |
||||||
|
#include <cstdint> // uint32_t |
||||||
|
#include <functional> // function |
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <unordered_map> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "macro.h" |
||||||
|
#include "testcase.h" |
||||||
|
#include "testsuite.h" |
||||||
|
#include "util/json/array.h" |
||||||
|
#include "util/json/job.h" |
||||||
|
#include "util/json/lexer.h" |
||||||
|
#include "util/json/parser.h" |
||||||
|
#include "util/json/serializer.h" |
||||||
|
#include "util/json/value.h" |
||||||
|
|
||||||
|
#define DONT_PRINT_PARSER_ERRORS |
||||||
|
|
||||||
|
#ifndef DONT_PRINT_PARSER_ERRORS |
||||||
|
#define EXEC(x) x |
||||||
|
#else |
||||||
|
#define EXEC(x) \ |
||||||
|
stdout = Test::TestSuite::the().outputNull(); \
|
||||||
|
x; \
|
||||||
|
stdout = Test::TestSuite::the().outputStd(); |
||||||
|
#endif |
||||||
|
|
||||||
|
std::vector<Json::Token> lex(const std::string& input) |
||||||
|
{ |
||||||
|
EXEC( |
||||||
|
Json::Job job(input); |
||||||
|
Json::Lexer lexer(&job); |
||||||
|
lexer.analyze();); |
||||||
|
return *job.tokens(); |
||||||
|
} |
||||||
|
|
||||||
|
Json::Value parse(const std::string& input) |
||||||
|
{ |
||||||
|
EXEC( |
||||||
|
Json::Job job(input); |
||||||
|
Json::Lexer lexer(&job); |
||||||
|
lexer.analyze();); |
||||||
|
|
||||||
|
if (!job.success()) { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
EXEC( |
||||||
|
Json::Parser parser(&job); |
||||||
|
Json::Value json = parser.parse();); |
||||||
|
|
||||||
|
if (!job.success()) { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
return json; |
||||||
|
} |
||||||
|
|
||||||
|
std::string serialize(const std::string& input, uint32_t indent = 0) |
||||||
|
{ |
||||||
|
EXEC( |
||||||
|
auto json = Json::Value::parse(input);); |
||||||
|
return json.dump(indent); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
TEST_CASE(JsonLexer) |
||||||
|
{ |
||||||
|
std::vector<Json::Token> tokens; |
||||||
|
|
||||||
|
// Literal
|
||||||
|
|
||||||
|
tokens = lex("true"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "true"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::Literal); |
||||||
|
|
||||||
|
tokens = lex("false"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "false"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::Literal); |
||||||
|
|
||||||
|
tokens = lex("null"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "null"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::Literal); |
||||||
|
|
||||||
|
// Number
|
||||||
|
|
||||||
|
tokens = lex("3.14"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "3.14"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::Number); |
||||||
|
|
||||||
|
tokens = lex("-3.14e+2"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "-3.14e+2"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::Number); |
||||||
|
|
||||||
|
tokens = lex("+3.14"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "+"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::None); |
||||||
|
|
||||||
|
// String
|
||||||
|
|
||||||
|
tokens = lex(R"("a string")"); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "a string"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::String); |
||||||
|
|
||||||
|
tokens = lex(R"("a string""another string")"); |
||||||
|
EXPECT_EQ(tokens.size(), 2); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "a string"); |
||||||
|
EXPECT_EQ(tokens[1].symbol, "another string"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::String); |
||||||
|
|
||||||
|
tokens = lex("\"a string\nwill break on the newline symbol\""); |
||||||
|
EXPECT_EQ(tokens.size(), 1); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "a string"); |
||||||
|
EXPECT(tokens[0].type == Json::Token::Type::String); |
||||||
|
|
||||||
|
// Array
|
||||||
|
|
||||||
|
tokens = lex("[]"); |
||||||
|
EXPECT_EQ(tokens.size(), 2); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "["); |
||||||
|
EXPECT_EQ(tokens[1].symbol, "]"); |
||||||
|
|
||||||
|
tokens = lex("[\n\n\n]"); |
||||||
|
EXPECT_EQ(tokens.size(), 2); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "["); |
||||||
|
EXPECT_EQ(tokens[1].symbol, "]"); |
||||||
|
|
||||||
|
// Object
|
||||||
|
|
||||||
|
tokens = lex("{}"); |
||||||
|
EXPECT_EQ(tokens.size(), 2); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "{"); |
||||||
|
EXPECT_EQ(tokens[1].symbol, "}"); |
||||||
|
|
||||||
|
tokens = lex("{\n\n\n}"); |
||||||
|
EXPECT_EQ(tokens.size(), 2); |
||||||
|
EXPECT_EQ(tokens[0].symbol, "{"); |
||||||
|
EXPECT_EQ(tokens[1].symbol, "}"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE(JsonParser) |
||||||
|
{ |
||||||
|
Json::Value json; |
||||||
|
|
||||||
|
json = parse("null"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("true"); |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Bool); |
||||||
|
|
||||||
|
json = parse("false"); |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Bool); |
||||||
|
|
||||||
|
json = parse("3.14"); |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Number); |
||||||
|
|
||||||
|
json = parse(R"("a string")"); |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::String); |
||||||
|
|
||||||
|
// Array
|
||||||
|
|
||||||
|
json = parse("["); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("[ 123"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("[ 123,"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("[ 123, ]"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("[ 123 456 ]"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("[]"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
json = parse(R"([ "element", 3.14 ])"); |
||||||
|
EXPECT_EQ(json.size(), 2); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
// Object
|
||||||
|
|
||||||
|
json = parse("{"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name")"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name":)"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name":,)"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name":"value")"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name":"value",)"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name":"value", })"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ "name" "value" })"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse(R"({ 123 })"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("{}"); |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Object); |
||||||
|
|
||||||
|
json = parse(R"({ "name": "value", "name2": 3.14 })"); |
||||||
|
EXPECT_EQ(json.size(), 2); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Object); |
||||||
|
|
||||||
|
// Multiple root elements
|
||||||
|
|
||||||
|
json = parse("54 false"); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("3.14, 666"); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = parse("true\nfalse"); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE(JsonToJsonValue) |
||||||
|
{ |
||||||
|
Json::Value json; |
||||||
|
|
||||||
|
json = {}; |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = nullptr; |
||||||
|
EXPECT_EQ(json.size(), 0); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Null); |
||||||
|
|
||||||
|
json = true; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Bool); |
||||||
|
|
||||||
|
json = false; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Bool); |
||||||
|
|
||||||
|
json = 666; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Number); |
||||||
|
|
||||||
|
json = 3.14; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Number); |
||||||
|
|
||||||
|
const char* characters = "my string"; |
||||||
|
json = characters; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::String); |
||||||
|
|
||||||
|
std::string string = "my string"; |
||||||
|
json = string; |
||||||
|
EXPECT_EQ(json.size(), 1); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::String); |
||||||
|
|
||||||
|
// Nested Array with multiple types
|
||||||
|
json = { "element", 3.14, true, nullptr, { "nested element", { "more nesting", { 1, 2, 3, "yes" } } } }; |
||||||
|
EXPECT_EQ(json.size(), 5); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
// Nested Object with multiple types
|
||||||
|
json = { { "name", "value" }, { "name2", 3.14 }, { "name3", true }, { "name4", nullptr }, { "name5", { { "nested name", "value" } } } }; |
||||||
|
EXPECT_EQ(json.size(), 5); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Object); |
||||||
|
|
||||||
|
// Array with singular type
|
||||||
|
std::vector<std::string> vector = { "element", "element2", "element3" }; |
||||||
|
json = vector; |
||||||
|
EXPECT_EQ(json.size(), 3); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
// Object with singular type
|
||||||
|
std::map<std::string, std::string> map = { { "name", "value" }, { "name2", "value2" } }; |
||||||
|
json = map; |
||||||
|
EXPECT_EQ(json.size(), 2); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Object); |
||||||
|
|
||||||
|
// Object with singular type
|
||||||
|
std::unordered_map<std::string, std::string> unorderedMap = { { "name", "value" }, { "name2", "value2" } }; |
||||||
|
json = unorderedMap; |
||||||
|
EXPECT_EQ(json.size(), 2); |
||||||
|
EXPECT_EQ(json.type(), Json::Value::Type::Object); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE(JsonFromJsonValue) |
||||||
|
{ |
||||||
|
Json::Value json; |
||||||
|
|
||||||
|
json = nullptr; |
||||||
|
EXPECT_EQ(json.get<std::nullptr_t>(), nullptr); |
||||||
|
|
||||||
|
json = true; |
||||||
|
EXPECT_EQ(json.get<bool>(), true); |
||||||
|
|
||||||
|
json = false; |
||||||
|
EXPECT_EQ(json.get<bool>(), false); |
||||||
|
|
||||||
|
json = 666; |
||||||
|
EXPECT_EQ(json.get<int>(), 666); |
||||||
|
|
||||||
|
json = 3.14; |
||||||
|
EXPECT_EQ(json.get<double>(), 3.14); |
||||||
|
|
||||||
|
std::string string; |
||||||
|
json = "my string"; |
||||||
|
json.getTo(string); |
||||||
|
EXPECT_EQ(string, "my string"); |
||||||
|
EXPECT_EQ(json.get<std::string>(), "my string"); |
||||||
|
|
||||||
|
// Array with singular type
|
||||||
|
json = { "element", "element2" }; |
||||||
|
EXPECT_EQ(json[0].get<std::string>(), "element"); |
||||||
|
EXPECT_EQ(json.at(1).get<std::string>(), "element2"); |
||||||
|
auto array = json.get<std::vector<std::string>>(); |
||||||
|
EXPECT_EQ(array.size(), 2); |
||||||
|
EXPECT_EQ(array[0], "element"); |
||||||
|
EXPECT_EQ(array[1], "element2"); |
||||||
|
|
||||||
|
// Array with multiple types
|
||||||
|
json = { "string", 3.14, true, nullptr }; |
||||||
|
EXPECT_EQ(json[0].get<std::string>(), "string"); |
||||||
|
EXPECT_EQ(json.at(1).get<double>(), 3.14); |
||||||
|
EXPECT_EQ(json[2].get<bool>(), true); |
||||||
|
EXPECT_EQ(json[3].get<std::nullptr_t>(), nullptr); |
||||||
|
auto valueArray = json.get<std::vector<Json::Value>>(); |
||||||
|
EXPECT_EQ(valueArray.size(), 4); |
||||||
|
EXPECT_EQ(valueArray[0].get<std::string>(), "string"); |
||||||
|
EXPECT_EQ(valueArray[1].get<double>(), 3.14); |
||||||
|
EXPECT_EQ(valueArray[2].get<bool>(), true); |
||||||
|
EXPECT_EQ(valueArray[3].get<std::nullptr_t>(), nullptr); |
||||||
|
|
||||||
|
// Nested Array with multiple types
|
||||||
|
json = { |
||||||
|
"value", |
||||||
|
{ |
||||||
|
"thing", |
||||||
|
666, |
||||||
|
}, |
||||||
|
{ |
||||||
|
{ |
||||||
|
3.14, |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
EXPECT_EQ(json[0].get<std::string>(), "value"); |
||||||
|
EXPECT_EQ(json.at(1)[0].get<std::string>(), "thing"); |
||||||
|
EXPECT_EQ(json[1].at(1).get<int>(), 666); |
||||||
|
EXPECT_EQ(json[2][0][0].get<double>(), 3.14); |
||||||
|
|
||||||
|
// Object with singular type
|
||||||
|
json = { { "name", "value" }, { "name2", "value2" } }; |
||||||
|
EXPECT_EQ(json["name"].get<std::string>(), "value"); |
||||||
|
EXPECT_EQ(json.at("name2").get<std::string>(), "value2"); |
||||||
|
auto object = json.get<std::map<std::string, std::string>>(); |
||||||
|
EXPECT_EQ(object.size(), 2); |
||||||
|
EXPECT_EQ(object["name"], "value"); |
||||||
|
EXPECT_EQ(object["name2"], "value2"); |
||||||
|
auto unorderedObject = json.get<std::unordered_map<std::string, std::string>>(); |
||||||
|
EXPECT_EQ(unorderedObject.size(), 2); |
||||||
|
EXPECT_EQ(unorderedObject["name"], "value"); |
||||||
|
EXPECT_EQ(unorderedObject["name2"], "value2"); |
||||||
|
|
||||||
|
// Object with multiple types
|
||||||
|
json = { { "name", "value" }, { "name2", 3.14 }, { "name3", true }, { "name4", nullptr } }; |
||||||
|
EXPECT_EQ(json["name"].get<std::string>(), "value"); |
||||||
|
EXPECT_EQ(json.at("name2").get<double>(), 3.14); |
||||||
|
EXPECT_EQ(json["name3"].get<bool>(), true); |
||||||
|
EXPECT_EQ(json["name4"].get<std::nullptr_t>(), nullptr); |
||||||
|
auto valueObject = json.get<std::map<std::string, Json::Value>>(); |
||||||
|
EXPECT_EQ(valueObject.size(), 4); |
||||||
|
EXPECT_EQ(valueObject["name"].get<std::string>(), "value"); |
||||||
|
EXPECT_EQ(valueObject["name2"].get<double>(), 3.14); |
||||||
|
EXPECT_EQ(valueObject["name3"].get<bool>(), true); |
||||||
|
EXPECT_EQ(valueObject["name4"].get<std::nullptr_t>(), nullptr); |
||||||
|
|
||||||
|
// Nested Object with multiple types
|
||||||
|
json = { |
||||||
|
{ |
||||||
|
"name", |
||||||
|
"value", |
||||||
|
}, |
||||||
|
{ |
||||||
|
"nest 1-deep", |
||||||
|
{ { |
||||||
|
"number", |
||||||
|
1, |
||||||
|
} }, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"nest 2-deep", |
||||||
|
{ { |
||||||
|
"nest 1-deep", |
||||||
|
{ { |
||||||
|
"bool", |
||||||
|
true, |
||||||
|
} }, |
||||||
|
} }, |
||||||
|
}, |
||||||
|
}; |
||||||
|
EXPECT_EQ(json["name"].get<std::string>(), "value"); |
||||||
|
EXPECT_EQ(json["nest 1-deep"]["number"].get<int>(), 1); |
||||||
|
EXPECT_EQ(json["nest 2-deep"]["nest 1-deep"]["bool"].get<bool>(), true); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE(JsonImplicitConversion) |
||||||
|
{ |
||||||
|
Json::Value array; |
||||||
|
array[0]; |
||||||
|
EXPECT_EQ(array.type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
Json::Value arrayEmplace; |
||||||
|
arrayEmplace.emplace_back("element"); |
||||||
|
arrayEmplace.emplace_back({ "nested element" }); |
||||||
|
EXPECT_EQ(arrayEmplace.type(), Json::Value::Type::Array); |
||||||
|
EXPECT_EQ(arrayEmplace[1].type(), Json::Value::Type::Array); |
||||||
|
|
||||||
|
Json::Value object; |
||||||
|
object[""]; |
||||||
|
EXPECT_EQ(object.type(), Json::Value::Type::Object); |
||||||
|
|
||||||
|
Json::Value objectEmplace; |
||||||
|
objectEmplace.emplace("name", "value"); |
||||||
|
objectEmplace.emplace("name2", { { "nested name", "value" } }); |
||||||
|
EXPECT_EQ(objectEmplace.type(), Json::Value::Type::Object); |
||||||
|
EXPECT_EQ(objectEmplace["name2"].type(), Json::Value::Type::Object); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE(JsonSerializer) |
||||||
|
{ |
||||||
|
EXPECT_EQ(serialize(""), "null"); |
||||||
|
EXPECT_EQ(serialize("null"), "null"); |
||||||
|
EXPECT_EQ(serialize("true"), "true"); |
||||||
|
EXPECT_EQ(serialize("false"), "false"); |
||||||
|
EXPECT_EQ(serialize("3.14"), "3.14"); |
||||||
|
EXPECT_EQ(serialize(R"("string")"), R"("string")"); |
||||||
|
|
||||||
|
EXPECT_EQ(serialize("\n\n\n"), "null"); |
||||||
|
EXPECT_EQ(serialize("null\n"), "null"); |
||||||
|
EXPECT_EQ(serialize("true\n"), "true"); |
||||||
|
EXPECT_EQ(serialize("false\n"), "false"); |
||||||
|
EXPECT_EQ(serialize("3.14\n"), "3.14"); |
||||||
|
// clang-format off
|
||||||
|
EXPECT_EQ(serialize(R"("string")" "\n"), R"("string")"); |
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
EXPECT_EQ(serialize("[\n\n\n]"), "[]"); |
||||||
|
EXPECT_EQ(serialize("[null]"), "[null]"); |
||||||
|
EXPECT_EQ(serialize("[true]"), "[true]"); |
||||||
|
EXPECT_EQ(serialize("[false]"), "[false]"); |
||||||
|
EXPECT_EQ(serialize("[3.14]"), "[3.14]"); |
||||||
|
EXPECT_EQ(serialize(R"(["string"])"), R"(["string"])"); |
||||||
|
|
||||||
|
EXPECT_EQ(serialize("[\n\n\n]", 4), "[\n]"); |
||||||
|
EXPECT_EQ(serialize("[null]", 4), "[\n null\n]"); |
||||||
|
EXPECT_EQ(serialize("[true]", 4), "[\n true\n]"); |
||||||
|
EXPECT_EQ(serialize("[false]", 4), "[\n false\n]"); |
||||||
|
EXPECT_EQ(serialize("[3.14]", 4), "[\n 3.14\n]"); |
||||||
|
// clang-format off
|
||||||
|
EXPECT_EQ(serialize(R"(["string"])", 4), "[\n " R"("string")" "\n]"); |
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Check for trailing comma on last array element
|
||||||
|
EXPECT_EQ(serialize(R"([1])"), R"([1])"); |
||||||
|
EXPECT_EQ(serialize(R"([1,2])"), R"([1,2])"); |
||||||
|
EXPECT_EQ(serialize(R"([1,2,3])"), R"([1,2,3])"); |
||||||
|
|
||||||
|
// Check for trailing comma on last object member
|
||||||
|
EXPECT_EQ(serialize(R"({"n1":"v1"})"), R"({"n1":"v1"})"); |
||||||
|
EXPECT_EQ(serialize(R"({"n1":"v1", "n2":"v2"})"), R"({"n1":"v1","n2":"v2"})"); |
||||||
|
EXPECT_EQ(serialize(R"({"n1":"v1", "n2":"v2", "n3":"v3"})"), R"({"n1":"v1","n2":"v2","n3":"v3"})"); |
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
EXPECT_EQ(serialize(R"({ |
||||||
|
"object member one": [ |
||||||
|
"array element one" |
||||||
|
], |
||||||
|
"object member two": [ |
||||||
|
"array element one", |
||||||
|
"array element two" |
||||||
|
], |
||||||
|
"object member three": [ |
||||||
|
"array element one", |
||||||
|
2, |
||||||
|
3.0, |
||||||
|
4.56, |
||||||
|
true, |
||||||
|
false, |
||||||
|
null |
||||||
|
], |
||||||
|
"object member four": 3.14, |
||||||
|
"object member five": "value five", |
||||||
|
"object member six": null, |
||||||
|
"object member seven": { "no": 0 } |
||||||
|
})", 4), R"({ |
||||||
|
"object member five": "value five", |
||||||
|
"object member four": 3.14, |
||||||
|
"object member one": [ |
||||||
|
"array element one" |
||||||
|
], |
||||||
|
"object member seven": { |
||||||
|
"no": 0 |
||||||
|
}, |
||||||
|
"object member six": null, |
||||||
|
"object member three": [ |
||||||
|
"array element one", |
||||||
|
2, |
||||||
|
3, |
||||||
|
4.56, |
||||||
|
true, |
||||||
|
false, |
||||||
|
null |
||||||
|
], |
||||||
|
"object member two": [ |
||||||
|
"array element one", |
||||||
|
"array element two" |
||||||
|
] |
||||||
|
})"); |
||||||
|
// clang-format on
|
||||||
|
} |
Loading…
Reference in new issue