data_unittests.cc 31.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <gtest/gtest.h>
#include <boost/foreach.hpp>
#include <boost/assign/std/vector.hpp>
18
#include <climits>
19

JINMEI Tatuya's avatar
JINMEI Tatuya committed
20
#include <cc/data.h>
21

Jelte Jansen's avatar
Jelte Jansen committed
22
using namespace isc::data;
23

24
#include <sstream>
25
26
27
28
29
#include <iostream>
using std::oct;
#include <iomanip>
using std::setfill;
using std::setw;
30
using std::string;
31

32
namespace {
33
TEST(Element, type) {
34
    // this tests checks whether the getType() function returns the
35
36
    // correct type
    IntElement int_el = IntElement(1);
37
    EXPECT_EQ(int_el.getType(), Element::integer);
38
    DoubleElement double_el = DoubleElement(1.0);
39
    EXPECT_EQ(double_el.getType(), Element::real);
40
    BoolElement bool_el = BoolElement(true);
41
    EXPECT_EQ(bool_el.getType(), Element::boolean);
42
    StringElement str_el = StringElement("foo");
43
    EXPECT_EQ(str_el.getType(), Element::string);
44
    ListElement list_el = ListElement();
45
    EXPECT_EQ(list_el.getType(), Element::list);
46
    MapElement map_el = MapElement();
47
    EXPECT_EQ(map_el.getType(), Element::map);
Jelte Jansen's avatar
Jelte Jansen committed
48

49
50
}

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
TEST(Element, TypeNameConversion) {
    EXPECT_EQ(Element::integer, Element::nameToType("integer"));
    EXPECT_EQ(Element::real, Element::nameToType("real"));
    EXPECT_EQ(Element::boolean, Element::nameToType("boolean"));
    EXPECT_EQ(Element::string, Element::nameToType("string"));
    EXPECT_EQ(Element::list, Element::nameToType("list"));
    EXPECT_EQ(Element::map, Element::nameToType("map"));
    EXPECT_EQ(Element::null, Element::nameToType("null"));
    EXPECT_EQ(Element::any, Element::nameToType("any"));
    EXPECT_THROW(Element::nameToType("somethingunknown"), TypeError);

    EXPECT_EQ("integer", Element::typeToName(Element::integer));
    EXPECT_EQ("real", Element::typeToName(Element::real));
    EXPECT_EQ("boolean", Element::typeToName(Element::boolean));
    EXPECT_EQ("string", Element::typeToName(Element::string));
    EXPECT_EQ("list", Element::typeToName(Element::list));
    EXPECT_EQ("map", Element::typeToName(Element::map));
    EXPECT_EQ("null", Element::typeToName(Element::null));
    EXPECT_EQ("any", Element::typeToName(Element::any));
    EXPECT_EQ("unknown", Element::typeToName((Element::types)123));
}

Jelte Jansen's avatar
Jelte Jansen committed
73
TEST(Element, from_and_to_json) {
74
75
76
    // a set of inputs that are the same when converted to json and
    // back to a string (tests for inputs that have equivalent, but
    // different string representations when converted back are below)
77
    ConstElementPtr el;
78
79
80
81
    std::vector<std::string> sv;

    sv.push_back("12");
    sv.push_back("1.1");
82
83
    sv.push_back("true");
    sv.push_back("false");
84
    sv.push_back("\"asdf\"");
85
    sv.push_back("null");
86
    sv.push_back("[ 1, 2, 3, 4 ]");
87
88
    sv.push_back("{ \"name\": \"foo\", \"value\": 47806 }");
    sv.push_back("[ { \"a\": 1, \"b\": \"c\" }, { \"a\": 2, \"b\": \"d\" } ]");
89
90
91
92
93
94
    sv.push_back("8.23");
    sv.push_back("123.456");
    sv.push_back("null");
    sv.push_back("-1");
    sv.push_back("-1.234");
    sv.push_back("-123.456");
95
96
97
    // We should confirm that our string handling is 8-bit clean.
    // At one point we were using char-length data and comparing to EOF,
    // which means that character '\xFF' would not parse properly.
98
    sv.push_back("\"\xFF\"");
99

100
    BOOST_FOREACH(const std::string& s, sv) {
Jelte Jansen's avatar
Jelte Jansen committed
101
        // test << operator, which uses Element::str()
102
        std::ostringstream stream;
103
        el = Element::fromJSON(s);
104
105
        stream << *el;
        EXPECT_EQ(s, stream.str());
Jelte Jansen's avatar
Jelte Jansen committed
106
107
108
109

        // test toWire(ostream), which should also be the same now
        std::ostringstream wire_stream;
        el->toWire(wire_stream);
110
        EXPECT_EQ(s, wire_stream.str());
111
112
113
114
    }

    // some parse errors
    try {
115
        Element::fromJSON("{1}");
116
    } catch (const isc::data::JSONError& pe) {
117
        std::string s = std::string(pe.what());
118
        EXPECT_EQ("String expected in <string>:1:3", s);
119
    }
120

121
122
    sv.clear();
    sv.push_back("{1}");
123
    //ElementPtr ep = Element::fromJSON("\"aaa\nbbb\"err");
124
125
126
127
128
129
    //std::cout << ep << std::endl;
    sv.push_back("\n\nTru");
    sv.push_back("{ \n \"aaa\nbbb\"err:");
    sv.push_back("{ \t\n \"aaa\nbbb\"\t\n\n:\n True, \"\\\"");
    sv.push_back("{ \"a\": None}");
    sv.push_back("");
Jelte Jansen's avatar
Jelte Jansen committed
130
    sv.push_back("nul");
131
132
133
134
    sv.push_back("hello\"foobar\"");
    sv.push_back("\"foobar\"hello");
    sv.push_back("[]hello");
    sv.push_back("{}hello");
135
136
137
138
139
    // String not delimited correctly
    sv.push_back("\"hello");
    sv.push_back("hello\"");


140
    BOOST_FOREACH(std::string s, sv) {
Jelte Jansen's avatar
Jelte Jansen committed
141
        EXPECT_THROW(el = Element::fromJSON(s), isc::data::JSONError);
142
143
    }

144
145
    // some json specific format tests, here the str() output is
    // different from the string input
146
    EXPECT_EQ("100", Element::fromJSON("+100")->str());
147
    EXPECT_EQ("100", Element::fromJSON("1e2")->str());
148
149
    EXPECT_EQ("100", Element::fromJSON("+1e2")->str());
    EXPECT_EQ("-100", Element::fromJSON("-1e2")->str());
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

    // LONG_MAX, -LONG_MAX, LONG_MIN test
    std::ostringstream longmax, minus_longmax, longmin;
    longmax << LONG_MAX;
    minus_longmax << -LONG_MAX;
    longmin << LONG_MIN;
    EXPECT_NO_THROW( {
       EXPECT_EQ(longmax.str(), Element::fromJSON(longmax.str())->str());
    });
    EXPECT_NO_THROW( {
       EXPECT_EQ(minus_longmax.str(), Element::fromJSON(minus_longmax.str())->str());
    });
    EXPECT_NO_THROW( {
       EXPECT_EQ(longmin.str(), Element::fromJSON(longmin.str())->str());
    });

166
    EXPECT_EQ("0.01", Element::fromJSON("1e-2")->str());
Jelte Jansen's avatar
Jelte Jansen committed
167
    EXPECT_EQ("0.01", Element::fromJSON(".01")->str());
168
    EXPECT_EQ("-0.01", Element::fromJSON("-1e-2")->str());
169
170
171
172
    EXPECT_EQ("1.2", Element::fromJSON("1.2")->str());
    EXPECT_EQ("1", Element::fromJSON("1.0")->str());
    EXPECT_EQ("120", Element::fromJSON("1.2e2")->str());
    EXPECT_EQ("100", Element::fromJSON("1.0e2")->str());
173
    EXPECT_EQ("100", Element::fromJSON("1.0E2")->str());
174
175
    EXPECT_EQ("0.01", Element::fromJSON("1.0e-2")->str());
    EXPECT_EQ("0.012", Element::fromJSON("1.2e-2")->str());
176
    EXPECT_EQ("0.012", Element::fromJSON("1.2E-2")->str());
177
178
179
180
181
182
    EXPECT_EQ("null", Element::fromJSON("Null")->str());
    EXPECT_EQ("null", Element::fromJSON("NULL")->str());
    EXPECT_EQ("false", Element::fromJSON("False")->str());
    EXPECT_EQ("false", Element::fromJSON("FALSE")->str());
    EXPECT_EQ("true", Element::fromJSON("True")->str());
    EXPECT_EQ("true", Element::fromJSON("TRUE")->str());
183
184
185
    EXPECT_EQ("\"\"", Element::fromJSON("  \n \t \r \f \b \"\" \n \f \t \r \b")->str());
    EXPECT_EQ("{  }", Element::fromJSON("{  \n  \r \t  \b \f }")->str());
    EXPECT_EQ("[  ]", Element::fromJSON("[  \n  \r \f \t  \b  ]")->str());
Jelte Jansen's avatar
Jelte Jansen committed
186

Jelte Jansen's avatar
Jelte Jansen committed
187
    // number overflows
Jelte Jansen's avatar
Jelte Jansen committed
188
189
    EXPECT_THROW(Element::fromJSON("12345678901234567890")->str(), JSONError);
    EXPECT_THROW(Element::fromJSON("1.1e12345678901234567890")->str(), JSONError);
190
    EXPECT_THROW(Element::fromJSON("-1.1e12345678901234567890")->str(), JSONError);
Jelte Jansen's avatar
Jelte Jansen committed
191
192
    EXPECT_THROW(Element::fromJSON("1e12345678901234567890")->str(), JSONError);
    EXPECT_THROW(Element::fromJSON("1e50000")->str(), JSONError);
193
194
    // number underflow
    EXPECT_THROW(Element::fromJSON("1.1e-12345678901234567890")->str(), JSONError);
Jelte Jansen's avatar
Jelte Jansen committed
195

196
197
}

198
199
200
201
template <typename T>
void
testGetValueInt() {
    T el;
Jelte Jansen's avatar
Jelte Jansen committed
202
    long int i;
Jelte Jansen's avatar
Jelte Jansen committed
203
204
    double d;
    bool b;
205
    std::string s;
206
207
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
208
209

    el = Element::create(1);
210
    EXPECT_NO_THROW(el->intValue());
211
212
213
214
215
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
Jelte Jansen's avatar
Jelte Jansen committed
216
217
218
219
220
221
    EXPECT_TRUE(el->getValue(i));
    EXPECT_FALSE(el->getValue(d));
    EXPECT_FALSE(el->getValue(b));
    EXPECT_FALSE(el->getValue(s));
    EXPECT_FALSE(el->getValue(v));
    EXPECT_FALSE(el->getValue(m));
222
223
    EXPECT_EQ(1, i);
}
224

225
226
227
228
229
230
231
232
233
234
template <typename T>
void
testGetValueDouble() {
    T el;
    long int i;
    double d;
    bool b;
    std::string s;
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
235
236

    el = Element::create(1.1);
237
    EXPECT_THROW(el->intValue(), TypeError);
238
    EXPECT_NO_THROW(el->doubleValue());
239
240
241
242
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
Jelte Jansen's avatar
Jelte Jansen committed
243
244
245
246
247
248
    EXPECT_FALSE(el->getValue(i));
    EXPECT_TRUE(el->getValue(d));
    EXPECT_FALSE(el->getValue(b));
    EXPECT_FALSE(el->getValue(s));
    EXPECT_FALSE(el->getValue(v));
    EXPECT_FALSE(el->getValue(m));
249
250
251
252
253
254
255
256
257
258
259
260
261
    EXPECT_EQ(1.1, d);
}

template <typename T>
void
testGetValueBool() {
    T el;
    long int i;
    double d;
    bool b;
    std::string s;
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
262
263

    el = Element::create(true);
264
265
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
266
    EXPECT_NO_THROW(el->boolValue());
267
268
269
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
Jelte Jansen's avatar
Jelte Jansen committed
270
271
272
273
274
275
    EXPECT_FALSE(el->getValue(i));
    EXPECT_FALSE(el->getValue(d));
    EXPECT_TRUE(el->getValue(b));
    EXPECT_FALSE(el->getValue(s));
    EXPECT_FALSE(el->getValue(v));
    EXPECT_FALSE(el->getValue(m));
276
277
278
279
280
281
282
283
284
285
286
287
288
    EXPECT_EQ(true, b);
}

template <typename T>
void
testGetValueString() {
    T el;
    long int i;
    double d;
    bool b;
    std::string s;
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
289
290

    el = Element::create("foo");
291
292
293
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
294
    EXPECT_NO_THROW(el->stringValue());
295
296
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
Jelte Jansen's avatar
Jelte Jansen committed
297
298
299
300
301
302
    EXPECT_FALSE(el->getValue(i));
    EXPECT_FALSE(el->getValue(d));
    EXPECT_FALSE(el->getValue(b));
    EXPECT_TRUE(el->getValue(s));
    EXPECT_FALSE(el->getValue(v));
    EXPECT_FALSE(el->getValue(m));
303
304
305
306
307
308
309
310
311
312
313
314
315
    EXPECT_EQ("foo", s);
}

template <typename T>
void
testGetValueList() {
    T el;
    long int i;
    double d;
    bool b;
    std::string s;
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
316

317
    el = Element::createList();
318
319
320
321
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
322
    EXPECT_NO_THROW(el->listValue());
323
    EXPECT_THROW(el->mapValue(), TypeError);
Jelte Jansen's avatar
Jelte Jansen committed
324
325
326
327
328
329
330
    EXPECT_FALSE(el->getValue(i));
    EXPECT_FALSE(el->getValue(d));
    EXPECT_FALSE(el->getValue(b));
    EXPECT_FALSE(el->getValue(s));
    EXPECT_TRUE(el->getValue(v));
    EXPECT_FALSE(el->getValue(m));
    EXPECT_EQ("[  ]", el->str());
331
332
333
334
335
336
337
338
339
340
341
342
}

template <typename T>
void
testGetValueMap() {
    T el;
    long int i;
    double d;
    bool b;
    std::string s;
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
343

344
    el = Element::createMap();
345
346
347
348
349
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
350
    EXPECT_NO_THROW(el->mapValue());
Jelte Jansen's avatar
Jelte Jansen committed
351
352
353
354
355
356
    EXPECT_FALSE(el->getValue(i));
    EXPECT_FALSE(el->getValue(d));
    EXPECT_FALSE(el->getValue(b));
    EXPECT_FALSE(el->getValue(s));
    EXPECT_FALSE(el->getValue(v));
    EXPECT_TRUE(el->getValue(m));
Mukund Sivaraman's avatar
Mukund Sivaraman committed
357
    EXPECT_EQ("{  }", el->str());
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
}

TEST(Element, create_and_value_throws) {
    // this test checks whether elements throw exceptions if the
    // incorrect type is requested
    ElementPtr el;
    ConstElementPtr cel;
    long int i = 0;
    double d = 0.0;
    bool b = false;
    std::string s("asdf");
    std::vector<ConstElementPtr> v;
    std::map<std::string, ConstElementPtr> m;
    ConstElementPtr tmp;

    testGetValueInt<ElementPtr>();
    testGetValueInt<ConstElementPtr>();

    el = Element::create(1);
    i = 2;
    EXPECT_TRUE(el->setValue(i));
    EXPECT_EQ(2, el->intValue());
    EXPECT_FALSE(el->setValue(d));
    EXPECT_FALSE(el->setValue(b));
    EXPECT_FALSE(el->setValue(s));
    EXPECT_FALSE(el->setValue(v));
    EXPECT_FALSE(el->setValue(m));
    EXPECT_THROW(el->get(1), TypeError);
    EXPECT_THROW(el->set(1, el), TypeError);
    EXPECT_THROW(el->add(el), TypeError);
    EXPECT_THROW(el->remove(1), TypeError);
    EXPECT_THROW(el->size(), TypeError);
    EXPECT_THROW(el->get("foo"), TypeError);
    EXPECT_THROW(el->set("foo", el), TypeError);
    EXPECT_THROW(el->remove("foo"), TypeError);
    EXPECT_THROW(el->contains("foo"), TypeError);
    EXPECT_FALSE(el->find("foo", tmp));

    testGetValueDouble<ElementPtr>();
    testGetValueDouble<ConstElementPtr>();
398

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
    el = Element::create(1.1);
    d = 2.2;
    EXPECT_TRUE(el->setValue(d));
    EXPECT_EQ(2.2, el->doubleValue());
    EXPECT_FALSE(el->setValue(i));
    EXPECT_FALSE(el->setValue(b));
    EXPECT_FALSE(el->setValue(s));
    EXPECT_FALSE(el->setValue(v));
    EXPECT_FALSE(el->setValue(m));
    EXPECT_THROW(el->get(1), TypeError);
    EXPECT_THROW(el->set(1, el), TypeError);
    EXPECT_THROW(el->add(el), TypeError);
    EXPECT_THROW(el->remove(1), TypeError);
    EXPECT_THROW(el->size(), TypeError);
    EXPECT_THROW(el->get("foo"), TypeError);
    EXPECT_THROW(el->set("foo", el), TypeError);
    EXPECT_THROW(el->remove("foo"), TypeError);
    EXPECT_THROW(el->contains("foo"), TypeError);
    EXPECT_FALSE(el->find("foo", tmp));

    testGetValueBool<ElementPtr>();
    testGetValueBool<ConstElementPtr>();

    el = Element::create(true);
    b = false;
    EXPECT_TRUE(el->setValue(b));
    EXPECT_FALSE(el->boolValue());
    EXPECT_FALSE(el->setValue(i));
    EXPECT_FALSE(el->setValue(d));
    EXPECT_FALSE(el->setValue(s));
    EXPECT_FALSE(el->setValue(v));
    EXPECT_FALSE(el->setValue(m));
    EXPECT_THROW(el->get(1), TypeError);
    EXPECT_THROW(el->set(1, el), TypeError);
    EXPECT_THROW(el->add(el), TypeError);
    EXPECT_THROW(el->remove(1), TypeError);
    EXPECT_THROW(el->size(), TypeError);
    EXPECT_THROW(el->get("foo"), TypeError);
    EXPECT_THROW(el->set("foo", el), TypeError);
    EXPECT_THROW(el->remove("foo"), TypeError);
    EXPECT_THROW(el->contains("foo"), TypeError);
    EXPECT_FALSE(el->find("foo", tmp));

    testGetValueString<ElementPtr>();
    testGetValueString<ConstElementPtr>();

    el = Element::create("foo");
    s = "bar";
    EXPECT_TRUE(el->setValue(s));
    EXPECT_EQ("bar", el->stringValue());
    EXPECT_FALSE(el->setValue(i));
    EXPECT_FALSE(el->setValue(b));
    EXPECT_FALSE(el->setValue(d));
    EXPECT_FALSE(el->setValue(v));
    EXPECT_FALSE(el->setValue(m));
    EXPECT_THROW(el->get(1), TypeError);
    EXPECT_THROW(el->set(1, el), TypeError);
    EXPECT_THROW(el->add(el), TypeError);
    EXPECT_THROW(el->remove(1), TypeError);
    EXPECT_THROW(el->size(), TypeError);
    EXPECT_THROW(el->get("foo"), TypeError);
    EXPECT_THROW(el->set("foo", el), TypeError);
    EXPECT_THROW(el->remove("foo"), TypeError);
    EXPECT_THROW(el->contains("foo"), TypeError);
    EXPECT_FALSE(el->find("foo", tmp));

    testGetValueList<ElementPtr>();
    testGetValueList<ConstElementPtr>();

    el = Element::createList();
    v.push_back(Element::create(1));
    EXPECT_TRUE(el->setValue(v));
    EXPECT_EQ("[ 1 ]", el->str());

    testGetValueMap<ElementPtr>();
    testGetValueMap<ConstElementPtr>();

    el = Element::createMap();
477
478
    EXPECT_NO_THROW(el->set("foo", Element::create("bar")));
    EXPECT_EQ("{ \"foo\": \"bar\" }", el->str());
479
480
}

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
// Helper for escape check; it puts the given string in a StringElement,
// then checks for the following conditions:
// stringValue() must be same as input
// toJSON() output must be escaped
// fromJSON() on the previous output must result in original input
void
escapeHelper(const std::string& input, const std::string& expected) {
    StringElement str_element = StringElement(input);
    EXPECT_EQ(input, str_element.stringValue());
    std::stringstream os;
    str_element.toJSON(os);
    EXPECT_EQ(expected, os.str());
    ElementPtr str_element2 = Element::fromJSON(os.str());
    EXPECT_EQ(str_element.stringValue(), str_element2->stringValue());
}

TEST(Element, escape) {
    // Test whether quotes are escaped correctly when creating direct
    // String elements.
    escapeHelper("foo\"bar", "\"foo\\\"bar\"");
    escapeHelper("foo\\bar", "\"foo\\\\bar\"");
502
503
504
505
506
    escapeHelper("foo\bbar", "\"foo\\bbar\"");
    escapeHelper("foo\fbar", "\"foo\\fbar\"");
    escapeHelper("foo\nbar", "\"foo\\nbar\"");
    escapeHelper("foo\rbar", "\"foo\\rbar\"");
    escapeHelper("foo\tbar", "\"foo\\tbar\"");
507
508
509
    // Bad escapes
    EXPECT_THROW(Element::fromJSON("\\a"), JSONError);
    EXPECT_THROW(Element::fromJSON("\\"), JSONError);
510
511
512
513
514
    // Can't have escaped quotes outside strings
    EXPECT_THROW(Element::fromJSON("\\\"\\\""), JSONError);
    // Inside strings is OK
    EXPECT_NO_THROW(Element::fromJSON("\"\\\"\\\"\""));
    // A whitespace test
Mukund Sivaraman's avatar
Mukund Sivaraman committed
515
    EXPECT_NO_THROW(Element::fromJSON("\"  \n  \r \t \f  \n \n    \t\""));
516
517
}

518
519
TEST(Element, ListElement) {
    // this function checks the specific functions for ListElements
520
    ElementPtr el = Element::fromJSON("[ 1, \"bar\", 3 ]");
521
522
523
    EXPECT_EQ(el->get(0)->intValue(), 1);
    EXPECT_EQ(el->get(1)->stringValue(), "bar");
    EXPECT_EQ(el->get(2)->intValue(), 3);
524

525
    el->set(0, Element::fromJSON("\"foo\""));
526
    EXPECT_EQ(el->get(0)->stringValue(), "foo");
527
528

    el->add(Element::create(47806));
529
    EXPECT_EQ(el->get(3)->intValue(), 47806);
530
531
532
533
534
535
536
537
538

    el->remove(1);
    el->remove(1);
    EXPECT_EQ(el->str(), "[ \"foo\", 47806 ]");

    // hmm, it errors on EXPECT_THROW(el->get(3), std::out_of_range)
    EXPECT_ANY_THROW(el->get(3));

    el->add(Element::create(32));
539
540
541
542
543
544
545
    EXPECT_EQ(32, el->get(2)->intValue());

    // boundary condition tests for set()
    el->set(2, Element::create(0)); // update the last entry of the list
    EXPECT_EQ(0, el->get(2)->intValue());
    // attempt of set beyond the range of list should trigger an exception.
    EXPECT_ANY_THROW(el->set(3, Element::create(0)));
546
547
548
549
}

TEST(Element, MapElement) {
    // this function checks the specific functions for ListElements
550
    ElementPtr el = Element::fromJSON("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
551
    ConstElementPtr el2;
552

553
554
    EXPECT_EQ(el->get("name")->stringValue(), "foo");
    EXPECT_EQ(el->get("value2")->getType(), Element::map);
555

556
    EXPECT_TRUE(isNull(el->get("value3")));
557
558

    el->set("value3", Element::create(47806));
559
    EXPECT_EQ(el->get("value3")->intValue(), 47806);
560
561

    el->remove("value3");
562
    EXPECT_TRUE(isNull(el->get("value3")));
563

564
    EXPECT_EQ(el->find("value2/number")->intValue(), 42);
565
    EXPECT_TRUE(isNull(el->find("value2/nothing/")));
566

567
568
    EXPECT_EQ(el->find("value1")->stringValue(), "bar");
    EXPECT_EQ(el->find("value1/")->stringValue(), "bar");
569

570
    EXPECT_TRUE(el->find("value1", el2));
571
    EXPECT_EQ("bar", el2->stringValue());
572
    EXPECT_FALSE(el->find("name/error", el2));
573
574
575
576
577
578
579
580

    // A map element whose (only) element has the maximum length of tag.
    string long_maptag("0123456789abcdef1123456789abcdef2123456789abcdef"
                       "3123456789abcdef4123456789abcdef5123456789abcdef"
                       "6123456789abcdef7123456789abcdef8123456789abcdef"
                       "9123456789abcdefa123456789abcdefb123456789abcdef"
                       "c123456789abcdefd123456789abcdefe123456789abcdef"
                       "f123456789abcde");
581

582
    EXPECT_EQ(255, long_maptag.length()); // check prerequisite
583
    el = Element::fromJSON("{ \"" + long_maptag + "\": \"bar\"}");
584
585
    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());

586
587
    el = Element::createMap();
    el->set(long_maptag, Element::create("bar"));
588
589
    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());

590
    // A one-byte longer tag should still be allowed
591
    long_maptag.push_back('f');
592
593
594
    el = Element::fromJSON("{ \"" + long_maptag + "\": \"bar\"}");
    el->set(long_maptag, Element::create("bar"));
    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
595

596
597
598
}

