data_unittests.cc 17 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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.

// $Id$

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

#include <data.h>

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

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

32
TEST(Element, type) {
33
    // this tests checks whether the getType() function returns the
34
35
    // correct type
    IntElement int_el = IntElement(1);
36
    EXPECT_EQ(int_el.getType(), Element::integer);
37
    DoubleElement double_el = DoubleElement(1.0);
38
    EXPECT_EQ(double_el.getType(), Element::real);
39
    BoolElement bool_el = BoolElement(true);
40
    EXPECT_EQ(bool_el.getType(), Element::boolean);
41
    StringElement str_el = StringElement("foo");
42
    EXPECT_EQ(str_el.getType(), Element::string);
43
44
    std::vector<ElementPtr> v;
    ListElement list_el = ListElement(v);
45
    EXPECT_EQ(list_el.getType(), Element::list);
46
47
    std::map<std::string, ElementPtr> m;
    MapElement map_el = MapElement(m);
48
    EXPECT_EQ(map_el.getType(), Element::map);
49
50
}

51
TEST(Element, from_and_to_str) {
52
53
54
55
56
57
58
59
60
61
62
63
    // this test checks whether the str() method returns the same
    // string that was used for creation
    ElementPtr el;
    std::vector<std::string> sv;

    sv.push_back("12");
    sv.push_back("1.1");
    sv.push_back("True");
    sv.push_back("False");
    sv.push_back("\"asdf\"");
    sv.push_back("[ 1, 2, 3, 4 ]");
    sv.push_back("{\"name\": \"foo\", \"value\": 47806}");
64
    sv.push_back("[ {\"a\": 1, \"b\": \"c\"}, {\"a\": 2, \"b\": \"d\"} ]");
65
66

    BOOST_FOREACH(std::string s, sv) {
67
68
        // also test << operator, which uses Element::str()
        std::ostringstream stream;
69
        el = Element::createFromString(s);
70
71
72
73
74
75
76
77
78
        stream << el;
        EXPECT_EQ(stream.str(), s);
    }

    // some parse errors
    try {
        Element::createFromString("{1}");
    } catch (isc::data::ParseError pe) {
        std::string s = std::string(pe.what());
79
        EXPECT_EQ(s, "String expected in <string>:1:3");
80
    }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    
    sv.clear();
    sv.push_back("{1}");
    //ElementPtr ep = Element::createFromString("\"aaa\nbbb\"err");
    //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("");
    BOOST_FOREACH(std::string s, sv) {
        
        EXPECT_THROW(el = Element::createFromString(s), isc::data::ParseError);
    }

96
97
98
99
100
101
102
103
}

TEST(Element, create_and_value_throws) {
    // this test checks whether elements throw exceptions if the
    // incorrect type is requested
    ElementPtr el;

    el = Element::create(1);
104
105
106
107
108
    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);
109
110

    el = Element::create(1.1);
111
112
113
114
115
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
116
117

    el = Element::create(true);
118
119
120
121
122
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
123
124

    el = Element::create("foo");
125
126
127
128
129
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->listValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
130
131
132

    std::vector<ElementPtr> v;
    el = Element::create(v);
133
134
135
136
137
    EXPECT_THROW(el->intValue(), TypeError);
    EXPECT_THROW(el->doubleValue(), TypeError);
    EXPECT_THROW(el->boolValue(), TypeError);
    EXPECT_THROW(el->stringValue(), TypeError);
    EXPECT_THROW(el->mapValue(), TypeError);
138
139
140

    std::map<std::string, ElementPtr> m;
    el = Element::create(m);
141
142
143
144
145
    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);
146
147
148
149
150

}

