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