/ src / univalue / test / object.cpp
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  }