TEST(Element, ListElement) {
    // this function checks the specific functions for ListElements
151
152
153
154
    ElementPtr el = Element::createFromString("[ 1, \"bar\", 3 ]");
    EXPECT_EQ(el->get(0)->intValue(), 1);
    EXPECT_EQ(el->get(1)->stringValue(), "bar");
    EXPECT_EQ(el->get(2)->intValue(), 3);
155

156
157
    el->set(0, Element::createFromString("\"foo\""));
    EXPECT_EQ(el->get(0)->stringValue(), "foo");
158
159

    el->add(Element::create(47806));
160
    EXPECT_EQ(el->get(3)->intValue(), 47806);
161
162
163
164
165
166
167
168
169

    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));
170
    EXPECT_EQ(el->get(2)->intValue(), 32);
171
172
}

173
174
175
176
177
178
179
180
181
namespace {
const string long_maptag("0123456789abcdef1123456789abcdef2123456789abcdef"
                         "3123456789abcdef4123456789abcdef5123456789abcdef"
                         "6123456789abcdef7123456789abcdef8123456789abcdef"
                         "9123456789abcdefa123456789abcdefb123456789abcdef"
                         "c123456789abcdefd123456789abcdefe123456789abcdef"
                         "f123456789abcdef");
}

182
183
TEST(Element, MapElement) {
    // this function checks the specific functions for ListElements
184
    ElementPtr el = Element::createFromString("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
185
186
    ElementPtr el2;
    
187
188
    EXPECT_EQ(el->get("name")->stringValue(), "foo");
    EXPECT_EQ(el->get("value2")->getType(), Element::map);
189

190
    EXPECT_TRUE(isNull(el->get("value3")));
191
192

    el->set("value3", Element::create(47806));
193
    EXPECT_EQ(el->get("value3")->intValue(), 47806);
194
195

    el->remove("value3");
196
    EXPECT_TRUE(isNull(el->get("value3")));
197

198
    EXPECT_EQ(el->find("value2/number")->intValue(), 42);
199
    EXPECT_TRUE(isNull(el->find("value2/nothing/")));
200
   
201
202
    EXPECT_EQ(el->find("value1")->stringValue(), "bar");
    EXPECT_EQ(el->find("value1/")->stringValue(), "bar");
203
204
205
    
    EXPECT_TRUE(el->find("value1", el2));
    EXPECT_FALSE(el->find("name/error", el2));
206
207
208
209
210
211
212
213

    // A map element whose (only) element has the maximum length of tag.
    string long_maptag("0123456789abcdef1123456789abcdef2123456789abcdef"
                       "3123456789abcdef4123456789abcdef5123456789abcdef"
                       "6123456789abcdef7123456789abcdef8123456789abcdef"
                       "9123456789abcdefa123456789abcdefb123456789abcdef"
                       "c123456789abcdefd123456789abcdefe123456789abcdef"
                       "f123456789abcde");
214
215
    std::map<std::string, ElementPtr> long_maptag_map;
    
216
217
218
219
    EXPECT_EQ(255, long_maptag.length()); // check prerequisite
    el = Element::createFromString("{ \"" + long_maptag + "\": \"bar\"}");
    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());

220
221
222
223
    long_maptag_map[long_maptag] = Element::create("bar");
    el = Element::create(long_maptag_map);
    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());

224
225
226
227
228
    // A one-byte longer tag should trigger an exception.
    long_maptag.push_back('f');
    EXPECT_THROW(Element::createFromString("{ \"" + long_maptag +
                                           "\": \"bar\"}"),
                 ParseError);
229
230
231
232

    long_maptag_map[long_maptag] = Element::create("bar");
    EXPECT_THROW(Element::create(long_maptag_map), TypeError);

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
}