TEST(Element, to_and_from_wire) {
599
600
601
602
603
604
605
    // Wire format is now plain JSON.
    EXPECT_EQ("1", Element::create(1)->toWire());
    EXPECT_EQ("1.1", Element::create(1.1)->toWire());
    EXPECT_EQ("true", Element::create(true)->toWire());
    EXPECT_EQ("false", Element::create(false)->toWire());
    EXPECT_EQ("null", Element::create()->toWire());
    EXPECT_EQ("\"a string\"", Element::create("a string")->toWire());
606
607
    EXPECT_EQ("[ \"a\", \"list\" ]", Element::fromJSON("[ \"a\", \"list\" ]")->toWire());
    EXPECT_EQ("{ \"a\": \"map\" }", Element::fromJSON("{ \"a\": \"map\" }")->toWire());
608
609

    EXPECT_EQ("1", Element::fromWire("1")->str());
Jelte Jansen's avatar
Jelte Jansen committed
610
611
612
613

    std::stringstream ss;
    ss << "1";
    EXPECT_EQ("1", Element::fromWire(ss, 1)->str());
614
615

    // Some malformed JSON input
616
617
618
619
620
621
622
623
    EXPECT_THROW(Element::fromJSON("{ "), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\" "), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": "), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": \"b\""), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": {"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": {}"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": []"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\": [ }"), isc::data::JSONError);
