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