TEST(Element, to_and_from_wire) {
    ElementPtr el, decoded_el;
    std::string wire;
    std::vector<std::string> sv;
    std::vector<std::string> sw;
    std::stringstream bigstring, bigstring2;
    std::stringstream bigwire, bigwire2;

    sv.push_back("{\"name\": \"foo\"}");
    sw.push_back("Skan\004name\050\003foo");
    sv.push_back("{\"value2\": {\"number\": 42}}");
    sw.push_back("Skan\006value2\042\013\006number\046\00242");
    sv.push_back("{\"bool\": False, \"bool2\": True, \"real\": 2.34, \"string\": \"foo\"}");
    sw.push_back("Skan\004bool\045\0010\005bool2\045\0011\004real\047\0042\05634\006string\050\003foo");
    sv.push_back("{\"list\": [ 1, 2, 3, 4 ]}");
    sw.push_back("Skan\004list\043\014\046\0011\046\0012\046\0013\046\0014");

    // some big ones

    bigstring << "{\"bigstring\": \"";
    bigwire << "Skan\011bigstring\030\001\001";
    for (size_t i = 0; i < 257; i++) {
        bigstring << "x";
        bigwire << "x";
    }
    bigstring << "\"}";
    sv.push_back(bigstring.str());
    sw.push_back(bigwire.str());


    bigstring2 << "{\"bigstring2\": \"";
    bigwire2 << "Skan\012bigstring2\010";
    bigwire2 << '\000' << '\001' << '\000' << '\001';
    for (size_t i = 0; i < 65537; i++) {
        bigstring2 << "x";
        bigwire2 << "x";
    }
    bigstring2 << "\"}";
    sv.push_back(bigstring2.str());
    sw.push_back(bigwire2.str());


    BOOST_FOREACH(std::string s, sv) {
        // also test << operator, which uses Element::str()
        el = Element::createFromString(s);
        EXPECT_EQ(s, el->str());
        wire = el->toWire();
        /*
        std::cout << "Encoded wire format:" << std::endl;
        my_print(wire);
        std::cout << "Expecting:" << std::endl;
        my_print(sw.at(0));
        */
        EXPECT_EQ(sw.at(0), wire);
        sw.erase(sw.begin());
        decoded_el = Element::fromWire(wire);
        EXPECT_EQ(s, decoded_el->str());
    }
    
    //EXPECT_THROW(Element::fromWire("Skan\004name\050\003foo"), DecodeError);
    EXPECT_THROW(Element::fromWire("Skan\004name\050"), DecodeError);
    EXPECT_THROW(Element::fromWire("Skan\004na"), DecodeError);
    EXPECT_THROW(Element::fromWire("Skan\004name\050\003fo"), DecodeError);
    EXPECT_NO_THROW(Element::fromWire("Skan\004name\041\003foo"));
    EXPECT_THROW(Element::fromWire("Skan\004name\041\003fo"), DecodeError);
    EXPECT_NO_THROW(Element::fromWire("Skan\004name\044\001a"));
    EXPECT_THROW(Element::fromWire("Skab\004name\050\003foo"), DecodeError);

    //EXPECT_EQ("\047\0031.2", Element::create(1.2)->toWire(0));
    EXPECT_EQ("\046\0011", Element::createFromString("[ 1 ]")->toWire(1));
305
306
307
308
309
310
311
312

    std::string ddef = "{\"data_specification\": {\"config_data\": [ {\"item_default\": \"Hello, world!\", \"item_name\": \"default_name\", \"item_optional\": False, \"item_type\": \"string\"}, {\"item_default\": [  ], \"item_name\": \"zone_list\", \"item_optional\": False, \"item_type\": \"list\", \"list_item_spec\": {\"item_name\": \"zone_name\", \"item_optional\": True, \"item_type\": \"string\"}} ], \"module_name\": \"Auth\"}}";
    //std::string ddef = "{\"aaa\": 123, \"test\": [  ], \"zzz\": 123}";
    ElementPtr ddef_el = Element::createFromString(ddef);
    std::string ddef_wire = ddef_el->toWire();
    ElementPtr ddef_el2 = Element::fromWire(ddef_wire);
    std::string ddef2 = ddef_el2->str();
    EXPECT_EQ(ddef, ddef2);
313
314
}

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
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
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
ElementPtr efs(const std::string& str) {
    return Element::createFromString(str);
}

