Line data Source code
1 : // Copyright 2014 BitPay, Inc.
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <stdint.h>
6 : #include <vector>
7 : #include <string>
8 : #include <map>
9 : #include <univalue.h>
10 : #include "test/test_bitcoin.h"
11 :
12 : #include <boost/test/unit_test.hpp>
13 :
14 : using namespace std;
15 :
16 1 : BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup)
17 :
18 6 : BOOST_AUTO_TEST_CASE(univalue_constructor)
19 : {
20 : UniValue v1;
21 9 : BOOST_CHECK(v1.isNull());
22 :
23 4 : UniValue v2(UniValue::VSTR);
24 9 : BOOST_CHECK(v2.isStr());
25 :
26 4 : UniValue v3(UniValue::VSTR, "foo");
27 9 : BOOST_CHECK(v3.isStr());
28 5 : BOOST_CHECK_EQUAL(v3.getValStr(), "foo");
29 :
30 1 : UniValue numTest;
31 10 : BOOST_CHECK(numTest.setNumStr("82"));
32 9 : BOOST_CHECK(numTest.isNum());
33 5 : BOOST_CHECK_EQUAL(numTest.getValStr(), "82");
34 :
35 1 : uint64_t vu64 = 82;
36 2 : UniValue v4(vu64);
37 9 : BOOST_CHECK(v4.isNum());
38 5 : BOOST_CHECK_EQUAL(v4.getValStr(), "82");
39 :
40 1 : int64_t vi64 = -82;
41 2 : UniValue v5(vi64);
42 8 : BOOST_CHECK(v5.isNum());
43 5 : BOOST_CHECK_EQUAL(v5.getValStr(), "-82");
44 :
45 1 : int vi = -688;
46 2 : UniValue v6(vi);
47 9 : BOOST_CHECK(v6.isNum());
48 5 : BOOST_CHECK_EQUAL(v6.getValStr(), "-688");
49 :
50 1 : double vd = -7.21;
51 2 : UniValue v7(vd);
52 9 : BOOST_CHECK(v7.isNum());
53 5 : BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
54 :
55 2 : string vs("yawn");
56 2 : UniValue v8(vs);
57 9 : BOOST_CHECK(v8.isStr());
58 5 : BOOST_CHECK_EQUAL(v8.getValStr(), "yawn");
59 :
60 1 : const char *vcs = "zappa";
61 2 : UniValue v9(vcs);
62 9 : BOOST_CHECK(v9.isStr());
63 6 : BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
64 1 : }
65 :
66 6 : BOOST_AUTO_TEST_CASE(univalue_typecheck)
67 : {
68 : UniValue v1;
69 9 : BOOST_CHECK(v1.setNumStr("1"));
70 9 : BOOST_CHECK(v1.isNum());
71 8 : BOOST_CHECK_THROW(v1.get_bool(), runtime_error);
72 :
73 1 : UniValue v2;
74 8 : BOOST_CHECK(v2.setBool(true));
75 5 : BOOST_CHECK_EQUAL(v2.get_bool(), true);
76 8 : BOOST_CHECK_THROW(v2.get_int(), runtime_error);
77 :
78 1 : UniValue v3;
79 10 : BOOST_CHECK(v3.setNumStr("32482348723847471234"));
80 8 : BOOST_CHECK_THROW(v3.get_int64(), runtime_error);
81 10 : BOOST_CHECK(v3.setNumStr("1000"));
82 5 : BOOST_CHECK_EQUAL(v3.get_int64(), 1000);
83 :
84 1 : UniValue v4;
85 10 : BOOST_CHECK(v4.setNumStr("2147483648"));
86 5 : BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648);
87 8 : BOOST_CHECK_THROW(v4.get_int(), runtime_error);
88 10 : BOOST_CHECK(v4.setNumStr("1000"));
89 5 : BOOST_CHECK_EQUAL(v4.get_int(), 1000);
90 8 : BOOST_CHECK_THROW(v4.get_str(), runtime_error);
91 5 : BOOST_CHECK_EQUAL(v4.get_real(), 1000);
92 8 : BOOST_CHECK_THROW(v4.get_array(), runtime_error);
93 8 : BOOST_CHECK_THROW(v4.getKeys(), runtime_error);
94 8 : BOOST_CHECK_THROW(v4.getValues(), runtime_error);
95 8 : BOOST_CHECK_THROW(v4.get_obj(), runtime_error);
96 :
97 1 : UniValue v5;
98 8 : BOOST_CHECK(v5.read("[true, 10]"));
99 7 : BOOST_CHECK_NO_THROW(v5.get_array());
100 2 : std::vector<UniValue> vals = v5.getValues();
101 8 : BOOST_CHECK_THROW(vals[0].get_int(), runtime_error);
102 5 : BOOST_CHECK_EQUAL(vals[0].get_bool(), true);
103 :
104 6 : BOOST_CHECK_EQUAL(vals[1].get_int(), 10);
105 10 : BOOST_CHECK_THROW(vals[1].get_bool(), runtime_error);
106 1 : }
107 :
108 6 : BOOST_AUTO_TEST_CASE(univalue_set)
109 : {
110 3 : UniValue v(UniValue::VSTR, "foo");
111 1 : v.clear();
112 9 : BOOST_CHECK(v.isNull());
113 5 : BOOST_CHECK_EQUAL(v.getValStr(), "");
114 :
115 8 : BOOST_CHECK(v.setObject());
116 9 : BOOST_CHECK(v.isObject());
117 6 : BOOST_CHECK_EQUAL(v.size(), 0);
118 5 : BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
119 8 : BOOST_CHECK(v.empty());
120 :
121 8 : BOOST_CHECK(v.setArray());
122 9 : BOOST_CHECK(v.isArray());
123 6 : BOOST_CHECK_EQUAL(v.size(), 0);
124 :
125 10 : BOOST_CHECK(v.setStr("zum"));
126 9 : BOOST_CHECK(v.isStr());
127 5 : BOOST_CHECK_EQUAL(v.getValStr(), "zum");
128 :
129 8 : BOOST_CHECK(v.setFloat(-1.01));
130 9 : BOOST_CHECK(v.isNum());
131 5 : BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
132 :
133 8 : BOOST_CHECK(v.setInt((int)1023));
134 9 : BOOST_CHECK(v.isNum());
135 5 : BOOST_CHECK_EQUAL(v.getValStr(), "1023");
136 :
137 8 : BOOST_CHECK(v.setInt((int64_t)-1023LL));
138 9 : BOOST_CHECK(v.isNum());
139 5 : BOOST_CHECK_EQUAL(v.getValStr(), "-1023");
140 :
141 8 : BOOST_CHECK(v.setInt((uint64_t)1023ULL));
142 9 : BOOST_CHECK(v.isNum());
143 5 : BOOST_CHECK_EQUAL(v.getValStr(), "1023");
144 :
145 10 : BOOST_CHECK(v.setNumStr("-688"));
146 9 : BOOST_CHECK(v.isNum());
147 5 : BOOST_CHECK_EQUAL(v.getValStr(), "-688");
148 :
149 8 : BOOST_CHECK(v.setBool(false));
150 6 : BOOST_CHECK_EQUAL(v.isBool(), true);
151 5 : BOOST_CHECK_EQUAL(v.isTrue(), false);
152 5 : BOOST_CHECK_EQUAL(v.isFalse(), true);
153 6 : BOOST_CHECK_EQUAL(v.getBool(), false);
154 :
155 8 : BOOST_CHECK(v.setBool(true));
156 6 : BOOST_CHECK_EQUAL(v.isBool(), true);
157 5 : BOOST_CHECK_EQUAL(v.isTrue(), true);
158 5 : BOOST_CHECK_EQUAL(v.isFalse(), false);
159 6 : BOOST_CHECK_EQUAL(v.getBool(), true);
160 :
161 10 : BOOST_CHECK(!v.setNumStr("zombocom"));
162 :
163 8 : BOOST_CHECK(v.setNull());
164 9 : BOOST_CHECK(v.isNull());
165 1 : }
166 :
167 6 : BOOST_AUTO_TEST_CASE(univalue_array)
168 : {
169 3 : UniValue arr(UniValue::VARR);
170 :
171 2 : UniValue v((int64_t)1023LL);
172 8 : BOOST_CHECK(arr.push_back(v));
173 :
174 2 : string vStr("zippy");
175 8 : BOOST_CHECK(arr.push_back(vStr));
176 :
177 : const char *s = "pippy";
178 8 : BOOST_CHECK(arr.push_back(s));
179 :
180 1 : vector<UniValue> vec;
181 3 : v.setStr("boing");
182 1 : vec.push_back(v);
183 :
184 3 : v.setStr("going");
185 1 : vec.push_back(v);
186 :
187 8 : BOOST_CHECK(arr.push_backV(vec));
188 :
189 6 : BOOST_CHECK_EQUAL(arr.empty(), false);
190 6 : BOOST_CHECK_EQUAL(arr.size(), 5);
191 :
192 6 : BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
193 6 : BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
194 6 : BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy");
195 6 : BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing");
196 6 : BOOST_CHECK_EQUAL(arr[4].getValStr(), "going");
197 :
198 6 : BOOST_CHECK_EQUAL(arr[999].getValStr(), "");
199 :
200 1 : arr.clear();
201 8 : BOOST_CHECK(arr.empty());
202 7 : BOOST_CHECK_EQUAL(arr.size(), 0);
203 1 : }
204 :
205 6 : BOOST_AUTO_TEST_CASE(univalue_object)
206 : {
207 3 : UniValue obj(UniValue::VOBJ);
208 : string strKey, strVal;
209 1 : UniValue v;
210 :
211 : strKey = "age";
212 : v.setInt(100);
213 8 : BOOST_CHECK(obj.pushKV(strKey, v));
214 :
215 : strKey = "first";
216 : strVal = "John";
217 8 : BOOST_CHECK(obj.pushKV(strKey, strVal));
218 :
219 : strKey = "last";
220 : const char *cVal = "Smith";
221 8 : BOOST_CHECK(obj.pushKV(strKey, cVal));
222 :
223 : strKey = "distance";
224 8 : BOOST_CHECK(obj.pushKV(strKey, (int64_t) 25));
225 :
226 : strKey = "time";
227 8 : BOOST_CHECK(obj.pushKV(strKey, (uint64_t) 3600));
228 :
229 : strKey = "calories";
230 8 : BOOST_CHECK(obj.pushKV(strKey, (int) 12));
231 :
232 : strKey = "temperature";
233 8 : BOOST_CHECK(obj.pushKV(strKey, (double) 90.012));
234 :
235 4 : UniValue obj2(UniValue::VOBJ);
236 10 : BOOST_CHECK(obj2.pushKV("cat1", 9000));
237 10 : BOOST_CHECK(obj2.pushKV("cat2", 12345));
238 :
239 8 : BOOST_CHECK(obj.pushKVs(obj2));
240 :
241 6 : BOOST_CHECK_EQUAL(obj.empty(), false);
242 6 : BOOST_CHECK_EQUAL(obj.size(), 9);
243 :
244 8 : BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100");
245 8 : BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John");
246 8 : BOOST_CHECK_EQUAL(obj["last"].getValStr(), "Smith");
247 8 : BOOST_CHECK_EQUAL(obj["distance"].getValStr(), "25");
248 8 : BOOST_CHECK_EQUAL(obj["time"].getValStr(), "3600");
249 8 : BOOST_CHECK_EQUAL(obj["calories"].getValStr(), "12");
250 8 : BOOST_CHECK_EQUAL(obj["temperature"].getValStr(), "90.012");
251 8 : BOOST_CHECK_EQUAL(obj["cat1"].getValStr(), "9000");
252 8 : BOOST_CHECK_EQUAL(obj["cat2"].getValStr(), "12345");
253 :
254 8 : BOOST_CHECK_EQUAL(obj["nyuknyuknyuk"].getValStr(), "");
255 :
256 11 : BOOST_CHECK(obj.exists("age"));
257 11 : BOOST_CHECK(obj.exists("first"));
258 11 : BOOST_CHECK(obj.exists("last"));
259 11 : BOOST_CHECK(obj.exists("distance"));
260 11 : BOOST_CHECK(obj.exists("time"));
261 11 : BOOST_CHECK(obj.exists("calories"));
262 11 : BOOST_CHECK(obj.exists("temperature"));
263 11 : BOOST_CHECK(obj.exists("cat1"));
264 11 : BOOST_CHECK(obj.exists("cat2"));
265 :
266 11 : BOOST_CHECK(!obj.exists("nyuknyuknyuk"));
267 :
268 : map<string, UniValue::VType> objTypes;
269 3 : objTypes["age"] = UniValue::VNUM;
270 3 : objTypes["first"] = UniValue::VSTR;
271 3 : objTypes["last"] = UniValue::VSTR;
272 3 : objTypes["distance"] = UniValue::VNUM;
273 3 : objTypes["time"] = UniValue::VNUM;
274 3 : objTypes["calories"] = UniValue::VNUM;
275 3 : objTypes["temperature"] = UniValue::VNUM;
276 3 : objTypes["cat1"] = UniValue::VNUM;
277 3 : objTypes["cat2"] = UniValue::VNUM;
278 8 : BOOST_CHECK(obj.checkObject(objTypes));
279 :
280 3 : objTypes["cat2"] = UniValue::VSTR;
281 8 : BOOST_CHECK(!obj.checkObject(objTypes));
282 :
283 1 : obj.clear();
284 8 : BOOST_CHECK(obj.empty());
285 7 : BOOST_CHECK_EQUAL(obj.size(), 0);
286 1 : }
287 :
288 : static const char *json1 =
289 : "[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]";
290 :
291 6 : BOOST_AUTO_TEST_CASE(univalue_readwrite)
292 : {
293 : UniValue v;
294 8 : BOOST_CHECK(v.read(json1));
295 :
296 2 : string strJson1(json1);
297 8 : BOOST_CHECK(v.read(strJson1));
298 :
299 9 : BOOST_CHECK(v.isArray());
300 6 : BOOST_CHECK_EQUAL(v.size(), 2);
301 :
302 6 : BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000");
303 :
304 2 : UniValue obj = v[1];
305 9 : BOOST_CHECK(obj.isObject());
306 6 : BOOST_CHECK_EQUAL(obj.size(), 3);
307 :
308 11 : BOOST_CHECK(obj["key1"].isStr());
309 2 : std::string correctValue("str");
310 1 : correctValue.push_back('\0');
311 8 : BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue);
312 11 : BOOST_CHECK(obj["key2"].isNum());
313 8 : BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800");
314 11 : BOOST_CHECK(obj["key3"].isObject());
315 :
316 6 : BOOST_CHECK_EQUAL(strJson1, v.write());
317 :
318 : /* Check for (correctly reporting) a parsing error if the initial
319 : JSON construct is followed by more stuff. Note that whitespace
320 : is, of course, exempt. */
321 :
322 8 : BOOST_CHECK(v.read(" {}\n "));
323 9 : BOOST_CHECK(v.isObject());
324 8 : BOOST_CHECK(v.read(" []\n "));
325 9 : BOOST_CHECK(v.isArray());
326 :
327 8 : BOOST_CHECK(!v.read("@{}"));
328 8 : BOOST_CHECK(!v.read("{} garbage"));
329 8 : BOOST_CHECK(!v.read("[]{}"));
330 8 : BOOST_CHECK(!v.read("{}[]"));
331 9 : BOOST_CHECK(!v.read("{} 42"));
332 1 : }
333 :
334 3 : BOOST_AUTO_TEST_SUITE_END()
335 :
|