Add JSON tests for unicode, all types, and conformance to ECMA-262/ECMA-404

Also avoid using toStyledString
This commit is contained in:
Alex Beregszaszi 2021-09-15 19:06:35 +01:00
parent 2c3322cbf6
commit 69e9531181
2 changed files with 90 additions and 11 deletions

View File

@ -63,8 +63,8 @@ public:
BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation,
"Expected:\n" << expectedDocumentation.toStyledString() <<
"\n but got:\n" << generatedDocumentation.toStyledString()
"Expected:\n" << util::jsonPrettyPrint(expectedDocumentation) <<
"\n but got:\n" << util::jsonPrettyPrint(generatedDocumentation)
);
}
@ -2089,8 +2089,8 @@ BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex)
BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation,
"Expected:\n" << expectedDocumentation.toStyledString() <<
"\n but got:\n" << generatedDocumentation.toStyledString()
"Expected:\n" << util::jsonPrettyPrint(expectedDocumentation) <<
"\n but got:\n" << util::jsonPrettyPrint(generatedDocumentation)
);
}

View File

@ -33,6 +33,48 @@ namespace solidity::util::test
BOOST_AUTO_TEST_SUITE(JsonTest, *boost::unit_test::label("nooptions"))
BOOST_AUTO_TEST_CASE(json_types)
{
auto check = [](Json::Value value, string const& expectation) {
BOOST_CHECK(jsonCompactPrint(value) == expectation);
};
Json::Value value;
BOOST_CHECK(value.empty());
value = {};
BOOST_CHECK(value.empty());
value = Json::Value();
BOOST_CHECK(value.empty());
value = Json::nullValue;
BOOST_CHECK(value.empty());
check(value, "null");
check({}, "null");
check(Json::Value(), "null");
check(Json::nullValue, "null");
check(Json::objectValue, "{}");
check(Json::arrayValue, "[]");
check(Json::UInt(1), "1");
check(Json::UInt(-1), "4294967295");
check(Json::UInt64(1), "1");
check(Json::UInt64(-1), "18446744073709551615");
check(Json::LargestUInt(1), "1");
check(Json::LargestUInt(-1), "18446744073709551615");
check(Json::LargestUInt(0xffffffff), "4294967295");
check(Json::Value("test"), "\"test\"");
check("test", "\"test\"");
check(true, "true");
value = Json::objectValue;
value["key"] = "value";
check(value, "{\"key\":\"value\"}");
value = Json::arrayValue;
value.append(1);
value.append(2);
check(value, "[1,2]");
}
BOOST_AUTO_TEST_CASE(json_pretty_print)
{
Json::Value json;
@ -43,6 +85,8 @@ BOOST_AUTO_TEST_CASE(json_pretty_print)
json["1"] = 1;
json["2"] = "2";
json["3"] = jsonChild;
json["4"] = "ऑ ऒ ओ औ क ख";
json["5"] = "\xff";
BOOST_CHECK(
"{\n"
@ -52,7 +96,9 @@ BOOST_AUTO_TEST_CASE(json_pretty_print)
" {\n"
" \"3.1\": \"3.1\",\n"
" \"3.2\": 2\n"
" }\n"
" },\n"
" \"4\": \"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\n"
" \"5\": \"\\ufffd\"\n"
"}" == jsonPrettyPrint(json));
}
@ -66,26 +112,32 @@ BOOST_AUTO_TEST_CASE(json_compact_print)
json["1"] = 1;
json["2"] = "2";
json["3"] = jsonChild;
json["4"] = "ऑ ऒ ओ औ क ख";
json["5"] = "\xff";
BOOST_CHECK("{\"1\":1,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":2}}" == jsonCompactPrint(json));
BOOST_CHECK("{\"1\":1,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":2},\"4\":\"\\u0911 \\u0912 \\u0913 \\u0914 \\u0915 \\u0916\",\"5\":\"\\ufffd\"}" == jsonCompactPrint(json));
}
BOOST_AUTO_TEST_CASE(parse_json_strict)
{
// In this test we check conformance against JSON.parse (https://tc39.es/ecma262/multipage/structured-data.html#sec-json.parse)
// and ECMA-404 (https://www.ecma-international.org/publications-and-standards/standards/ecma-404/)
Json::Value json;
std::string errors;
// just parse a valid json input
// Just parse a valid json input
BOOST_CHECK(jsonParseStrict("{\"1\":1,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":2}}", json, &errors));
BOOST_CHECK(json["1"] == 1);
BOOST_CHECK(json["2"] == "2");
BOOST_CHECK(json["3"]["3.1"] == "3.1");
BOOST_CHECK(json["3"]["3.2"] == 2);
// trailing garbage is not allowed in strict-mode
// Trailing garbage is not allowed in ECMA-262
BOOST_CHECK(!jsonParseStrict("{\"1\":2,\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":3}}}}}}}}}}", json, &errors));
// comments are allowed in strict-mode? - that's strange...
// Comments are not allowed in ECMA-262
// ... but JSONCPP allows them
BOOST_CHECK(jsonParseStrict(
"{\"1\":3, // awesome comment\n\"2\":\"2\",\"3\":{\"3.1\":\"3.1\",\"3.2\":5}}", json, &errors
));
@ -94,15 +146,42 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
BOOST_CHECK(json["3"]["3.1"] == "3.1");
BOOST_CHECK(json["3"]["3.2"] == 5);
// root element can only be object or array
// According to ECMA-404 object, array, number, string, true, false, null are allowed
// ... but JSONCPP disallows value types
BOOST_CHECK(jsonParseStrict("[]", json, &errors));
BOOST_CHECK(json.isArray());
BOOST_CHECK(jsonParseStrict("{}", json, &errors));
BOOST_CHECK(json.isObject());
BOOST_CHECK(!jsonParseStrict("1", json, &errors));
// BOOST_CHECK(json.isNumeric());
BOOST_CHECK(!jsonParseStrict("\"hello\"", json, &errors));
// BOOST_CHECK(json.isString());
BOOST_CHECK(!jsonParseStrict("true", json, &errors));
// BOOST_CHECK(json.isBool());
BOOST_CHECK(!jsonParseStrict("null", json, &errors));
// BOOST_CHECK(json.isNull());
// non-UTF-8 escapes allowed??
// Single quotes are also disallowed by ECMA-404
BOOST_CHECK(!jsonParseStrict("'hello'", json, &errors));
// BOOST_CHECK(json.isString());
// Only string keys in objects are allowed in ECMA-404
BOOST_CHECK(!jsonParseStrict("{ 42: \"hello\" }", json, &errors));
// According to ECMA-404 hex escape sequences are not allowed, only unicode (\uNNNN) and
// a few control characters (\b, \f, \n, \r, \t)
//
// More lenient parsers allow hex escapes as long as they translate to a valid UTF-8 encoding.
//
// ... but JSONCPP allows any hex escapes
BOOST_CHECK(jsonParseStrict("[ \"\x80\xec\x80\" ]", json, &errors));
BOOST_CHECK(json.isArray());
BOOST_CHECK(json[0] == "\x80\xec\x80");
// This would be valid more lenient parsers.
BOOST_CHECK(jsonParseStrict("[ \"\xF0\x9F\x98\x8A\" ]", json, &errors));
BOOST_CHECK(json.isArray());
BOOST_CHECK(json[0] == "😊");
}
BOOST_AUTO_TEST_SUITE_END()