diff --git a/cmake/script/GenerateHeaderFromJson.cmake b/cmake/script/GenerateHeaderFromJson.cmake index 4a3bddb323..384ac20d10 100644 --- a/cmake/script/GenerateHeaderFromJson.cmake +++ b/cmake/script/GenerateHeaderFromJson.cmake @@ -6,7 +6,7 @@ cmake_path(GET JSON_SOURCE_PATH STEM json_source_basename) file(READ ${JSON_SOURCE_PATH} hex_content HEX) string(REGEX REPLACE "................" "\\0\n" formatted_bytes "${hex_content}") -string(REGEX REPLACE "[^\n][^\n]" "0x\\0, " formatted_bytes "${formatted_bytes}") +string(REGEX REPLACE "[^\n][^\n]" "'\\\\x\\0'," formatted_bytes "${formatted_bytes}") set(header_content "#include diff --git a/cmake/script/GenerateHeaderFromRaw.cmake b/cmake/script/GenerateHeaderFromRaw.cmake index 638876ecea..d373d1c4f8 100644 --- a/cmake/script/GenerateHeaderFromRaw.cmake +++ b/cmake/script/GenerateHeaderFromRaw.cmake @@ -6,7 +6,7 @@ cmake_path(GET RAW_SOURCE_PATH STEM raw_source_basename) file(READ ${RAW_SOURCE_PATH} hex_content HEX) string(REGEX REPLACE "................" "\\0\n" formatted_bytes "${hex_content}") -string(REGEX REPLACE "[^\n][^\n]" "std::byte{0x\\0}, " formatted_bytes "${formatted_bytes}") +string(REGEX REPLACE "[^\n][^\n]" "std::byte{0x\\0}," formatted_bytes "${formatted_bytes}") set(header_content "#include diff --git a/src/univalue/CMakeLists.txt b/src/univalue/CMakeLists.txt index 96733fe077..c31e82cadc 100644 --- a/src/univalue/CMakeLists.txt +++ b/src/univalue/CMakeLists.txt @@ -15,10 +15,119 @@ target_include_directories(univalue target_link_libraries(univalue PRIVATE core_interface) if(BUILD_TESTS) - add_executable(unitester test/unitester.cpp) - target_compile_definitions(unitester - PRIVATE - JSON_TEST_SRC=\"${CMAKE_CURRENT_SOURCE_DIR}/test\" + include(GenerateHeaders) + generate_header_from_json(test/fail1.json) + generate_header_from_json(test/fail10.json) + generate_header_from_json(test/fail11.json) + generate_header_from_json(test/fail12.json) + generate_header_from_json(test/fail13.json) + generate_header_from_json(test/fail14.json) + generate_header_from_json(test/fail15.json) + generate_header_from_json(test/fail16.json) + generate_header_from_json(test/fail17.json) + generate_header_from_json(test/fail18.json) + generate_header_from_json(test/fail19.json) + generate_header_from_json(test/fail2.json) + generate_header_from_json(test/fail20.json) + generate_header_from_json(test/fail21.json) + generate_header_from_json(test/fail22.json) + generate_header_from_json(test/fail23.json) + generate_header_from_json(test/fail24.json) + generate_header_from_json(test/fail25.json) + generate_header_from_json(test/fail26.json) + generate_header_from_json(test/fail27.json) + generate_header_from_json(test/fail28.json) + generate_header_from_json(test/fail29.json) + generate_header_from_json(test/fail3.json) + generate_header_from_json(test/fail30.json) + generate_header_from_json(test/fail31.json) + generate_header_from_json(test/fail32.json) + generate_header_from_json(test/fail33.json) + generate_header_from_json(test/fail34.json) + generate_header_from_json(test/fail35.json) + generate_header_from_json(test/fail36.json) + generate_header_from_json(test/fail37.json) + generate_header_from_json(test/fail38.json) + generate_header_from_json(test/fail39.json) + generate_header_from_json(test/fail4.json) + generate_header_from_json(test/fail40.json) + generate_header_from_json(test/fail41.json) + generate_header_from_json(test/fail42.json) + generate_header_from_json(test/fail44.json) + generate_header_from_json(test/fail45.json) + generate_header_from_json(test/fail5.json) + generate_header_from_json(test/fail6.json) + generate_header_from_json(test/fail7.json) + generate_header_from_json(test/fail8.json) + generate_header_from_json(test/fail9.json) + generate_header_from_json(test/pass1.json) + generate_header_from_json(test/pass2.json) + generate_header_from_json(test/pass3.json) + generate_header_from_json(test/pass4.json) + generate_header_from_json(test/round1.json) + generate_header_from_json(test/round2.json) + generate_header_from_json(test/round3.json) + generate_header_from_json(test/round4.json) + generate_header_from_json(test/round5.json) + generate_header_from_json(test/round6.json) + generate_header_from_json(test/round7.json) + add_executable(unitester + ${CMAKE_CURRENT_BINARY_DIR}/test/fail1.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail10.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail11.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail12.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail13.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail14.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail15.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail16.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail17.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail18.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail19.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail2.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail20.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail21.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail22.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail23.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail24.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail25.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail26.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail27.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail28.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail29.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail3.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail30.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail31.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail32.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail33.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail34.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail35.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail36.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail37.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail38.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail39.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail4.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail40.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail41.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail42.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail44.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail45.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail5.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail6.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail7.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail8.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/fail9.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/pass1.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/pass2.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/pass3.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/pass4.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round1.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round2.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round3.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round4.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round5.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round6.json.h + ${CMAKE_CURRENT_BINARY_DIR}/test/round7.json.h + test/unitester.cpp ) target_link_libraries(unitester PRIVATE diff --git a/src/univalue/test/fail18.json b/src/univalue/test/fail18.json index edac92716f..a72bec7e18 100644 --- a/src/univalue/test/fail18.json +++ b/src/univalue/test/fail18.json @@ -1 +1 @@ -[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/src/univalue/test/pass2.json b/src/univalue/test/pass2.json index d3c63c7ad8..624387bf33 100644 --- a/src/univalue/test/pass2.json +++ b/src/univalue/test/pass2.json @@ -1 +1 @@ -[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp index d27e647e5c..e517e64188 100644 --- a/src/univalue/test/unitester.cpp +++ b/src/univalue/test/unitester.cpp @@ -1,130 +1,159 @@ // Copyright 2014 BitPay Inc. -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2015-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + 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); + std::string prefix = filename.substr(0, 4); - bool wantPass = (prefix == "pass") || (prefix == "roun"); - bool wantFail = (prefix == "fail"); - bool wantRoundTrip = (prefix == "roun"); - assert(wantPass || wantFail); + bool wantPass = (prefix == "pass") || (prefix == "roun"); + bool wantFail = (prefix == "fail"); + bool wantRoundTrip = (prefix == "roun"); + assert(wantPass || wantFail); - UniValue val; - bool testResult = val.read(jdata); + UniValue val; + bool testResult = val.read(jdata); - if (wantPass) { - assert(testResult == true); - } else { - assert(testResult == false); - } + if (wantPass) { + assert(testResult == true); + } else { + assert(testResult == false); + } - if (wantRoundTrip) { - std::string odata = val.write(0, 0); - assert(odata == rtrim(jdata)); - } + 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 -}; +#define TEST_FILE(name) {#name, json_tests::name} +inline constexpr std::array tests{std::to_array>({ + TEST_FILE(fail1), + TEST_FILE(fail10), + TEST_FILE(fail11), + TEST_FILE(fail12), + TEST_FILE(fail13), + TEST_FILE(fail14), + TEST_FILE(fail15), + TEST_FILE(fail16), + TEST_FILE(fail17), + TEST_FILE(fail18), + TEST_FILE(fail19), + TEST_FILE(fail2), + TEST_FILE(fail20), + TEST_FILE(fail21), + TEST_FILE(fail22), + TEST_FILE(fail23), + TEST_FILE(fail24), + TEST_FILE(fail25), + TEST_FILE(fail26), + TEST_FILE(fail27), + TEST_FILE(fail28), + TEST_FILE(fail29), + TEST_FILE(fail3), + TEST_FILE(fail30), + TEST_FILE(fail31), + TEST_FILE(fail32), + TEST_FILE(fail33), + TEST_FILE(fail34), + TEST_FILE(fail35), + TEST_FILE(fail36), + TEST_FILE(fail37), + TEST_FILE(fail38), // invalid unicode: only first half of surrogate pair + TEST_FILE(fail39), // invalid unicode: only second half of surrogate pair + TEST_FILE(fail4), // extra comma + TEST_FILE(fail40), // invalid unicode: broken UTF-8 + TEST_FILE(fail41), // invalid unicode: unfinished UTF-8 + TEST_FILE(fail42), // valid json with garbage following a nul byte + TEST_FILE(fail44), // unterminated string + TEST_FILE(fail45), // nested beyond max depth + TEST_FILE(fail5), + TEST_FILE(fail6), + TEST_FILE(fail7), + TEST_FILE(fail8), + TEST_FILE(fail9), // extra comma + TEST_FILE(pass1), + TEST_FILE(pass2), + TEST_FILE(pass3), + TEST_FILE(pass4), + TEST_FILE(round1), // round-trip test + TEST_FILE(round2), // unicode + TEST_FILE(round3), // bare string + TEST_FILE(round4), // bare number + TEST_FILE(round5), // bare true + TEST_FILE(round6), // bare false + TEST_FILE(round7), // bare null +})}; // Test \u handling void unescape_unicode_test() @@ -156,10 +185,10 @@ void no_nul_test() assert(val.read({buf + 3, 7})); } -int main (int argc, char *argv[]) +int main(int argc, char* argv[]) { - for (const auto& f: filenames) { - runtest_file(f); + for (const auto& [file, json] : tests) { + runtest(std::string{file}, std::string{json}); } unescape_unicode_test(); @@ -167,4 +196,3 @@ int main (int argc, char *argv[]) return 0; } -