unitester.cpp
1 // Copyright 2014 BitPay Inc. 2 // Copyright (c) 2015-present The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or https://opensource.org/licenses/mit-license.php. 5 6 #include <univalue.h> 7 8 #include <univalue/test/fail1.json.h> 9 #include <univalue/test/fail10.json.h> 10 #include <univalue/test/fail11.json.h> 11 #include <univalue/test/fail12.json.h> 12 #include <univalue/test/fail13.json.h> 13 #include <univalue/test/fail14.json.h> 14 #include <univalue/test/fail15.json.h> 15 #include <univalue/test/fail16.json.h> 16 #include <univalue/test/fail17.json.h> 17 #include <univalue/test/fail18.json.h> 18 #include <univalue/test/fail19.json.h> 19 #include <univalue/test/fail2.json.h> 20 #include <univalue/test/fail20.json.h> 21 #include <univalue/test/fail21.json.h> 22 #include <univalue/test/fail22.json.h> 23 #include <univalue/test/fail23.json.h> 24 #include <univalue/test/fail24.json.h> 25 #include <univalue/test/fail25.json.h> 26 #include <univalue/test/fail26.json.h> 27 #include <univalue/test/fail27.json.h> 28 #include <univalue/test/fail28.json.h> 29 #include <univalue/test/fail29.json.h> 30 #include <univalue/test/fail3.json.h> 31 #include <univalue/test/fail30.json.h> 32 #include <univalue/test/fail31.json.h> 33 #include <univalue/test/fail32.json.h> 34 #include <univalue/test/fail33.json.h> 35 #include <univalue/test/fail34.json.h> 36 #include <univalue/test/fail35.json.h> 37 #include <univalue/test/fail36.json.h> 38 #include <univalue/test/fail37.json.h> 39 #include <univalue/test/fail38.json.h> 40 #include <univalue/test/fail39.json.h> 41 #include <univalue/test/fail4.json.h> 42 #include <univalue/test/fail40.json.h> 43 #include <univalue/test/fail41.json.h> 44 #include <univalue/test/fail42.json.h> 45 #include <univalue/test/fail44.json.h> 46 #include <univalue/test/fail45.json.h> 47 #include <univalue/test/fail5.json.h> 48 #include <univalue/test/fail6.json.h> 49 #include <univalue/test/fail7.json.h> 50 #include <univalue/test/fail8.json.h> 51 #include <univalue/test/fail9.json.h> 52 #include <univalue/test/pass1.json.h> 53 #include <univalue/test/pass2.json.h> 54 #include <univalue/test/pass3.json.h> 55 #include <univalue/test/pass4.json.h> 56 #include <univalue/test/round1.json.h> 57 #include <univalue/test/round2.json.h> 58 #include <univalue/test/round3.json.h> 59 #include <univalue/test/round4.json.h> 60 #include <univalue/test/round5.json.h> 61 #include <univalue/test/round6.json.h> 62 #include <univalue/test/round7.json.h> 63 64 #include <array> 65 #include <cassert> 66 #include <string> 67 #include <string_view> 68 #include <tuple> 69 70 static std::string rtrim(std::string s) 71 { 72 s.erase(s.find_last_not_of(" \n\r\t") + 1); 73 return s; 74 } 75 76 static void runtest(std::string filename, const std::string& jdata) 77 { 78 std::string prefix = filename.substr(0, 4); 79 80 bool wantPass = (prefix == "pass") || (prefix == "roun"); 81 bool wantFail = (prefix == "fail"); 82 bool wantRoundTrip = (prefix == "roun"); 83 assert(wantPass || wantFail); 84 85 UniValue val; 86 bool testResult = val.read(jdata); 87 88 if (wantPass) { 89 assert(testResult == true); 90 } else { 91 assert(testResult == false); 92 } 93 94 if (wantRoundTrip) { 95 std::string odata = val.write(0, 0); 96 assert(odata == rtrim(jdata)); 97 } 98 } 99 100 #define TEST_FILE(name) {#name, json_tests::name} 101 inline constexpr std::array tests{std::to_array<std::tuple<std::string_view, std::string_view>>({ 102 TEST_FILE(fail1), 103 TEST_FILE(fail10), 104 TEST_FILE(fail11), 105 TEST_FILE(fail12), 106 TEST_FILE(fail13), 107 TEST_FILE(fail14), 108 TEST_FILE(fail15), 109 TEST_FILE(fail16), 110 TEST_FILE(fail17), 111 TEST_FILE(fail18), 112 TEST_FILE(fail19), 113 TEST_FILE(fail2), 114 TEST_FILE(fail20), 115 TEST_FILE(fail21), 116 TEST_FILE(fail22), 117 TEST_FILE(fail23), 118 TEST_FILE(fail24), 119 TEST_FILE(fail25), 120 TEST_FILE(fail26), 121 TEST_FILE(fail27), 122 TEST_FILE(fail28), 123 TEST_FILE(fail29), 124 TEST_FILE(fail3), 125 TEST_FILE(fail30), 126 TEST_FILE(fail31), 127 TEST_FILE(fail32), 128 TEST_FILE(fail33), 129 TEST_FILE(fail34), 130 TEST_FILE(fail35), 131 TEST_FILE(fail36), 132 TEST_FILE(fail37), 133 TEST_FILE(fail38), // invalid unicode: only first half of surrogate pair 134 TEST_FILE(fail39), // invalid unicode: only second half of surrogate pair 135 TEST_FILE(fail4), // extra comma 136 TEST_FILE(fail40), // invalid unicode: broken UTF-8 137 TEST_FILE(fail41), // invalid unicode: unfinished UTF-8 138 TEST_FILE(fail42), // valid json with garbage following a nul byte 139 TEST_FILE(fail44), // unterminated string 140 TEST_FILE(fail45), // nested beyond max depth 141 TEST_FILE(fail5), 142 TEST_FILE(fail6), 143 TEST_FILE(fail7), 144 TEST_FILE(fail8), 145 TEST_FILE(fail9), // extra comma 146 TEST_FILE(pass1), 147 TEST_FILE(pass2), 148 TEST_FILE(pass3), 149 TEST_FILE(pass4), 150 TEST_FILE(round1), // round-trip test 151 TEST_FILE(round2), // unicode 152 TEST_FILE(round3), // bare string 153 TEST_FILE(round4), // bare number 154 TEST_FILE(round5), // bare true 155 TEST_FILE(round6), // bare false 156 TEST_FILE(round7), // bare null 157 })}; 158 159 // Test \u handling 160 void unescape_unicode_test() 161 { 162 UniValue val; 163 bool testResult; 164 // Escaped ASCII (quote) 165 testResult = val.read("[\"\\u0022\"]"); 166 assert(testResult); 167 assert(val[0].get_str() == "\""); 168 // Escaped Basic Plane character, two-byte UTF-8 169 testResult = val.read("[\"\\u0191\"]"); 170 assert(testResult); 171 assert(val[0].get_str() == "\xc6\x91"); 172 // Escaped Basic Plane character, three-byte UTF-8 173 testResult = val.read("[\"\\u2191\"]"); 174 assert(testResult); 175 assert(val[0].get_str() == "\xe2\x86\x91"); 176 // Escaped Supplementary Plane character U+1d161 177 testResult = val.read("[\"\\ud834\\udd61\"]"); 178 assert(testResult); 179 assert(val[0].get_str() == "\xf0\x9d\x85\xa1"); 180 } 181 182 void no_nul_test() 183 { 184 char buf[] = "___[1,2,3]___"; 185 UniValue val; 186 assert(val.read({buf + 3, 7})); 187 } 188 189 int main(int argc, char* argv[]) 190 { 191 for (const auto& [file, json] : tests) { 192 runtest(std::string{file}, std::string{json}); 193 } 194 195 unescape_unicode_test(); 196 no_nul_test(); 197 198 return 0; 199 }