object.cpp raw

   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  }
 468