// Copyright 2014 BitPay Inc. // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. #include #include #include #include #ifndef JSON_TEST_SRC #error JSON_TEST_SRC must point to test source directory #endif std::string srcdir(JSON_TEST_SRC); static std::string rtrim(std::string s) { s.erase(s.find_last_not_of(" \n\r\t")+1); return s; } static void runtest(std::string filename, const std::string& jdata) { std::string prefix = filename.substr(0, 4); bool wantPass = (prefix == "pass") || (prefix == "roun"); bool wantFail = (prefix == "fail"); bool wantRoundTrip = (prefix == "roun"); assert(wantPass || wantFail); UniValue val; bool testResult = val.read(jdata); if (wantPass) { assert(testResult == true); } else { assert(testResult == false); } if (wantRoundTrip) { std::string odata = val.write(0, 0); assert(odata == rtrim(jdata)); } } static void runtest_file(const char *filename_) { std::string basename(filename_); std::string filename = srcdir + "/" + basename; FILE *f = fopen(filename.c_str(), "r"); assert(f != nullptr); std::string jdata; char buf[4096]; while (!feof(f)) { int bread = fread(buf, 1, sizeof(buf), f); assert(!ferror(f)); std::string s(buf, bread); jdata += s; } assert(!ferror(f)); fclose(f); runtest(basename, jdata); } static const char *filenames[] = { "fail10.json", "fail11.json", "fail12.json", "fail13.json", "fail14.json", "fail15.json", "fail16.json", "fail17.json", //"fail18.json", // investigate "fail19.json", "fail1.json", "fail20.json", "fail21.json", "fail22.json", "fail23.json", "fail24.json", "fail25.json", "fail26.json", "fail27.json", "fail28.json", "fail29.json", "fail2.json", "fail30.json", "fail31.json", "fail32.json", "fail33.json", "fail34.json", "fail35.json", "fail36.json", "fail37.json", "fail38.json", // invalid unicode: only first half of surrogate pair "fail39.json", // invalid unicode: only second half of surrogate pair "fail40.json", // invalid unicode: broken UTF-8 "fail41.json", // invalid unicode: unfinished UTF-8 "fail42.json", // valid json with garbage following a nul byte "fail44.json", // unterminated string "fail45.json", // nested beyond max depth "fail3.json", "fail4.json", // extra comma "fail5.json", "fail6.json", "fail7.json", "fail8.json", "fail9.json", // extra comma "pass1.json", "pass2.json", "pass3.json", "pass4.json", "round1.json", // round-trip test "round2.json", // unicode "round3.json", // bare string "round4.json", // bare number "round5.json", // bare true "round6.json", // bare false "round7.json", // bare null }; // Test \u handling void unescape_unicode_test() { UniValue val; bool testResult; // Escaped ASCII (quote) testResult = val.read("[\"\\u0022\"]"); assert(testResult); assert(val[0].get_str() == "\""); // Escaped Basic Plane character, two-byte UTF-8 testResult = val.read("[\"\\u0191\"]"); assert(testResult); assert(val[0].get_str() == "\xc6\x91"); // Escaped Basic Plane character, three-byte UTF-8 testResult = val.read("[\"\\u2191\"]"); assert(testResult); assert(val[0].get_str() == "\xe2\x86\x91"); // Escaped Supplementary Plane character U+1d161 testResult = val.read("[\"\\ud834\\udd61\"]"); assert(testResult); assert(val[0].get_str() == "\xf0\x9d\x85\xa1"); } int main (int argc, char *argv[]) { for (const auto& f: filenames) { runtest_file(f); } unescape_unicode_test(); return 0; }