object.cpp raw

   1  // Copyright (c) 2014 BitPay Inc.
   2  // Copyright (c) 2014-2022 The Limenka 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  }
 469