624
625
626
    EXPECT_THROW(Element::fromJSON("{\":"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("]"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
627
628
    EXPECT_THROW(Element::fromJSON("[ 1, 2, {}"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("[ 1, 2, { ]"), isc::data::JSONError);
Jelte Jansen's avatar
Jelte Jansen committed
629
630
631
632
633
    EXPECT_THROW(Element::fromJSON("[ "), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{{}}"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{[]}"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("{ \"a\", \"b\" }"), isc::data::JSONError);
    EXPECT_THROW(Element::fromJSON("[ \"a\": \"b\" ]"), isc::data::JSONError);
634
635
}

636
ConstElementPtr
637
efs(const std::string& str) {
JINMEI Tatuya's avatar
JINMEI Tatuya committed
638
    return (Element::fromJSON(str));
639
640
641
}

TEST(Element, equals) {
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
    EXPECT_EQ(*efs("1"), *efs("1"));
    EXPECT_NE(*efs("1"), *efs("2"));
    EXPECT_NE(*efs("1"), *efs("\"1\""));
    EXPECT_NE(*efs("1"), *efs("[]"));
    EXPECT_NE(*efs("1"), *efs("True"));
    EXPECT_NE(*efs("1"), *efs("{}"));

    EXPECT_EQ(*efs("1.1"), *efs("1.1"));
    EXPECT_NE(*efs("1.0"), *efs("1"));
    EXPECT_NE(*efs("1.1"), *efs("\"1\""));
    EXPECT_NE(*efs("1.1"), *efs("[]"));
    EXPECT_NE(*efs("1.1"), *efs("True"));
    EXPECT_NE(*efs("1.1"), *efs("{}"));

    EXPECT_EQ(*efs("True"), *efs("True"));
    EXPECT_NE(*efs("True"), *efs("False"));
    EXPECT_NE(*efs("True"), *efs("1"));
    EXPECT_NE(*efs("True"), *efs("\"1\""));
    EXPECT_NE(*efs("True"), *efs("[]"));
    EXPECT_NE(*efs("True"), *efs("{}"));

    EXPECT_EQ(*efs("\"foo\""), *efs("\"foo\""));
    EXPECT_NE(*efs("\"foo\""), *efs("\"bar\""));
    EXPECT_NE(*efs("\"foo\""), *efs("1"));
    EXPECT_NE(*efs("\"foo\""), *efs("\"1\""));
    EXPECT_NE(*efs("\"foo\""), *efs("True"));
    EXPECT_NE(*efs("\"foo\""), *efs("[]"));
    EXPECT_NE(*efs("\"foo\""), *efs("{}"));

    EXPECT_EQ(*efs("[]"), *efs("[]"));
    EXPECT_EQ(*efs("[ 1, 2, 3 ]"), *efs("[ 1, 2, 3 ]"));
    EXPECT_EQ(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 1], 2.2 ]"));
    EXPECT_NE(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 2], 2.2 ]"));
    EXPECT_NE(*efs("[]"), *efs("[1]"));
    EXPECT_NE(*efs("[]"), *efs("1"));
    EXPECT_NE(*efs("[]"), *efs("\"1\""));
    EXPECT_NE(*efs("[]"), *efs("{}"));

    EXPECT_EQ(*efs("{}"), *efs("{}"));
    EXPECT_EQ(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"foo\": \"bar\" }"));
    EXPECT_EQ(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("1"));
    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("\"1\""));
    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("[]"));
    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{}"));
    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"something\": \"different\" }"));

    EXPECT_EQ(*efs("null"), *Element::create());