TEST(Element, equals) {
    // why does EXPECT_EQ not work?
    EXPECT_TRUE(efs("1") == efs("1"));
    EXPECT_FALSE(efs("1") == efs("2"));
    EXPECT_FALSE(efs("1") == efs("\"1\""));
    EXPECT_FALSE(efs("1") == efs("[]"));
    EXPECT_FALSE(efs("1") == efs("True"));
    EXPECT_FALSE(efs("1") == efs("{}"));

    EXPECT_TRUE(efs("1.1") == efs("1.1"));
    EXPECT_FALSE(efs("1.0") == efs("1"));
    EXPECT_FALSE(efs("1.1") == efs("\"1\""));
    EXPECT_FALSE(efs("1.1") == efs("[]"));
    EXPECT_FALSE(efs("1.1") == efs("True"));
    EXPECT_FALSE(efs("1.1") == efs("{}"));

    EXPECT_TRUE(efs("True") == efs("True"));
    EXPECT_FALSE(efs("True") == efs("False"));
    EXPECT_FALSE(efs("True") == efs("1"));
    EXPECT_FALSE(efs("True") == efs("\"1\""));
    EXPECT_FALSE(efs("True") == efs("[]"));
    EXPECT_FALSE(efs("True") == efs("{}"));

    EXPECT_TRUE(efs("\"foo\"") == efs("\"foo\""));
    EXPECT_FALSE(efs("\"foo\"") == efs("\"bar\""));
    EXPECT_FALSE(efs("\"foo\"") == efs("1"));
    EXPECT_FALSE(efs("\"foo\"") == efs("\"1\""));
    EXPECT_FALSE(efs("\"foo\"") == efs("True"));
    EXPECT_FALSE(efs("\"foo\"") == efs("[]"));
    EXPECT_FALSE(efs("\"foo\"") == efs("{}"));

    EXPECT_TRUE(efs("[]") == efs("[]"));
    EXPECT_TRUE(efs("[ 1, 2, 3 ]") == efs("[ 1, 2, 3 ]"));
    EXPECT_TRUE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 1], 2.2 ]"));
    EXPECT_FALSE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 2], 2.2 ]"));
    EXPECT_FALSE(efs("[]") == efs("[1]"));
    EXPECT_FALSE(efs("[]") == efs("1"));
    EXPECT_FALSE(efs("[]") == efs("\"1\""));
    EXPECT_FALSE(efs("[]") == efs("{}"));

    EXPECT_TRUE(efs("{}") == efs("{}"));
    EXPECT_TRUE(efs("{ \"foo\": \"bar\" }") == efs("{ \"foo\": \"bar\" }"));
    EXPECT_TRUE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
    EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
    EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
    EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("1"));
    EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("\"1\""));
    EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("[]"));
    EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("{}"));
}

TEST(Element, removeIdentical) {
    ElementPtr a = Element::createFromString("{}");
    ElementPtr b = Element::createFromString("{}");
    ElementPtr c = Element::createFromString("{}");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": 1 }");
    b = Element::createFromString("{ \"a\": 1 }");
    c = Element::createFromString("{}");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::createFromString("{}");
    c = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    b = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
    c = Element::createFromString("{}");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

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

    a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    b = Element::createFromString("{}");
    c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    b = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    c = Element::createFromString("{}");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
    c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    removeIdentical(a, b);
    EXPECT_TRUE(a == c);
}
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

TEST(Element, merge)
{
    ElementPtr a = Element::createFromString("{}");
    ElementPtr b = Element::createFromString("{}");
    ElementPtr c = Element::createFromString("{}");
    merge(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("1");
    b = Element::createFromString("{}");
    EXPECT_THROW(merge(a, b), TypeError);

    a = Element::createFromString("{}");
    b = Element::createFromString("{ \"a\": 1 }");
    c = Element::createFromString("{ \"a\": 1 }");
    merge(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": 1 }");
    b = Element::createFromString("{ \"a\": 2 }");
    c = Element::createFromString("{ \"a\": 2 }");
    merge(a, b);
    EXPECT_TRUE(a == c);

    a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
    b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
    c = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
    merge(a, b);
    EXPECT_TRUE(a == c);

}