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