692
693
694
}

TEST(Element, removeIdentical) {
695
    ElementPtr a = Element::createMap();
696
697
    ConstElementPtr b = Element::createMap();
    ConstElementPtr c = Element::createMap();
698
    removeIdentical(a, b);
699
    EXPECT_EQ(*a, *c);
700

701
702
    a = Element::fromJSON("{ \"a\": 1 }");
    b = Element::fromJSON("{ \"a\": 1 }");
703
    c = Element::createMap();
704
    removeIdentical(a, b);
705
    EXPECT_EQ(*a, *c);
706

707
    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
708
    b = Element::createMap();
709
    c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
710
    removeIdentical(a, b);
711
    EXPECT_EQ(*a, *c);
712

713
714
    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
715
    c = Element::createMap();
716
    removeIdentical(a, b);
717
    EXPECT_EQ(*a, *c);
718

719
720
721
    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
    c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
722
    removeIdentical(a, b);
723
    EXPECT_EQ(*a, *c);
724

725
    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
726
    b = Element::createMap();
727
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
728
    removeIdentical(a, b);
729
    EXPECT_EQ(*a, *c);
730

731
732
    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
733
    c = Element::createMap();
734
    removeIdentical(a, b);
735
    EXPECT_EQ(*a, *c);
736

737
738
739
    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
740
    removeIdentical(a, b);
741
    EXPECT_EQ(*a, *c);
Jelte Jansen's avatar
Jelte Jansen committed
742

743
744
745
746
747
748
    a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
    b = Element::fromJSON("{ \"c\": 3, \"b\": 2 }");
    c = Element::fromJSON("{ \"a\": 1 }");
    removeIdentical(a, b);
    EXPECT_EQ(*a, *c);

Jelte Jansen's avatar
Jelte Jansen committed
749
    EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)), TypeError);
