From bc1f4f49ee6759c0093e3bf30cf1463b7115a760 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 15 Oct 2019 18:17:51 -0700 Subject: [PATCH 01/13] Fix issues with signed/unsigned overflows --- src/lib_json/json_reader.cpp | 41 +++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 958a39869..02ae8203d 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -11,6 +11,7 @@ #include #endif // if !defined(JSON_IS_AMALGAMATION) #include +#include #include #include #include @@ -1528,15 +1529,35 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (isNegative) ++current; - static constexpr auto positive_threshold = Value::maxLargestUInt / 10; - static constexpr auto positive_last_digit = Value::maxLargestUInt % 10; - static constexpr auto negative_threshold = - Value::LargestUInt(Value::minLargestInt) / 10; - static constexpr auto negative_last_digit = - Value::LargestUInt(Value::minLargestInt) % 10; - - const auto threshold = isNegative ? negative_threshold : positive_threshold; - const auto last_digit = + // We assume we can represent the largest and smallest integer types as + // unsigned integers with separate sign. This is only true if they can fit + // into an unsigned integer. + static_assert(Value::maxLargestInt <= Value::maxLargestUInt); + + // We need to convert minLargestInt into a positive number. The easiest way + // to do this conversion is to assume our "threshold" value of minLargestInt + // divided by 10 can fit in maxLargestInt when absolute valued. This should + // be a safe assumption. + static_assert(Value::minLargestInt <= -Value::maxLargestInt); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt); + + static constexpr Value::LargestUInt positive_threshold = + Value::maxLargestInt / 10; + static constexpr Value::UInt positive_last_digit = Value::maxLargestInt % 10; + + // For the negative values, we have to be more careful. Since typically + // -Value::minLargestInt will cause an overflow, we first divide by 10 and + // then take the inverse. This assumes that minLargestInt is only a single + // power of 10 different in magnitude, which we check above. For the last + // digit, we take the modulus before negating for the same reason. + static const Value::LargestUInt negative_threshold = + Value::LargestUInt(-(Value::minLargestInt / 10)); + static const Value::UInt negative_last_digit = + Value::UInt(-(Value::minLargestInt % 10)); + + const Value::LargestUInt threshold = + isNegative ? negative_threshold : positive_threshold; + const Value::UInt last_digit = isNegative ? negative_last_digit : positive_last_digit; Value::LargestUInt value = 0; @@ -1545,7 +1566,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (c < '0' || c > '9') return decodeDouble(token, decoded); - const auto digit(static_cast(c - '0')); + const Value::UInt digit(static_cast(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If // a) we've only just touched the limit, meaing value == threshold, From 8fb4506a473a06786b5aedd5df8a6c11c07e240d Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 15 Oct 2019 18:23:42 -0700 Subject: [PATCH 02/13] Add tests --- test/data/test_negative_integer_01_64bits.expected | 1 + test/data/test_negative_integer_01_64bits.json | 1 + 2 files changed, 2 insertions(+) create mode 100644 test/data/test_negative_integer_01_64bits.expected create mode 100644 test/data/test_negative_integer_01_64bits.json diff --git a/test/data/test_negative_integer_01_64bits.expected b/test/data/test_negative_integer_01_64bits.expected new file mode 100644 index 000000000..5d6789c18 --- /dev/null +++ b/test/data/test_negative_integer_01_64bits.expected @@ -0,0 +1 @@ +.=-9223372036854775808 \ No newline at end of file diff --git a/test/data/test_negative_integer_01_64bits.json b/test/data/test_negative_integer_01_64bits.json new file mode 100644 index 000000000..9af921bf6 --- /dev/null +++ b/test/data/test_negative_integer_01_64bits.json @@ -0,0 +1 @@ +-9223372036854775808 \ No newline at end of file From 4df31400df1aa18202118062c78e45fae1047743 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 15 Oct 2019 18:26:24 -0700 Subject: [PATCH 03/13] Delete duplicate tests. --- test/data/test_negative_integer_01_64bits.expected | 1 - test/data/test_negative_integer_01_64bits.json | 1 - 2 files changed, 2 deletions(-) delete mode 100644 test/data/test_negative_integer_01_64bits.expected delete mode 100644 test/data/test_negative_integer_01_64bits.json diff --git a/test/data/test_negative_integer_01_64bits.expected b/test/data/test_negative_integer_01_64bits.expected deleted file mode 100644 index 5d6789c18..000000000 --- a/test/data/test_negative_integer_01_64bits.expected +++ /dev/null @@ -1 +0,0 @@ -.=-9223372036854775808 \ No newline at end of file diff --git a/test/data/test_negative_integer_01_64bits.json b/test/data/test_negative_integer_01_64bits.json deleted file mode 100644 index 9af921bf6..000000000 --- a/test/data/test_negative_integer_01_64bits.json +++ /dev/null @@ -1 +0,0 @@ --9223372036854775808 \ No newline at end of file From 74816cef3437ef9595682136f59e2dbdf7fde75b Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 15 Oct 2019 18:49:09 -0700 Subject: [PATCH 04/13] In progress --- src/jsontestrunner/main.cpp | 69 +++++++++++++++++++++++++++--------- src/lib_json/json_reader.cpp | 17 ++++++--- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp index cb9db66cd..53b324c93 100644 --- a/src/jsontestrunner/main.cpp +++ b/src/jsontestrunner/main.cpp @@ -16,6 +16,7 @@ #include // sort #include #include +#include #include struct Options { @@ -126,15 +127,39 @@ static int parseAndSaveValueTree(const Json::String& input, const Json::String& actual, const Json::String& kind, const Json::Features& features, bool parseOnly, - Json::Value* root) { - Json::Reader reader(features); - bool parsingSuccessful = - reader.parse(input.data(), input.data() + input.size(), *root); - if (!parsingSuccessful) { - printf("Failed to parse %s file: \n%s\n", kind.c_str(), - reader.getFormattedErrorMessages().c_str()); - return 1; + Json::Value* root, bool use_legacy) { + if (!use_legacy) { + Json::CharReaderBuilder builder; + + builder.settings_["allowComments"] = features.allowComments_; + builder.settings_["strictRoot"] = features.strictRoot_; + builder.settings_["allowDroppedNullPlaceholders"] = + features.allowDroppedNullPlaceholders_; + builder.settings_["allowNumericKeys"] = features.allowNumericKeys_; + + std::unique_ptr reader(builder.newCharReader()); + Json::String errors; + const bool parsingSuccessful = + reader->parse(input.data(), input.data() + input.size(), root, &errors); + + if (!parsingSuccessful) { + printf("Failed to parse %s file: \n%s\n", kind.c_str(), errors.c_str()); + return 1; + } + + // We may instead check the legacy implementation (to ensure it doesn't + // randomly get broken). + } else { + Json::Reader reader(features); + const bool parsingSuccessful = + reader.parse(input.data(), input.data() + input.size(), *root); + if (!parsingSuccessful) { + printf("Failed to parse %s file: \n%s\n", kind.c_str(), + reader.getFormattedErrorMessages().c_str()); + return 1; + } } + if (!parseOnly) { FILE* factual = fopen(actual.c_str(), "wt"); if (!factual) { @@ -240,7 +265,8 @@ static int parseCommandLine(int argc, const char* argv[], Options* opts) { opts->path = argv[index]; return 0; } -static int runTest(Options const& opts) { + +static int runTest(Options const& opts, bool use_legacy) { int exitCode = 0; Json::String input = readInputTestFile(opts.path.c_str()); @@ -262,23 +288,25 @@ static int runTest(Options const& opts) { Json::Value root; exitCode = parseAndSaveValueTree(input, actualPath, "input", opts.features, - opts.parseOnly, &root); + opts.parseOnly, &root, use_legacy); if (exitCode || opts.parseOnly) { return exitCode; } + Json::String rewrite; exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite); if (exitCode) { return exitCode; } + Json::Value rewriteRoot; exitCode = parseAndSaveValueTree(rewrite, rewriteActualPath, "rewrite", - opts.features, opts.parseOnly, &rewriteRoot); - if (exitCode) { - return exitCode; - } - return 0; + opts.features, opts.parseOnly, &rewriteRoot, + use_legacy); + + return exitCode; } + int main(int argc, const char* argv[]) { Options opts; try { @@ -287,7 +315,16 @@ int main(int argc, const char* argv[]) { printf("Failed to parse command-line."); return exitCode; } - return runTest(opts); + + // TODO(baylesj): replace this with proper calls to both. Right now + // we only check the legacy if the modern one is not broken. + const int modern_return_code = runTest(opts, false); + const int legacy_return_code = runTest(opts, true); + if (modern_return_code) { + return modern_return_code; + } else { + return legacy_return_code; + } } catch (const std::exception& e) { printf("Unhandled exception:\n%s\n", e.what()); return 1; diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 02ae8203d..7a6640e39 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -11,7 +11,6 @@ #include #endif // if !defined(JSON_IS_AMALGAMATION) #include -#include #include #include #include @@ -1529,6 +1528,11 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (isNegative) ++current; + if (isNegative) { + decoded = Value::LargestInt(1337); + return true; + } + // We assume we can represent the largest and smallest integer types as // unsigned integers with separate sign. This is only true if they can fit // into an unsigned integer. @@ -1580,12 +1584,15 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { value = value * 10 + digit; } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxLargestInt)) + if (isNegative) { + // We use the same magnitude assumption here, just in case. + const Value::UInt last_digit = value % 10; + decoded = -Value::LargestInt(value / 10) - last_digit; + } else if (value > Value::LargestUInt(Value::maxLargestInt)) { decoded = Value::LargestInt(value); - else + } else { decoded = value; + } return true; } From 9050dc3d3b6437952045d72fb00324bc08827e90 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 15 Oct 2019 19:18:22 -0700 Subject: [PATCH 05/13] Finish fixing up json reader --- src/jsontestrunner/main.cpp | 2 +- src/lib_json/json_reader.cpp | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp index 53b324c93..27471fff1 100644 --- a/src/jsontestrunner/main.cpp +++ b/src/jsontestrunner/main.cpp @@ -318,8 +318,8 @@ int main(int argc, const char* argv[]) { // TODO(baylesj): replace this with proper calls to both. Right now // we only check the legacy if the modern one is not broken. - const int modern_return_code = runTest(opts, false); const int legacy_return_code = runTest(opts, true); + const int modern_return_code = runTest(opts, false); if (modern_return_code) { return modern_return_code; } else { diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 7a6640e39..88b2a8aaf 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1528,11 +1528,6 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (isNegative) ++current; - if (isNegative) { - decoded = Value::LargestInt(1337); - return true; - } - // We assume we can represent the largest and smallest integer types as // unsigned integers with separate sign. This is only true if they can fit // into an unsigned integer. @@ -1546,8 +1541,8 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt); static constexpr Value::LargestUInt positive_threshold = - Value::maxLargestInt / 10; - static constexpr Value::UInt positive_last_digit = Value::maxLargestInt % 10; + Value::maxLargestUInt / 10; + static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10; // For the negative values, we have to be more careful. Since typically // -Value::minLargestInt will cause an overflow, we first divide by 10 and @@ -1587,8 +1582,8 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (isNegative) { // We use the same magnitude assumption here, just in case. const Value::UInt last_digit = value % 10; - decoded = -Value::LargestInt(value / 10) - last_digit; - } else if (value > Value::LargestUInt(Value::maxLargestInt)) { + decoded = -Value::LargestInt(value / 10) * 10 - last_digit; + } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { decoded = Value::LargestInt(value); } else { decoded = value; From 836d954176f88325b82662903e4e365a4ebac03a Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Thu, 17 Oct 2019 10:43:02 -0700 Subject: [PATCH 06/13] Move tests to legacy_ prepend --- src/jsontestrunner/main.cpp | 40 ++++++++++--------- src/lib_json/json_reader.cpp | 6 +-- ...expected => legacy_test_array_01.expected} | 0 ...rray_01.json => legacy_test_array_01.json} | 0 ...expected => legacy_test_array_02.expected} | 0 ...rray_02.json => legacy_test_array_02.json} | 0 ...expected => legacy_test_array_03.expected} | 0 ...rray_03.json => legacy_test_array_03.json} | 0 ...expected => legacy_test_array_04.expected} | 0 ...rray_04.json => legacy_test_array_04.json} | 0 ...expected => legacy_test_array_05.expected} | 0 ...rray_05.json => legacy_test_array_05.json} | 0 ...expected => legacy_test_array_06.expected} | 0 ...rray_06.json => legacy_test_array_06.json} | 0 ...expected => legacy_test_array_07.expected} | 0 ...rray_07.json => legacy_test_array_07.json} | 0 ...expected => legacy_test_basic_01.expected} | 0 ...asic_01.json => legacy_test_basic_01.json} | 0 ...expected => legacy_test_basic_02.expected} | 0 ...asic_02.json => legacy_test_basic_02.json} | 0 ...expected => legacy_test_basic_03.expected} | 0 ...asic_03.json => legacy_test_basic_03.json} | 0 ...expected => legacy_test_basic_04.expected} | 0 ...asic_04.json => legacy_test_basic_04.json} | 0 ...expected => legacy_test_basic_05.expected} | 0 ...asic_05.json => legacy_test_basic_05.json} | 0 ...expected => legacy_test_basic_06.expected} | 0 ...asic_06.json => legacy_test_basic_06.json} | 0 ...expected => legacy_test_basic_07.expected} | 0 ...asic_07.json => legacy_test_basic_07.json} | 0 ...expected => legacy_test_basic_08.expected} | 0 ...asic_08.json => legacy_test_basic_08.json} | 0 ...expected => legacy_test_basic_09.expected} | 0 ...asic_09.json => legacy_test_basic_09.json} | 0 ...pected => legacy_test_comment_00.expected} | 0 ...nt_00.json => legacy_test_comment_00.json} | 0 ...pected => legacy_test_comment_01.expected} | 0 ...nt_01.json => legacy_test_comment_01.json} | 0 ...pected => legacy_test_comment_02.expected} | 0 ...nt_02.json => legacy_test_comment_02.json} | 0 ...pected => legacy_test_complex_01.expected} | 0 ...ex_01.json => legacy_test_complex_01.json} | 0 ...pected => legacy_test_integer_01.expected} | 0 ...er_01.json => legacy_test_integer_01.json} | 0 ...pected => legacy_test_integer_02.expected} | 0 ...er_02.json => legacy_test_integer_02.json} | 0 ...pected => legacy_test_integer_03.expected} | 0 ...er_03.json => legacy_test_integer_03.json} | 0 ...pected => legacy_test_integer_04.expected} | 0 ...er_04.json => legacy_test_integer_04.json} | 0 ...pected => legacy_test_integer_05.expected} | 0 ...er_05.json => legacy_test_integer_05.json} | 0 ...=> legacy_test_integer_06_64bits.expected} | 0 ...son => legacy_test_integer_06_64bits.json} | 0 ...=> legacy_test_integer_07_64bits.expected} | 0 ...son => legacy_test_integer_07_64bits.json} | 0 ...=> legacy_test_integer_08_64bits.expected} | 0 ...son => legacy_test_integer_08_64bits.json} | 0 ...expected => legacy_test_large_01.expected} | 0 ...arge_01.json => legacy_test_large_01.json} | 0 ...xpected => legacy_test_object_01.expected} | 0 ...ect_01.json => legacy_test_object_01.json} | 0 ...xpected => legacy_test_object_02.expected} | 0 ...ect_02.json => legacy_test_object_02.json} | 0 ...xpected => legacy_test_object_03.expected} | 0 ...ect_03.json => legacy_test_object_03.json} | 0 ...xpected => legacy_test_object_04.expected} | 0 ...ect_04.json => legacy_test_object_04.json} | 0 ... legacy_test_preserve_comment_01.expected} | 0 ...n => legacy_test_preserve_comment_01.json} | 0 ....expected => legacy_test_real_01.expected} | 0 ..._real_01.json => legacy_test_real_01.json} | 0 ....expected => legacy_test_real_02.expected} | 0 ..._real_02.json => legacy_test_real_02.json} | 0 ....expected => legacy_test_real_03.expected} | 0 ..._real_03.json => legacy_test_real_03.json} | 0 ....expected => legacy_test_real_04.expected} | 0 ..._real_04.json => legacy_test_real_04.json} | 0 ....expected => legacy_test_real_05.expected} | 0 ..._real_05.json => legacy_test_real_05.json} | 0 ....expected => legacy_test_real_06.expected} | 0 ..._real_06.json => legacy_test_real_06.json} | 0 ....expected => legacy_test_real_07.expected} | 0 ..._real_07.json => legacy_test_real_07.json} | 0 ....expected => legacy_test_real_08.expected} | 0 ..._real_08.json => legacy_test_real_08.json} | 0 ....expected => legacy_test_real_09.expected} | 0 ..._real_09.json => legacy_test_real_09.json} | 0 ....expected => legacy_test_real_10.expected} | 0 ..._real_10.json => legacy_test_real_10.json} | 0 ....expected => legacy_test_real_11.expected} | 0 ..._real_11.json => legacy_test_real_11.json} | 0 ....expected => legacy_test_real_12.expected} | 0 ..._real_12.json => legacy_test_real_12.json} | 0 ...xpected => legacy_test_string_01.expected} | 0 ...ing_01.json => legacy_test_string_01.json} | 0 ...xpected => legacy_test_string_02.expected} | 0 ...ing_02.json => legacy_test_string_02.json} | 0 ...xpected => legacy_test_string_03.expected} | 0 ...ing_03.json => legacy_test_string_03.json} | 0 ...xpected => legacy_test_string_04.expected} | 0 ...ing_04.json => legacy_test_string_04.json} | 0 ...xpected => legacy_test_string_05.expected} | 0 ...ing_05.json => legacy_test_string_05.json} | 0 ...=> legacy_test_string_unicode_01.expected} | 0 ...son => legacy_test_string_unicode_01.json} | 0 ...=> legacy_test_string_unicode_02.expected} | 0 ...son => legacy_test_string_unicode_02.json} | 0 ...=> legacy_test_string_unicode_03.expected} | 0 ...son => legacy_test_string_unicode_03.json} | 0 ...=> legacy_test_string_unicode_04.expected} | 0 ...son => legacy_test_string_unicode_04.json} | 0 ...=> legacy_test_string_unicode_05.expected} | 0 ...son => legacy_test_string_unicode_05.json} | 0 114 files changed, 24 insertions(+), 22 deletions(-) rename test/data/{test_array_01.expected => legacy_test_array_01.expected} (100%) rename test/data/{test_array_01.json => legacy_test_array_01.json} (100%) rename test/data/{test_array_02.expected => legacy_test_array_02.expected} (100%) rename test/data/{test_array_02.json => legacy_test_array_02.json} (100%) rename test/data/{test_array_03.expected => legacy_test_array_03.expected} (100%) rename test/data/{test_array_03.json => legacy_test_array_03.json} (100%) rename test/data/{test_array_04.expected => legacy_test_array_04.expected} (100%) rename test/data/{test_array_04.json => legacy_test_array_04.json} (100%) rename test/data/{test_array_05.expected => legacy_test_array_05.expected} (100%) rename test/data/{test_array_05.json => legacy_test_array_05.json} (100%) rename test/data/{test_array_06.expected => legacy_test_array_06.expected} (100%) rename test/data/{test_array_06.json => legacy_test_array_06.json} (100%) rename test/data/{test_array_07.expected => legacy_test_array_07.expected} (100%) rename test/data/{test_array_07.json => legacy_test_array_07.json} (100%) rename test/data/{test_basic_01.expected => legacy_test_basic_01.expected} (100%) rename test/data/{test_basic_01.json => legacy_test_basic_01.json} (100%) rename test/data/{test_basic_02.expected => legacy_test_basic_02.expected} (100%) rename test/data/{test_basic_02.json => legacy_test_basic_02.json} (100%) rename test/data/{test_basic_03.expected => legacy_test_basic_03.expected} (100%) rename test/data/{test_basic_03.json => legacy_test_basic_03.json} (100%) rename test/data/{test_basic_04.expected => legacy_test_basic_04.expected} (100%) rename test/data/{test_basic_04.json => legacy_test_basic_04.json} (100%) rename test/data/{test_basic_05.expected => legacy_test_basic_05.expected} (100%) rename test/data/{test_basic_05.json => legacy_test_basic_05.json} (100%) rename test/data/{test_basic_06.expected => legacy_test_basic_06.expected} (100%) rename test/data/{test_basic_06.json => legacy_test_basic_06.json} (100%) rename test/data/{test_basic_07.expected => legacy_test_basic_07.expected} (100%) rename test/data/{test_basic_07.json => legacy_test_basic_07.json} (100%) rename test/data/{test_basic_08.expected => legacy_test_basic_08.expected} (100%) rename test/data/{test_basic_08.json => legacy_test_basic_08.json} (100%) rename test/data/{test_basic_09.expected => legacy_test_basic_09.expected} (100%) rename test/data/{test_basic_09.json => legacy_test_basic_09.json} (100%) rename test/data/{test_comment_00.expected => legacy_test_comment_00.expected} (100%) rename test/data/{test_comment_00.json => legacy_test_comment_00.json} (100%) rename test/data/{test_comment_01.expected => legacy_test_comment_01.expected} (100%) rename test/data/{test_comment_01.json => legacy_test_comment_01.json} (100%) rename test/data/{test_comment_02.expected => legacy_test_comment_02.expected} (100%) rename test/data/{test_comment_02.json => legacy_test_comment_02.json} (100%) rename test/data/{test_complex_01.expected => legacy_test_complex_01.expected} (100%) rename test/data/{test_complex_01.json => legacy_test_complex_01.json} (100%) rename test/data/{test_integer_01.expected => legacy_test_integer_01.expected} (100%) rename test/data/{test_integer_01.json => legacy_test_integer_01.json} (100%) rename test/data/{test_integer_02.expected => legacy_test_integer_02.expected} (100%) rename test/data/{test_integer_02.json => legacy_test_integer_02.json} (100%) rename test/data/{test_integer_03.expected => legacy_test_integer_03.expected} (100%) rename test/data/{test_integer_03.json => legacy_test_integer_03.json} (100%) rename test/data/{test_integer_04.expected => legacy_test_integer_04.expected} (100%) rename test/data/{test_integer_04.json => legacy_test_integer_04.json} (100%) rename test/data/{test_integer_05.expected => legacy_test_integer_05.expected} (100%) rename test/data/{test_integer_05.json => legacy_test_integer_05.json} (100%) rename test/data/{test_integer_06_64bits.expected => legacy_test_integer_06_64bits.expected} (100%) rename test/data/{test_integer_06_64bits.json => legacy_test_integer_06_64bits.json} (100%) rename test/data/{test_integer_07_64bits.expected => legacy_test_integer_07_64bits.expected} (100%) rename test/data/{test_integer_07_64bits.json => legacy_test_integer_07_64bits.json} (100%) rename test/data/{test_integer_08_64bits.expected => legacy_test_integer_08_64bits.expected} (100%) rename test/data/{test_integer_08_64bits.json => legacy_test_integer_08_64bits.json} (100%) rename test/data/{test_large_01.expected => legacy_test_large_01.expected} (100%) rename test/data/{test_large_01.json => legacy_test_large_01.json} (100%) rename test/data/{test_object_01.expected => legacy_test_object_01.expected} (100%) rename test/data/{test_object_01.json => legacy_test_object_01.json} (100%) rename test/data/{test_object_02.expected => legacy_test_object_02.expected} (100%) rename test/data/{test_object_02.json => legacy_test_object_02.json} (100%) rename test/data/{test_object_03.expected => legacy_test_object_03.expected} (100%) rename test/data/{test_object_03.json => legacy_test_object_03.json} (100%) rename test/data/{test_object_04.expected => legacy_test_object_04.expected} (100%) rename test/data/{test_object_04.json => legacy_test_object_04.json} (100%) rename test/data/{test_preserve_comment_01.expected => legacy_test_preserve_comment_01.expected} (100%) rename test/data/{test_preserve_comment_01.json => legacy_test_preserve_comment_01.json} (100%) rename test/data/{test_real_01.expected => legacy_test_real_01.expected} (100%) rename test/data/{test_real_01.json => legacy_test_real_01.json} (100%) rename test/data/{test_real_02.expected => legacy_test_real_02.expected} (100%) rename test/data/{test_real_02.json => legacy_test_real_02.json} (100%) rename test/data/{test_real_03.expected => legacy_test_real_03.expected} (100%) rename test/data/{test_real_03.json => legacy_test_real_03.json} (100%) rename test/data/{test_real_04.expected => legacy_test_real_04.expected} (100%) rename test/data/{test_real_04.json => legacy_test_real_04.json} (100%) rename test/data/{test_real_05.expected => legacy_test_real_05.expected} (100%) rename test/data/{test_real_05.json => legacy_test_real_05.json} (100%) rename test/data/{test_real_06.expected => legacy_test_real_06.expected} (100%) rename test/data/{test_real_06.json => legacy_test_real_06.json} (100%) rename test/data/{test_real_07.expected => legacy_test_real_07.expected} (100%) rename test/data/{test_real_07.json => legacy_test_real_07.json} (100%) rename test/data/{test_real_08.expected => legacy_test_real_08.expected} (100%) rename test/data/{test_real_08.json => legacy_test_real_08.json} (100%) rename test/data/{test_real_09.expected => legacy_test_real_09.expected} (100%) rename test/data/{test_real_09.json => legacy_test_real_09.json} (100%) rename test/data/{test_real_10.expected => legacy_test_real_10.expected} (100%) rename test/data/{test_real_10.json => legacy_test_real_10.json} (100%) rename test/data/{test_real_11.expected => legacy_test_real_11.expected} (100%) rename test/data/{test_real_11.json => legacy_test_real_11.json} (100%) rename test/data/{test_real_12.expected => legacy_test_real_12.expected} (100%) rename test/data/{test_real_12.json => legacy_test_real_12.json} (100%) rename test/data/{test_string_01.expected => legacy_test_string_01.expected} (100%) rename test/data/{test_string_01.json => legacy_test_string_01.json} (100%) rename test/data/{test_string_02.expected => legacy_test_string_02.expected} (100%) rename test/data/{test_string_02.json => legacy_test_string_02.json} (100%) rename test/data/{test_string_03.expected => legacy_test_string_03.expected} (100%) rename test/data/{test_string_03.json => legacy_test_string_03.json} (100%) rename test/data/{test_string_04.expected => legacy_test_string_04.expected} (100%) rename test/data/{test_string_04.json => legacy_test_string_04.json} (100%) rename test/data/{test_string_05.expected => legacy_test_string_05.expected} (100%) rename test/data/{test_string_05.json => legacy_test_string_05.json} (100%) rename test/data/{test_string_unicode_01.expected => legacy_test_string_unicode_01.expected} (100%) rename test/data/{test_string_unicode_01.json => legacy_test_string_unicode_01.json} (100%) rename test/data/{test_string_unicode_02.expected => legacy_test_string_unicode_02.expected} (100%) rename test/data/{test_string_unicode_02.json => legacy_test_string_unicode_02.json} (100%) rename test/data/{test_string_unicode_03.expected => legacy_test_string_unicode_03.expected} (100%) rename test/data/{test_string_unicode_03.json => legacy_test_string_unicode_03.json} (100%) rename test/data/{test_string_unicode_04.expected => legacy_test_string_unicode_04.expected} (100%) rename test/data/{test_string_unicode_04.json => legacy_test_string_unicode_04.json} (100%) rename test/data/{test_string_unicode_05.expected => legacy_test_string_unicode_05.expected} (100%) rename test/data/{test_string_unicode_05.json => legacy_test_string_unicode_05.json} (100%) diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp index 27471fff1..51e88b6b6 100644 --- a/src/jsontestrunner/main.cpp +++ b/src/jsontestrunner/main.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include struct Options { @@ -143,7 +144,8 @@ static int parseAndSaveValueTree(const Json::String& input, reader->parse(input.data(), input.data() + input.size(), root, &errors); if (!parsingSuccessful) { - printf("Failed to parse %s file: \n%s\n", kind.c_str(), errors.c_str()); + std::cerr << "Failed to parse " << kind << " file: " << std::endl + << errors << std::endl; return 1; } @@ -154,8 +156,8 @@ static int parseAndSaveValueTree(const Json::String& input, const bool parsingSuccessful = reader.parse(input.data(), input.data() + input.size(), *root); if (!parsingSuccessful) { - printf("Failed to parse %s file: \n%s\n", kind.c_str(), - reader.getFormattedErrorMessages().c_str()); + std::cerr << "Failed to parse " << kind << " file: " << std::endl + << reader.getFormatedErrorMessages() << std::endl; return 1; } } @@ -163,7 +165,7 @@ static int parseAndSaveValueTree(const Json::String& input, if (!parseOnly) { FILE* factual = fopen(actual.c_str(), "wt"); if (!factual) { - printf("Failed to create %s actual file.\n", kind.c_str()); + std::cerr << "Failed to create '" << kind << "' actual file." << std::endl; return 2; } printValueTree(factual, *root); @@ -197,7 +199,7 @@ static int rewriteValueTree(const Json::String& rewritePath, *rewrite = write(root); FILE* fout = fopen(rewritePath.c_str(), "wt"); if (!fout) { - printf("Failed to create rewrite file: %s\n", rewritePath.c_str()); + std::cerr << "Failed to create rewrite file: " << rewritePath << std::endl; return 2; } fprintf(fout, "%s\n", rewrite->c_str()); @@ -218,14 +220,14 @@ static Json::String removeSuffix(const Json::String& path, static void printConfig() { // Print the configuration used to compile JsonCpp #if defined(JSON_NO_INT64) - printf("JSON_NO_INT64=1\n"); + std::cout << "JSON_NO_INT64=1" << std::endl; #else - printf("JSON_NO_INT64=0\n"); + std::cout << "JSON_NO_INT64=0" << std::endl; #endif } static int printUsage(const char* argv[]) { - printf("Usage: %s [--strict] input-json-file", argv[0]); + std::cout << "Usage: " << argv[0] << " [--strict] input-json-file" << std::endl; return 3; } @@ -255,7 +257,7 @@ static int parseCommandLine(int argc, const char* argv[], Options* opts) { } else if (writerName == "BuiltStyledStreamWriter") { opts->write = &useBuiltStyledStreamWriter; } else { - printf("Unknown '--json-writer %s'\n", writerName.c_str()); + std::cerr << "Unknown '--json-writer' " << writerName << std::endl; return 4; } } @@ -271,14 +273,13 @@ static int runTest(Options const& opts, bool use_legacy) { Json::String input = readInputTestFile(opts.path.c_str()); if (input.empty()) { - printf("Failed to read input or empty input: %s\n", opts.path.c_str()); + std::cerr << "Invalid input file: " << opts.path << std::endl; return 3; } Json::String basePath = removeSuffix(opts.path, ".json"); if (!opts.parseOnly && basePath.empty()) { - printf("Bad input path. Path does not end with '.expected':\n%s\n", - opts.path.c_str()); + std::cerr << "Bad input path '" << opts.path << "'. Must end with '.expected'" << std::endl; return 3; } @@ -312,21 +313,22 @@ int main(int argc, const char* argv[]) { try { int exitCode = parseCommandLine(argc, argv, &opts); if (exitCode != 0) { - printf("Failed to parse command-line."); + std::cerr << "Failed to parse command-line." << std::endl; return exitCode; } - // TODO(baylesj): replace this with proper calls to both. Right now - // we only check the legacy if the modern one is not broken. - const int legacy_return_code = runTest(opts, true); const int modern_return_code = runTest(opts, false); if (modern_return_code) { return modern_return_code; - } else { - return legacy_return_code; + } + + const std::string filename = opts.path.substr(opts.path.find_last_of("\\/") + 1); + const bool should_run_legacy = (filename.rfind("legacy_", 0) == 0); + if (should_run_legacy) { + return runTest(opts, true); } } catch (const std::exception& e) { - printf("Unhandled exception:\n%s\n", e.what()); + std::cerr << "Unhandled exception:" << std::endl << e.what() << std::endl; return 1; } } diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 88b2a8aaf..f6d244b67 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1531,14 +1531,14 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // We assume we can represent the largest and smallest integer types as // unsigned integers with separate sign. This is only true if they can fit // into an unsigned integer. - static_assert(Value::maxLargestInt <= Value::maxLargestUInt); + static_assert(Value::maxLargestInt <= Value::maxLargestUInt, "Int must be smaller than UInt"); // We need to convert minLargestInt into a positive number. The easiest way // to do this conversion is to assume our "threshold" value of minLargestInt // divided by 10 can fit in maxLargestInt when absolute valued. This should // be a safe assumption. - static_assert(Value::minLargestInt <= -Value::maxLargestInt); - static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt); + static_assert(Value::minLargestInt <= -Value::maxLargestInt, "The absolute value of minLargestInt must be greater than or equal to maxLargestInt"); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, "The absolute value of minLargestInt must be only 1 magnitude larger than maxLargest Int"); static constexpr Value::LargestUInt positive_threshold = Value::maxLargestUInt / 10; diff --git a/test/data/test_array_01.expected b/test/data/legacy_test_array_01.expected similarity index 100% rename from test/data/test_array_01.expected rename to test/data/legacy_test_array_01.expected diff --git a/test/data/test_array_01.json b/test/data/legacy_test_array_01.json similarity index 100% rename from test/data/test_array_01.json rename to test/data/legacy_test_array_01.json diff --git a/test/data/test_array_02.expected b/test/data/legacy_test_array_02.expected similarity index 100% rename from test/data/test_array_02.expected rename to test/data/legacy_test_array_02.expected diff --git a/test/data/test_array_02.json b/test/data/legacy_test_array_02.json similarity index 100% rename from test/data/test_array_02.json rename to test/data/legacy_test_array_02.json diff --git a/test/data/test_array_03.expected b/test/data/legacy_test_array_03.expected similarity index 100% rename from test/data/test_array_03.expected rename to test/data/legacy_test_array_03.expected diff --git a/test/data/test_array_03.json b/test/data/legacy_test_array_03.json similarity index 100% rename from test/data/test_array_03.json rename to test/data/legacy_test_array_03.json diff --git a/test/data/test_array_04.expected b/test/data/legacy_test_array_04.expected similarity index 100% rename from test/data/test_array_04.expected rename to test/data/legacy_test_array_04.expected diff --git a/test/data/test_array_04.json b/test/data/legacy_test_array_04.json similarity index 100% rename from test/data/test_array_04.json rename to test/data/legacy_test_array_04.json diff --git a/test/data/test_array_05.expected b/test/data/legacy_test_array_05.expected similarity index 100% rename from test/data/test_array_05.expected rename to test/data/legacy_test_array_05.expected diff --git a/test/data/test_array_05.json b/test/data/legacy_test_array_05.json similarity index 100% rename from test/data/test_array_05.json rename to test/data/legacy_test_array_05.json diff --git a/test/data/test_array_06.expected b/test/data/legacy_test_array_06.expected similarity index 100% rename from test/data/test_array_06.expected rename to test/data/legacy_test_array_06.expected diff --git a/test/data/test_array_06.json b/test/data/legacy_test_array_06.json similarity index 100% rename from test/data/test_array_06.json rename to test/data/legacy_test_array_06.json diff --git a/test/data/test_array_07.expected b/test/data/legacy_test_array_07.expected similarity index 100% rename from test/data/test_array_07.expected rename to test/data/legacy_test_array_07.expected diff --git a/test/data/test_array_07.json b/test/data/legacy_test_array_07.json similarity index 100% rename from test/data/test_array_07.json rename to test/data/legacy_test_array_07.json diff --git a/test/data/test_basic_01.expected b/test/data/legacy_test_basic_01.expected similarity index 100% rename from test/data/test_basic_01.expected rename to test/data/legacy_test_basic_01.expected diff --git a/test/data/test_basic_01.json b/test/data/legacy_test_basic_01.json similarity index 100% rename from test/data/test_basic_01.json rename to test/data/legacy_test_basic_01.json diff --git a/test/data/test_basic_02.expected b/test/data/legacy_test_basic_02.expected similarity index 100% rename from test/data/test_basic_02.expected rename to test/data/legacy_test_basic_02.expected diff --git a/test/data/test_basic_02.json b/test/data/legacy_test_basic_02.json similarity index 100% rename from test/data/test_basic_02.json rename to test/data/legacy_test_basic_02.json diff --git a/test/data/test_basic_03.expected b/test/data/legacy_test_basic_03.expected similarity index 100% rename from test/data/test_basic_03.expected rename to test/data/legacy_test_basic_03.expected diff --git a/test/data/test_basic_03.json b/test/data/legacy_test_basic_03.json similarity index 100% rename from test/data/test_basic_03.json rename to test/data/legacy_test_basic_03.json diff --git a/test/data/test_basic_04.expected b/test/data/legacy_test_basic_04.expected similarity index 100% rename from test/data/test_basic_04.expected rename to test/data/legacy_test_basic_04.expected diff --git a/test/data/test_basic_04.json b/test/data/legacy_test_basic_04.json similarity index 100% rename from test/data/test_basic_04.json rename to test/data/legacy_test_basic_04.json diff --git a/test/data/test_basic_05.expected b/test/data/legacy_test_basic_05.expected similarity index 100% rename from test/data/test_basic_05.expected rename to test/data/legacy_test_basic_05.expected diff --git a/test/data/test_basic_05.json b/test/data/legacy_test_basic_05.json similarity index 100% rename from test/data/test_basic_05.json rename to test/data/legacy_test_basic_05.json diff --git a/test/data/test_basic_06.expected b/test/data/legacy_test_basic_06.expected similarity index 100% rename from test/data/test_basic_06.expected rename to test/data/legacy_test_basic_06.expected diff --git a/test/data/test_basic_06.json b/test/data/legacy_test_basic_06.json similarity index 100% rename from test/data/test_basic_06.json rename to test/data/legacy_test_basic_06.json diff --git a/test/data/test_basic_07.expected b/test/data/legacy_test_basic_07.expected similarity index 100% rename from test/data/test_basic_07.expected rename to test/data/legacy_test_basic_07.expected diff --git a/test/data/test_basic_07.json b/test/data/legacy_test_basic_07.json similarity index 100% rename from test/data/test_basic_07.json rename to test/data/legacy_test_basic_07.json diff --git a/test/data/test_basic_08.expected b/test/data/legacy_test_basic_08.expected similarity index 100% rename from test/data/test_basic_08.expected rename to test/data/legacy_test_basic_08.expected diff --git a/test/data/test_basic_08.json b/test/data/legacy_test_basic_08.json similarity index 100% rename from test/data/test_basic_08.json rename to test/data/legacy_test_basic_08.json diff --git a/test/data/test_basic_09.expected b/test/data/legacy_test_basic_09.expected similarity index 100% rename from test/data/test_basic_09.expected rename to test/data/legacy_test_basic_09.expected diff --git a/test/data/test_basic_09.json b/test/data/legacy_test_basic_09.json similarity index 100% rename from test/data/test_basic_09.json rename to test/data/legacy_test_basic_09.json diff --git a/test/data/test_comment_00.expected b/test/data/legacy_test_comment_00.expected similarity index 100% rename from test/data/test_comment_00.expected rename to test/data/legacy_test_comment_00.expected diff --git a/test/data/test_comment_00.json b/test/data/legacy_test_comment_00.json similarity index 100% rename from test/data/test_comment_00.json rename to test/data/legacy_test_comment_00.json diff --git a/test/data/test_comment_01.expected b/test/data/legacy_test_comment_01.expected similarity index 100% rename from test/data/test_comment_01.expected rename to test/data/legacy_test_comment_01.expected diff --git a/test/data/test_comment_01.json b/test/data/legacy_test_comment_01.json similarity index 100% rename from test/data/test_comment_01.json rename to test/data/legacy_test_comment_01.json diff --git a/test/data/test_comment_02.expected b/test/data/legacy_test_comment_02.expected similarity index 100% rename from test/data/test_comment_02.expected rename to test/data/legacy_test_comment_02.expected diff --git a/test/data/test_comment_02.json b/test/data/legacy_test_comment_02.json similarity index 100% rename from test/data/test_comment_02.json rename to test/data/legacy_test_comment_02.json diff --git a/test/data/test_complex_01.expected b/test/data/legacy_test_complex_01.expected similarity index 100% rename from test/data/test_complex_01.expected rename to test/data/legacy_test_complex_01.expected diff --git a/test/data/test_complex_01.json b/test/data/legacy_test_complex_01.json similarity index 100% rename from test/data/test_complex_01.json rename to test/data/legacy_test_complex_01.json diff --git a/test/data/test_integer_01.expected b/test/data/legacy_test_integer_01.expected similarity index 100% rename from test/data/test_integer_01.expected rename to test/data/legacy_test_integer_01.expected diff --git a/test/data/test_integer_01.json b/test/data/legacy_test_integer_01.json similarity index 100% rename from test/data/test_integer_01.json rename to test/data/legacy_test_integer_01.json diff --git a/test/data/test_integer_02.expected b/test/data/legacy_test_integer_02.expected similarity index 100% rename from test/data/test_integer_02.expected rename to test/data/legacy_test_integer_02.expected diff --git a/test/data/test_integer_02.json b/test/data/legacy_test_integer_02.json similarity index 100% rename from test/data/test_integer_02.json rename to test/data/legacy_test_integer_02.json diff --git a/test/data/test_integer_03.expected b/test/data/legacy_test_integer_03.expected similarity index 100% rename from test/data/test_integer_03.expected rename to test/data/legacy_test_integer_03.expected diff --git a/test/data/test_integer_03.json b/test/data/legacy_test_integer_03.json similarity index 100% rename from test/data/test_integer_03.json rename to test/data/legacy_test_integer_03.json diff --git a/test/data/test_integer_04.expected b/test/data/legacy_test_integer_04.expected similarity index 100% rename from test/data/test_integer_04.expected rename to test/data/legacy_test_integer_04.expected diff --git a/test/data/test_integer_04.json b/test/data/legacy_test_integer_04.json similarity index 100% rename from test/data/test_integer_04.json rename to test/data/legacy_test_integer_04.json diff --git a/test/data/test_integer_05.expected b/test/data/legacy_test_integer_05.expected similarity index 100% rename from test/data/test_integer_05.expected rename to test/data/legacy_test_integer_05.expected diff --git a/test/data/test_integer_05.json b/test/data/legacy_test_integer_05.json similarity index 100% rename from test/data/test_integer_05.json rename to test/data/legacy_test_integer_05.json diff --git a/test/data/test_integer_06_64bits.expected b/test/data/legacy_test_integer_06_64bits.expected similarity index 100% rename from test/data/test_integer_06_64bits.expected rename to test/data/legacy_test_integer_06_64bits.expected diff --git a/test/data/test_integer_06_64bits.json b/test/data/legacy_test_integer_06_64bits.json similarity index 100% rename from test/data/test_integer_06_64bits.json rename to test/data/legacy_test_integer_06_64bits.json diff --git a/test/data/test_integer_07_64bits.expected b/test/data/legacy_test_integer_07_64bits.expected similarity index 100% rename from test/data/test_integer_07_64bits.expected rename to test/data/legacy_test_integer_07_64bits.expected diff --git a/test/data/test_integer_07_64bits.json b/test/data/legacy_test_integer_07_64bits.json similarity index 100% rename from test/data/test_integer_07_64bits.json rename to test/data/legacy_test_integer_07_64bits.json diff --git a/test/data/test_integer_08_64bits.expected b/test/data/legacy_test_integer_08_64bits.expected similarity index 100% rename from test/data/test_integer_08_64bits.expected rename to test/data/legacy_test_integer_08_64bits.expected diff --git a/test/data/test_integer_08_64bits.json b/test/data/legacy_test_integer_08_64bits.json similarity index 100% rename from test/data/test_integer_08_64bits.json rename to test/data/legacy_test_integer_08_64bits.json diff --git a/test/data/test_large_01.expected b/test/data/legacy_test_large_01.expected similarity index 100% rename from test/data/test_large_01.expected rename to test/data/legacy_test_large_01.expected diff --git a/test/data/test_large_01.json b/test/data/legacy_test_large_01.json similarity index 100% rename from test/data/test_large_01.json rename to test/data/legacy_test_large_01.json diff --git a/test/data/test_object_01.expected b/test/data/legacy_test_object_01.expected similarity index 100% rename from test/data/test_object_01.expected rename to test/data/legacy_test_object_01.expected diff --git a/test/data/test_object_01.json b/test/data/legacy_test_object_01.json similarity index 100% rename from test/data/test_object_01.json rename to test/data/legacy_test_object_01.json diff --git a/test/data/test_object_02.expected b/test/data/legacy_test_object_02.expected similarity index 100% rename from test/data/test_object_02.expected rename to test/data/legacy_test_object_02.expected diff --git a/test/data/test_object_02.json b/test/data/legacy_test_object_02.json similarity index 100% rename from test/data/test_object_02.json rename to test/data/legacy_test_object_02.json diff --git a/test/data/test_object_03.expected b/test/data/legacy_test_object_03.expected similarity index 100% rename from test/data/test_object_03.expected rename to test/data/legacy_test_object_03.expected diff --git a/test/data/test_object_03.json b/test/data/legacy_test_object_03.json similarity index 100% rename from test/data/test_object_03.json rename to test/data/legacy_test_object_03.json diff --git a/test/data/test_object_04.expected b/test/data/legacy_test_object_04.expected similarity index 100% rename from test/data/test_object_04.expected rename to test/data/legacy_test_object_04.expected diff --git a/test/data/test_object_04.json b/test/data/legacy_test_object_04.json similarity index 100% rename from test/data/test_object_04.json rename to test/data/legacy_test_object_04.json diff --git a/test/data/test_preserve_comment_01.expected b/test/data/legacy_test_preserve_comment_01.expected similarity index 100% rename from test/data/test_preserve_comment_01.expected rename to test/data/legacy_test_preserve_comment_01.expected diff --git a/test/data/test_preserve_comment_01.json b/test/data/legacy_test_preserve_comment_01.json similarity index 100% rename from test/data/test_preserve_comment_01.json rename to test/data/legacy_test_preserve_comment_01.json diff --git a/test/data/test_real_01.expected b/test/data/legacy_test_real_01.expected similarity index 100% rename from test/data/test_real_01.expected rename to test/data/legacy_test_real_01.expected diff --git a/test/data/test_real_01.json b/test/data/legacy_test_real_01.json similarity index 100% rename from test/data/test_real_01.json rename to test/data/legacy_test_real_01.json diff --git a/test/data/test_real_02.expected b/test/data/legacy_test_real_02.expected similarity index 100% rename from test/data/test_real_02.expected rename to test/data/legacy_test_real_02.expected diff --git a/test/data/test_real_02.json b/test/data/legacy_test_real_02.json similarity index 100% rename from test/data/test_real_02.json rename to test/data/legacy_test_real_02.json diff --git a/test/data/test_real_03.expected b/test/data/legacy_test_real_03.expected similarity index 100% rename from test/data/test_real_03.expected rename to test/data/legacy_test_real_03.expected diff --git a/test/data/test_real_03.json b/test/data/legacy_test_real_03.json similarity index 100% rename from test/data/test_real_03.json rename to test/data/legacy_test_real_03.json diff --git a/test/data/test_real_04.expected b/test/data/legacy_test_real_04.expected similarity index 100% rename from test/data/test_real_04.expected rename to test/data/legacy_test_real_04.expected diff --git a/test/data/test_real_04.json b/test/data/legacy_test_real_04.json similarity index 100% rename from test/data/test_real_04.json rename to test/data/legacy_test_real_04.json diff --git a/test/data/test_real_05.expected b/test/data/legacy_test_real_05.expected similarity index 100% rename from test/data/test_real_05.expected rename to test/data/legacy_test_real_05.expected diff --git a/test/data/test_real_05.json b/test/data/legacy_test_real_05.json similarity index 100% rename from test/data/test_real_05.json rename to test/data/legacy_test_real_05.json diff --git a/test/data/test_real_06.expected b/test/data/legacy_test_real_06.expected similarity index 100% rename from test/data/test_real_06.expected rename to test/data/legacy_test_real_06.expected diff --git a/test/data/test_real_06.json b/test/data/legacy_test_real_06.json similarity index 100% rename from test/data/test_real_06.json rename to test/data/legacy_test_real_06.json diff --git a/test/data/test_real_07.expected b/test/data/legacy_test_real_07.expected similarity index 100% rename from test/data/test_real_07.expected rename to test/data/legacy_test_real_07.expected diff --git a/test/data/test_real_07.json b/test/data/legacy_test_real_07.json similarity index 100% rename from test/data/test_real_07.json rename to test/data/legacy_test_real_07.json diff --git a/test/data/test_real_08.expected b/test/data/legacy_test_real_08.expected similarity index 100% rename from test/data/test_real_08.expected rename to test/data/legacy_test_real_08.expected diff --git a/test/data/test_real_08.json b/test/data/legacy_test_real_08.json similarity index 100% rename from test/data/test_real_08.json rename to test/data/legacy_test_real_08.json diff --git a/test/data/test_real_09.expected b/test/data/legacy_test_real_09.expected similarity index 100% rename from test/data/test_real_09.expected rename to test/data/legacy_test_real_09.expected diff --git a/test/data/test_real_09.json b/test/data/legacy_test_real_09.json similarity index 100% rename from test/data/test_real_09.json rename to test/data/legacy_test_real_09.json diff --git a/test/data/test_real_10.expected b/test/data/legacy_test_real_10.expected similarity index 100% rename from test/data/test_real_10.expected rename to test/data/legacy_test_real_10.expected diff --git a/test/data/test_real_10.json b/test/data/legacy_test_real_10.json similarity index 100% rename from test/data/test_real_10.json rename to test/data/legacy_test_real_10.json diff --git a/test/data/test_real_11.expected b/test/data/legacy_test_real_11.expected similarity index 100% rename from test/data/test_real_11.expected rename to test/data/legacy_test_real_11.expected diff --git a/test/data/test_real_11.json b/test/data/legacy_test_real_11.json similarity index 100% rename from test/data/test_real_11.json rename to test/data/legacy_test_real_11.json diff --git a/test/data/test_real_12.expected b/test/data/legacy_test_real_12.expected similarity index 100% rename from test/data/test_real_12.expected rename to test/data/legacy_test_real_12.expected diff --git a/test/data/test_real_12.json b/test/data/legacy_test_real_12.json similarity index 100% rename from test/data/test_real_12.json rename to test/data/legacy_test_real_12.json diff --git a/test/data/test_string_01.expected b/test/data/legacy_test_string_01.expected similarity index 100% rename from test/data/test_string_01.expected rename to test/data/legacy_test_string_01.expected diff --git a/test/data/test_string_01.json b/test/data/legacy_test_string_01.json similarity index 100% rename from test/data/test_string_01.json rename to test/data/legacy_test_string_01.json diff --git a/test/data/test_string_02.expected b/test/data/legacy_test_string_02.expected similarity index 100% rename from test/data/test_string_02.expected rename to test/data/legacy_test_string_02.expected diff --git a/test/data/test_string_02.json b/test/data/legacy_test_string_02.json similarity index 100% rename from test/data/test_string_02.json rename to test/data/legacy_test_string_02.json diff --git a/test/data/test_string_03.expected b/test/data/legacy_test_string_03.expected similarity index 100% rename from test/data/test_string_03.expected rename to test/data/legacy_test_string_03.expected diff --git a/test/data/test_string_03.json b/test/data/legacy_test_string_03.json similarity index 100% rename from test/data/test_string_03.json rename to test/data/legacy_test_string_03.json diff --git a/test/data/test_string_04.expected b/test/data/legacy_test_string_04.expected similarity index 100% rename from test/data/test_string_04.expected rename to test/data/legacy_test_string_04.expected diff --git a/test/data/test_string_04.json b/test/data/legacy_test_string_04.json similarity index 100% rename from test/data/test_string_04.json rename to test/data/legacy_test_string_04.json diff --git a/test/data/test_string_05.expected b/test/data/legacy_test_string_05.expected similarity index 100% rename from test/data/test_string_05.expected rename to test/data/legacy_test_string_05.expected diff --git a/test/data/test_string_05.json b/test/data/legacy_test_string_05.json similarity index 100% rename from test/data/test_string_05.json rename to test/data/legacy_test_string_05.json diff --git a/test/data/test_string_unicode_01.expected b/test/data/legacy_test_string_unicode_01.expected similarity index 100% rename from test/data/test_string_unicode_01.expected rename to test/data/legacy_test_string_unicode_01.expected diff --git a/test/data/test_string_unicode_01.json b/test/data/legacy_test_string_unicode_01.json similarity index 100% rename from test/data/test_string_unicode_01.json rename to test/data/legacy_test_string_unicode_01.json diff --git a/test/data/test_string_unicode_02.expected b/test/data/legacy_test_string_unicode_02.expected similarity index 100% rename from test/data/test_string_unicode_02.expected rename to test/data/legacy_test_string_unicode_02.expected diff --git a/test/data/test_string_unicode_02.json b/test/data/legacy_test_string_unicode_02.json similarity index 100% rename from test/data/test_string_unicode_02.json rename to test/data/legacy_test_string_unicode_02.json diff --git a/test/data/test_string_unicode_03.expected b/test/data/legacy_test_string_unicode_03.expected similarity index 100% rename from test/data/test_string_unicode_03.expected rename to test/data/legacy_test_string_unicode_03.expected diff --git a/test/data/test_string_unicode_03.json b/test/data/legacy_test_string_unicode_03.json similarity index 100% rename from test/data/test_string_unicode_03.json rename to test/data/legacy_test_string_unicode_03.json diff --git a/test/data/test_string_unicode_04.expected b/test/data/legacy_test_string_unicode_04.expected similarity index 100% rename from test/data/test_string_unicode_04.expected rename to test/data/legacy_test_string_unicode_04.expected diff --git a/test/data/test_string_unicode_04.json b/test/data/legacy_test_string_unicode_04.json similarity index 100% rename from test/data/test_string_unicode_04.json rename to test/data/legacy_test_string_unicode_04.json diff --git a/test/data/test_string_unicode_05.expected b/test/data/legacy_test_string_unicode_05.expected similarity index 100% rename from test/data/test_string_unicode_05.expected rename to test/data/legacy_test_string_unicode_05.expected diff --git a/test/data/test_string_unicode_05.json b/test/data/legacy_test_string_unicode_05.json similarity index 100% rename from test/data/test_string_unicode_05.json rename to test/data/legacy_test_string_unicode_05.json From 729abaff5c534c9b4494399fe3371f56d220e35d Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Thu, 17 Oct 2019 15:22:23 -0700 Subject: [PATCH 07/13] clang formatize --- src/jsontestrunner/main.cpp | 18 +++++++++++------- src/lib_json/json_reader.cpp | 11 ++++++++--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp index 51e88b6b6..dbfbe98c1 100644 --- a/src/jsontestrunner/main.cpp +++ b/src/jsontestrunner/main.cpp @@ -15,9 +15,9 @@ #include // sort #include +#include #include #include -#include #include struct Options { @@ -149,8 +149,8 @@ static int parseAndSaveValueTree(const Json::String& input, return 1; } - // We may instead check the legacy implementation (to ensure it doesn't - // randomly get broken). + // We may instead check the legacy implementation (to ensure it doesn't + // randomly get broken). } else { Json::Reader reader(features); const bool parsingSuccessful = @@ -165,7 +165,8 @@ static int parseAndSaveValueTree(const Json::String& input, if (!parseOnly) { FILE* factual = fopen(actual.c_str(), "wt"); if (!factual) { - std::cerr << "Failed to create '" << kind << "' actual file." << std::endl; + std::cerr << "Failed to create '" << kind << "' actual file." + << std::endl; return 2; } printValueTree(factual, *root); @@ -227,7 +228,8 @@ static void printConfig() { } static int printUsage(const char* argv[]) { - std::cout << "Usage: " << argv[0] << " [--strict] input-json-file" << std::endl; + std::cout << "Usage: " << argv[0] << " [--strict] input-json-file" + << std::endl; return 3; } @@ -279,7 +281,8 @@ static int runTest(Options const& opts, bool use_legacy) { Json::String basePath = removeSuffix(opts.path, ".json"); if (!opts.parseOnly && basePath.empty()) { - std::cerr << "Bad input path '" << opts.path << "'. Must end with '.expected'" << std::endl; + std::cerr << "Bad input path '" << opts.path + << "'. Must end with '.expected'" << std::endl; return 3; } @@ -322,7 +325,8 @@ int main(int argc, const char* argv[]) { return modern_return_code; } - const std::string filename = opts.path.substr(opts.path.find_last_of("\\/") + 1); + const std::string filename = + opts.path.substr(opts.path.find_last_of("\\/") + 1); const bool should_run_legacy = (filename.rfind("legacy_", 0) == 0); if (should_run_legacy) { return runTest(opts, true); diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index f6d244b67..1928337a6 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1531,14 +1531,19 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // We assume we can represent the largest and smallest integer types as // unsigned integers with separate sign. This is only true if they can fit // into an unsigned integer. - static_assert(Value::maxLargestInt <= Value::maxLargestUInt, "Int must be smaller than UInt"); + static_assert(Value::maxLargestInt <= Value::maxLargestUInt, + "Int must be smaller than UInt"); // We need to convert minLargestInt into a positive number. The easiest way // to do this conversion is to assume our "threshold" value of minLargestInt // divided by 10 can fit in maxLargestInt when absolute valued. This should // be a safe assumption. - static_assert(Value::minLargestInt <= -Value::maxLargestInt, "The absolute value of minLargestInt must be greater than or equal to maxLargestInt"); - static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, "The absolute value of minLargestInt must be only 1 magnitude larger than maxLargest Int"); + static_assert(Value::minLargestInt <= -Value::maxLargestInt, + "The absolute value of minLargestInt must be greater than or " + "equal to maxLargestInt"); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, + "The absolute value of minLargestInt must be only 1 magnitude " + "larger than maxLargest Int"); static constexpr Value::LargestUInt positive_threshold = Value::maxLargestUInt / 10; From 1c4763bbcc96c5e0d1fc5e16fd07ad066679f4b2 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Tue, 22 Oct 2019 12:19:28 -0700 Subject: [PATCH 08/13] Pushback meson version dependency so I can devbox --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 65dcffa8c..20b909751 100644 --- a/meson.build +++ b/meson.build @@ -15,7 +15,7 @@ project( 'cpp_std=c++11', 'warning_level=1'], license : 'Public Domain', - meson_version : '>= 0.50.0') + meson_version : '>= 0.49.0') jsoncpp_headers = [ From ac1b55c85038ab08bb253777eecbc1624475ea1b Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Wed, 23 Oct 2019 12:59:27 -0700 Subject: [PATCH 09/13] Fixup cmake errors/warnings --- src/lib_json/json_reader.cpp | 6 +++--- src/test_lib_json/main.cpp | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 1928337a6..6e25da2fb 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1561,7 +1561,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { const Value::LargestUInt threshold = isNegative ? negative_threshold : positive_threshold; - const Value::UInt last_digit = + const Value::UInt max_last_digit = isNegative ? negative_last_digit : positive_last_digit; Value::LargestUInt value = 0; @@ -1577,7 +1577,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || digit > last_digit) { + if (value > threshold || current != token.end_ || digit > max_last_digit) { return decodeDouble(token, decoded); } } @@ -1586,7 +1586,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { if (isNegative) { // We use the same magnitude assumption here, just in case. - const Value::UInt last_digit = value % 10; + const Value::UInt last_digit = static_cast(value % 10); decoded = -Value::LargestInt(value / 10) * 10 - last_digit; } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { decoded = Value::LargestInt(value); diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index f32a11fbf..9a7df5568 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -2258,7 +2258,6 @@ JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, multiLineArray) { "\n\t18," "\n\t19," "\n\t20\n]\n"); - Json::StyledStreamWriter writer; Json::Value root; for (int i = 0; i < 21; i++) root[i] = i; From 7e1a02dd58dedbdf020c34e7808d6be3a6966db5 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Wed, 23 Oct 2019 14:09:45 -0700 Subject: [PATCH 10/13] Fixup clang format --- src/lib_json/json_reader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 6e25da2fb..c7f34d56b 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1577,7 +1577,8 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || digit > max_last_digit) { + if (value > threshold || current != token.end_ || + digit > max_last_digit) { return decodeDouble(token, decoded); } } From 9ad6e8b1f256341f4939b8c1a6164976c5790a77 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Wed, 23 Oct 2019 15:29:13 -0700 Subject: [PATCH 11/13] Change OurReader to use string stream --- src/lib_json/json_reader.cpp | 50 ++++++++++-------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index c7f34d56b..61e41534a 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1524,9 +1524,10 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // larger than the maximum supported value of an integer then // we decode the number as a double. Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) + const bool isNegative = *current == '-'; + if (isNegative) { ++current; + } // We assume we can represent the largest and smallest integer types as // unsigned integers with separate sign. This is only true if they can fit @@ -1554,9 +1555,9 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // then take the inverse. This assumes that minLargestInt is only a single // power of 10 different in magnitude, which we check above. For the last // digit, we take the modulus before negating for the same reason. - static const Value::LargestUInt negative_threshold = + static constexpr Value::LargestUInt negative_threshold = Value::LargestUInt(-(Value::minLargestInt / 10)); - static const Value::UInt negative_last_digit = + static constexpr Value::UInt negative_last_digit = Value::UInt(-(Value::minLargestInt % 10)); const Value::LargestUInt threshold = @@ -1610,37 +1611,12 @@ bool OurReader::decodeDouble(Token& token) { bool OurReader::decodeDouble(Token& token, Value& decoded) { double value = 0; - const int bufferSize = 32; - int count; - ptrdiff_t const length = token.end_ - token.start_; - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - auto const ulength = static_cast(length); - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, ulength); - buffer[length] = 0; - fixNumericLocaleInput(buffer, buffer + length); - count = sscanf(buffer, format, &value); - } else { - String buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); - } - - if (count != 1) + const String buffer(token.start_, token.end_); + IStringStream is(buffer); + if (!(is >> value)) { return addError( "'" + String(token.start_, token.end_) + "' is not a number.", token); + } decoded = value; return true; } @@ -1658,13 +1634,13 @@ bool OurReader::decodeString(Token& token) { bool OurReader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' while (current != end) { Char c = *current++; - if (c == '"') + if (c == '"') { break; - else if (c == '\\') { + } else if (c == '\\') { if (current == end) return addError("Empty escape sequence in string", token, current); Char escape = *current++; From f4903f27665026a4c8f789b4886b0ada72b51588 Mon Sep 17 00:00:00 2001 From: dota17 <50514813+dota17@users.noreply.github.com> Date: Sat, 9 Nov 2019 11:04:38 +0800 Subject: [PATCH 12/13] run clang-format (#1089) --- src/lib_json/json_reader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 61e41534a..f8b804bbf 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1634,8 +1634,8 @@ bool OurReader::decodeString(Token& token) { bool OurReader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' while (current != end) { Char c = *current++; if (c == '"') { From ea0fc9ab0c4181c21a54f205422d0ef8f8b56735 Mon Sep 17 00:00:00 2001 From: dota17 <50514813+dota17@users.noreply.github.com> Date: Sat, 9 Nov 2019 11:37:12 +0800 Subject: [PATCH 13/13] fix conflict (#1090) Fix conflict: which has been modified in #1084 --- src/test_lib_json/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 9a7df5568..f32a11fbf 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -2258,6 +2258,7 @@ JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, multiLineArray) { "\n\t18," "\n\t19," "\n\t20\n]\n"); + Json::StyledStreamWriter writer; Json::Value root; for (int i = 0; i < 21; i++) root[i] = i;