object.cpp
1 // Copyright (c) 2014 BitPay Inc. 2 // Copyright (c) 2014-2022 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 <cassert> 9 #include <cstdint> 10 #include <map> 11 #include <memory> 12 #include <stdexcept> 13 #include <string> 14 #include <string_view> 15 #include <vector> 16 17 #define BOOST_CHECK(expr) assert(expr) 18 #define BOOST_CHECK_EQUAL(v1, v2) assert((v1) == (v2)) 19 #define BOOST_CHECK_THROW(stmt, excMatch) { \ 20 try { \ 21 (stmt); \ 22 assert(0 && "No exception caught"); \ 23 } catch (excMatch&) { \ 24 } catch (...) { \ 25 assert(0 && "Wrong exception caught"); \ 26 } \ 27 } 28 #define BOOST_CHECK_NO_THROW(stmt) { \ 29 try { \ 30 (stmt); \ 31 } catch (...) { \ 32 assert(0); \ 33 } \ 34 } 35 36 void univalue_constructor() 37 { 38 UniValue v1; 39 BOOST_CHECK(v1.isNull()); 40 41 UniValue v2(UniValue::VSTR); 42 BOOST_CHECK(v2.isStr()); 43 44 UniValue v3(UniValue::VSTR, "foo"); 45 BOOST_CHECK(v3.isStr()); 46 BOOST_CHECK_EQUAL(v3.getValStr(), "foo"); 47 48 UniValue numTest; 49 numTest.setNumStr("82"); 50 BOOST_CHECK(numTest.isNum()); 51 BOOST_CHECK_EQUAL(numTest.getValStr(), "82"); 52 53 uint64_t vu64 = 82; 54 UniValue v4(vu64); 55 BOOST_CHECK(v4.isNum()); 56 BOOST_CHECK_EQUAL(v4.getValStr(), "82"); 57 58 int64_t vi64 = -82; 59 UniValue v5(vi64); 60 BOOST_CHECK(v5.isNum()); 61 BOOST_CHECK_EQUAL(v5.getValStr(), "-82"); 62 63 int vi = -688; 64 UniValue v6(vi); 65 BOOST_CHECK(v6.isNum()); 66 BOOST_CHECK_EQUAL(v6.getValStr(), "-688"); 67 68 double vd = -7.21; 69 UniValue v7(vd); 70 BOOST_CHECK(v7.isNum()); 71 BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21"); 72 73 std::string vs("yawn"); 74 UniValue v8(vs); 75 BOOST_CHECK(v8.isStr()); 76 BOOST_CHECK_EQUAL(v8.getValStr(), "yawn"); 77 78 const char *vcs = "zappa"; 79 UniValue v9(vcs); 80 BOOST_CHECK(v9.isStr()); 81 BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); 82 } 83 84 void univalue_push_throw() 85 { 86 UniValue j; 87 BOOST_CHECK_THROW(j.push_back(1), std::runtime_error); 88 BOOST_CHECK_THROW(j.push_backV({1}), std::runtime_error); 89 BOOST_CHECK_THROW(j.pushKVEnd("k", 1), std::runtime_error); 90 BOOST_CHECK_THROW(j.pushKV("k", 1), std::runtime_error); 91 BOOST_CHECK_THROW(j.pushKVs({}), std::runtime_error); 92 } 93 94 void univalue_typecheck() 95 { 96 UniValue v1; 97 v1.setNumStr("1"); 98 BOOST_CHECK(v1.isNum()); 99 BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error); 100 101 { 102 UniValue v_negative; 103 v_negative.setNumStr("-1"); 104 BOOST_CHECK_THROW(v_negative.getInt<uint8_t>(), std::runtime_error); 105 BOOST_CHECK_EQUAL(v_negative.getInt<int8_t>(), -1); 106 } 107 108 UniValue v2; 109 v2.setBool(true); 110 BOOST_CHECK_EQUAL(v2.get_bool(), true); 111 BOOST_CHECK_THROW(v2.getInt<int>(), std::runtime_error); 112 113 UniValue v3; 114 v3.setNumStr("32482348723847471234"); 115 BOOST_CHECK_THROW(v3.getInt<int64_t>(), std::runtime_error); 116 v3.setNumStr("1000"); 117 BOOST_CHECK_EQUAL(v3.getInt<int64_t>(), 1000); 118 119 UniValue v4; 120 v4.setNumStr("2147483648"); 121 BOOST_CHECK_EQUAL(v4.getInt<int64_t>(), 2147483648); 122 BOOST_CHECK_THROW(v4.getInt<int>(), std::runtime_error); 123 v4.setNumStr("1000"); 124 BOOST_CHECK_EQUAL(v4.getInt<int>(), 1000); 125 BOOST_CHECK_THROW(v4.get_str(), std::runtime_error); 126 BOOST_CHECK_EQUAL(v4.get_real(), 1000); 127 BOOST_CHECK_THROW(v4.get_array(), std::runtime_error); 128 BOOST_CHECK_THROW(v4.getKeys(), std::runtime_error); 129 BOOST_CHECK_THROW(v4.getValues(), std::runtime_error); 130 BOOST_CHECK_THROW(v4.get_obj(), std::runtime_error); 131 132 UniValue v5; 133 BOOST_CHECK(v5.read("[true, 10]")); 134 BOOST_CHECK_NO_THROW(v5.get_array()); 135 std::vector<UniValue> vals = v5.getValues(); 136 BOOST_CHECK_THROW(vals[0].getInt<int>(), std::runtime_error); 137 BOOST_CHECK_EQUAL(vals[0].get_bool(), true); 138 139 BOOST_CHECK_EQUAL(vals[1].getInt<int>(), 10); 140 BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error); 141 } 142 143 void univalue_set() 144 { 145 UniValue v(UniValue::VSTR, "foo"); 146 v.clear(); 147 BOOST_CHECK(v.isNull()); 148 BOOST_CHECK_EQUAL(v.getValStr(), ""); 149 150 v.setObject(); 151 BOOST_CHECK(v.isObject()); 152 BOOST_CHECK_EQUAL(v.size(), 0); 153 BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ); 154 BOOST_CHECK(v.empty()); 155 156 v.setArray(); 157 BOOST_CHECK(v.isArray()); 158 BOOST_CHECK_EQUAL(v.size(), 0); 159 160 v.setStr("zum"); 161 BOOST_CHECK(v.isStr()); 162 BOOST_CHECK_EQUAL(v.getValStr(), "zum"); 163 164 { 165 std::string_view sv{"ab\0c", 4}; 166 UniValue j{sv}; 167 BOOST_CHECK(j.isStr()); 168 BOOST_CHECK_EQUAL(j.getValStr(), sv); 169 BOOST_CHECK_EQUAL(j.write(), "\"ab\\u0000c\""); 170 } 171 172 v.setFloat(-1.01); 173 BOOST_CHECK(v.isNum()); 174 BOOST_CHECK_EQUAL(v.getValStr(), "-1.01"); 175 176 v.setInt(int{1023}); 177 BOOST_CHECK(v.isNum()); 178 BOOST_CHECK_EQUAL(v.getValStr(), "1023"); 179 180 v.setInt(int64_t{-1023LL}); 181 BOOST_CHECK(v.isNum()); 182 BOOST_CHECK_EQUAL(v.getValStr(), "-1023"); 183 184 v.setInt(uint64_t{1023ULL}); 185 BOOST_CHECK(v.isNum()); 186 BOOST_CHECK_EQUAL(v.getValStr(), "1023"); 187 188 v.setNumStr("-688"); 189 BOOST_CHECK(v.isNum()); 190 BOOST_CHECK_EQUAL(v.getValStr(), "-688"); 191 192 v.setBool(false); 193 BOOST_CHECK_EQUAL(v.isBool(), true); 194 BOOST_CHECK_EQUAL(v.isTrue(), false); 195 BOOST_CHECK_EQUAL(v.isFalse(), true); 196 BOOST_CHECK_EQUAL(v.get_bool(), false); 197 198 v.setBool(true); 199 BOOST_CHECK_EQUAL(v.isBool(), true); 200 BOOST_CHECK_EQUAL(v.isTrue(), true); 201 BOOST_CHECK_EQUAL(v.isFalse(), false); 202 BOOST_CHECK_EQUAL(v.get_bool(), true); 203 204 BOOST_CHECK_THROW(v.setNumStr("zombocom"), std::runtime_error); 205 206 v.setNull(); 207 BOOST_CHECK(v.isNull()); 208 } 209 210 void univalue_array() 211 { 212 UniValue arr(UniValue::VARR); 213 214 UniValue v((int64_t)1023LL); 215 arr.push_back(v); 216 217 std::string vStr("zippy"); 218 arr.push_back(vStr); 219 220 const char *s = "pippy"; 221 arr.push_back(s); 222 223 std::vector<UniValue> vec; 224 v.setStr("boing"); 225 vec.push_back(v); 226 227 v.setStr("going"); 228 vec.push_back(v); 229 230 arr.push_backV(vec); 231 232 arr.push_back(uint64_t{400ULL}); 233 arr.push_back(int64_t{-400LL}); 234 arr.push_back(int{-401}); 235 arr.push_back(-40.1); 236 arr.push_back(true); 237 238 BOOST_CHECK_EQUAL(arr.empty(), false); 239 BOOST_CHECK_EQUAL(arr.size(), 10); 240 241 BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); 242 BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM); 243 BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); 244 BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR); 245 BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); 246 BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR); 247 BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); 248 BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR); 249 BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); 250 BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR); 251 BOOST_CHECK_EQUAL(arr[5].getValStr(), "400"); 252 BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM); 253 BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400"); 254 BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM); 255 BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401"); 256 BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM); 257 BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1"); 258 BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM); 259 BOOST_CHECK_EQUAL(arr[9].getValStr(), "1"); 260 BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL); 261 262 BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); 263 264 arr.clear(); 265 BOOST_CHECK(arr.empty()); 266 BOOST_CHECK_EQUAL(arr.size(), 0); 267 } 268 269 void univalue_object() 270 { 271 UniValue obj(UniValue::VOBJ); 272 std::string strKey, strVal; 273 UniValue v; 274 275 strKey = "age"; 276 v.setInt(100); 277 obj.pushKV(strKey, v); 278 279 strKey = "first"; 280 strVal = "John"; 281 obj.pushKV(strKey, strVal); 282 283 strKey = "last"; 284 const char* cVal = "Smith"; 285 obj.pushKV(strKey, cVal); 286 287 strKey = "distance"; 288 obj.pushKV(strKey, int64_t{25}); 289 290 strKey = "time"; 291 obj.pushKV(strKey, uint64_t{3600}); 292 293 strKey = "calories"; 294 obj.pushKV(strKey, int{12}); 295 296 strKey = "temperature"; 297 obj.pushKV(strKey, double{90.012}); 298 299 strKey = "moon"; 300 obj.pushKV(strKey, true); 301 302 strKey = "spoon"; 303 obj.pushKV(strKey, false); 304 305 UniValue obj2(UniValue::VOBJ); 306 obj2.pushKV("cat1", 9000); 307 obj2.pushKV("cat2", 12345); 308 309 obj.pushKVs(obj2); 310 311 BOOST_CHECK_EQUAL(obj.empty(), false); 312 BOOST_CHECK_EQUAL(obj.size(), 11); 313 314 BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100"); 315 BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John"); 316 BOOST_CHECK_EQUAL(obj["last"].getValStr(), "Smith"); 317 BOOST_CHECK_EQUAL(obj["distance"].getValStr(), "25"); 318 BOOST_CHECK_EQUAL(obj["time"].getValStr(), "3600"); 319 BOOST_CHECK_EQUAL(obj["calories"].getValStr(), "12"); 320 BOOST_CHECK_EQUAL(obj["temperature"].getValStr(), "90.012"); 321 BOOST_CHECK_EQUAL(obj["moon"].getValStr(), "1"); 322 BOOST_CHECK_EQUAL(obj["spoon"].getValStr(), ""); 323 BOOST_CHECK_EQUAL(obj["cat1"].getValStr(), "9000"); 324 BOOST_CHECK_EQUAL(obj["cat2"].getValStr(), "12345"); 325 326 BOOST_CHECK_EQUAL(obj["nyuknyuknyuk"].getValStr(), ""); 327 328 BOOST_CHECK(obj.exists("age")); 329 BOOST_CHECK(obj.exists("first")); 330 BOOST_CHECK(obj.exists("last")); 331 BOOST_CHECK(obj.exists("distance")); 332 BOOST_CHECK(obj.exists("time")); 333 BOOST_CHECK(obj.exists("calories")); 334 BOOST_CHECK(obj.exists("temperature")); 335 BOOST_CHECK(obj.exists("moon")); 336 BOOST_CHECK(obj.exists("spoon")); 337 BOOST_CHECK(obj.exists("cat1")); 338 BOOST_CHECK(obj.exists("cat2")); 339 340 BOOST_CHECK(!obj.exists("nyuknyuknyuk")); 341 342 std::map<std::string, UniValue::VType> objTypes; 343 objTypes["age"] = UniValue::VNUM; 344 objTypes["first"] = UniValue::VSTR; 345 objTypes["last"] = UniValue::VSTR; 346 objTypes["distance"] = UniValue::VNUM; 347 objTypes["time"] = UniValue::VNUM; 348 objTypes["calories"] = UniValue::VNUM; 349 objTypes["temperature"] = UniValue::VNUM; 350 objTypes["moon"] = UniValue::VBOOL; 351 objTypes["spoon"] = UniValue::VBOOL; 352 objTypes["cat1"] = UniValue::VNUM; 353 objTypes["cat2"] = UniValue::VNUM; 354 BOOST_CHECK(obj.checkObject(objTypes)); 355 356 objTypes["cat2"] = UniValue::VSTR; 357 BOOST_CHECK(!obj.checkObject(objTypes)); 358 359 obj.clear(); 360 BOOST_CHECK(obj.empty()); 361 BOOST_CHECK_EQUAL(obj.size(), 0); 362 BOOST_CHECK_EQUAL(obj.getType(), UniValue::VNULL); 363 364 obj.setObject(); 365 UniValue uv; 366 uv.setInt(42); 367 obj.pushKVEnd("age", uv); 368 BOOST_CHECK_EQUAL(obj.size(), 1); 369 BOOST_CHECK_EQUAL(obj["age"].getValStr(), "42"); 370 371 uv.setInt(43); 372 obj.pushKV("age", uv); 373 BOOST_CHECK_EQUAL(obj.size(), 1); 374 BOOST_CHECK_EQUAL(obj["age"].getValStr(), "43"); 375 376 obj.pushKV("name", "foo bar"); 377 378 std::map<std::string,UniValue> kv; 379 obj.getObjMap(kv); 380 BOOST_CHECK_EQUAL(kv["age"].getValStr(), "43"); 381 BOOST_CHECK_EQUAL(kv["name"].getValStr(), "foo bar"); 382 383 } 384 385 static const char *json1 = 386 "[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]"; 387 388 void univalue_readwrite() 389 { 390 UniValue v; 391 BOOST_CHECK(v.read(json1)); 392 393 std::string strJson1(json1); 394 BOOST_CHECK(v.read(strJson1)); 395 396 BOOST_CHECK(v.isArray()); 397 BOOST_CHECK_EQUAL(v.size(), 2); 398 399 BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000"); 400 401 UniValue obj = v[1]; 402 BOOST_CHECK(obj.isObject()); 403 BOOST_CHECK_EQUAL(obj.size(), 3); 404 405 BOOST_CHECK(obj["key1"].isStr()); 406 std::string correctValue("str"); 407 correctValue.push_back('\0'); 408 BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue); 409 BOOST_CHECK(obj["key2"].isNum()); 410 BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800"); 411 BOOST_CHECK(obj["key3"].isObject()); 412 413 BOOST_CHECK_EQUAL(strJson1, v.write()); 414 415 // Valid 416 BOOST_CHECK(v.read("1.0") && (v.get_real() == 1.0)); 417 BOOST_CHECK(v.read("true") && v.get_bool()); 418 BOOST_CHECK(v.read("[false]") && !v[0].get_bool()); 419 BOOST_CHECK(v.read("{\"a\": true}") && v["a"].get_bool()); 420 BOOST_CHECK(v.read("{\"1\": \"true\"}") && (v["1"].get_str() == "true")); 421 // Valid, with leading or trailing whitespace 422 BOOST_CHECK(v.read(" 1.0") && (v.get_real() == 1.0)); 423 BOOST_CHECK(v.read("1.0 ") && (v.get_real() == 1.0)); 424 BOOST_CHECK(v.read("0.00000000000000000000000000000000000001e+30 ")); 425 426 BOOST_CHECK(!v.read(".19e-6")); //should fail, missing leading 0, therefore invalid JSON 427 // Invalid, initial garbage 428 BOOST_CHECK(!v.read("[1.0")); 429 BOOST_CHECK(!v.read("a1.0")); 430 // Invalid, trailing garbage 431 BOOST_CHECK(!v.read("1.0sds")); 432 BOOST_CHECK(!v.read("1.0]")); 433 // Invalid, keys have to be names 434 BOOST_CHECK(!v.read("{1: \"true\"}")); 435 BOOST_CHECK(!v.read("{true: 1}")); 436 BOOST_CHECK(!v.read("{[1]: 1}")); 437 BOOST_CHECK(!v.read("{{\"a\": \"a\"}: 1}")); 438 // BTC addresses should fail parsing 439 BOOST_CHECK(!v.read("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); 440 BOOST_CHECK(!v.read("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL")); 441 442 /* Check for (correctly reporting) a parsing error if the initial 443 JSON construct is followed by more stuff. Note that whitespace 444 is, of course, exempt. */ 445 446 BOOST_CHECK(v.read(" {}\n ")); 447 BOOST_CHECK(v.isObject()); 448 BOOST_CHECK(v.read(" []\n ")); 449 BOOST_CHECK(v.isArray()); 450 451 BOOST_CHECK(!v.read("@{}")); 452 BOOST_CHECK(!v.read("{} garbage")); 453 BOOST_CHECK(!v.read("[]{}")); 454 BOOST_CHECK(!v.read("{}[]")); 455 BOOST_CHECK(!v.read("{} 42")); 456 } 457 458 int main(int argc, char* argv[]) 459 { 460 univalue_constructor(); 461 univalue_push_throw(); 462 univalue_typecheck(); 463 univalue_set(); 464 univalue_array(); 465 univalue_object(); 466 univalue_readwrite(); 467 return 0; 468 }