750
}
751

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
TEST(Element, constRemoveIdentical) {
    ConstElementPtr a = Element::createMap();
    ConstElementPtr b = Element::createMap();
    ConstElementPtr c = Element::createMap();
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": 1 }");
    b = Element::fromJSON("{ \"a\": 1 }");
    c = Element::createMap();
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::createMap();
    c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    c = Element::createMap();
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
    c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::createMap();
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    c = Element::createMap();
    EXPECT_EQ(*removeIdentical(a, b), *c);

    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    EXPECT_EQ(*removeIdentical(a, b), *c);

793
794
795
796
797
    a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
    b = Element::fromJSON("{ \"c\": 3, \"b\": 2 }");
    c = Element::fromJSON("{ \"a\": 1 }");
    EXPECT_EQ(*removeIdentical(a, b), *c);

798
799
800
801
802
    EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)),
                 TypeError);
}

TEST(Element, merge) {
803
804
    ElementPtr a = Element::createMap();
    ElementPtr b = Element::createMap();
805
    ConstElementPtr c = Element::createMap();
806
    merge(a, b);
807
    EXPECT_EQ(*a, *c);
808

809
    a = Element::fromJSON("1");
810
    b = Element::createMap();
811
812
    EXPECT_THROW(merge(a, b), TypeError);

813
    a = Element::createMap();
814
815
    b = Element::fromJSON("{ \"a\": 1 }");
    c = Element::fromJSON("{ \"a\": 1 }");
816
    merge(a, b);
817
    EXPECT_EQ(*a, *c);
818
819
820
821
822

    a = Element::createMap();
    b = Element::fromJSON("{ \"a\": 1 }");
    c = Element::fromJSON("{ \"a\": 1 }");
    merge(b, a);
823
    EXPECT_EQ(*b, *c);
824

825
826
827
    a = Element::fromJSON("{ \"a\": 1 }");
    b = Element::fromJSON("{ \"a\": 2 }");
    c = Element::fromJSON("{ \"a\": 2 }");
828
    merge(a, b);
829
    EXPECT_EQ(*a, *c);
830
831
832
833
834

    a = Element::fromJSON("{ \"a\": 1 }");
    b = Element::fromJSON("{ \"a\": 2 }");
    c = Element::fromJSON("{ \"a\": 1 }");
    merge(b, a);
835
    EXPECT_EQ(*b, *c);
836

837
838
839
    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
    c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
840
    merge(a, b);
841
    EXPECT_EQ(*a, *c);
842
843
844
845
846

    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    merge(b, a);
847
    EXPECT_EQ(*b, *c);
848

Jelte Jansen's avatar
Jelte Jansen committed
849
850
851
852
    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": null }");
    c = Element::fromJSON("{  }");
    merge(a, b);
853
    EXPECT_EQ(*a, *c);
854
855
856
857
858

    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    b = Element::fromJSON("{ \"a\": null }");
    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
    merge(b, a);
859
    EXPECT_EQ(*b, *c);
860

861
862
863
864
865
    // And some tests with multiple values
    a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
    c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
    merge(a, b);
866
    EXPECT_EQ(*a, *c);
867
868
869
870
871

    a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
    b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
    c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
    merge(b, a);
872
    EXPECT_EQ(*b, *c);
873
874
875
876
877

    a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
    b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
    c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
    merge(a, b);
878
    EXPECT_EQ(*a, *c);
879
880
881
882
883

    a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
    b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
    c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
    merge(b, a);
884
    EXPECT_EQ(*b, *c);
Jelte Jansen's avatar
Jelte Jansen committed
885

886
}
887
}