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