check-qdict.c 21.2 KB
Newer Older
L
Luiz Capitulino 已提交
1 2 3 4 5 6 7
/*
 * QDict unit-tests.
 *
 * Copyright (C) 2009 Red Hat Inc.
 *
 * Authors:
 *  Luiz Capitulino <lcapitulino@redhat.com>
L
Luiz Capitulino 已提交
8 9 10
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
L
Luiz Capitulino 已提交
11
 */
P
Peter Maydell 已提交
12
#include "qemu/osdep.h"
L
Luiz Capitulino 已提交
13

14 15
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
16
#include "qapi/error.h"
L
Luiz Capitulino 已提交
17 18 19 20 21 22 23 24
#include "qemu-common.h"

/*
 * Public Interface test-cases
 *
 * (with some violations to access 'private' data)
 */

A
Anthony Liguori 已提交
25
static void qdict_new_test(void)
L
Luiz Capitulino 已提交
26 27 28 29
{
    QDict *qdict;

    qdict = qdict_new();
A
Anthony Liguori 已提交
30 31 32 33
    g_assert(qdict != NULL);
    g_assert(qdict_size(qdict) == 0);
    g_assert(qdict->base.refcnt == 1);
    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
L
Luiz Capitulino 已提交
34

35
    QDECREF(qdict);
L
Luiz Capitulino 已提交
36 37
}

A
Anthony Liguori 已提交
38
static void qdict_put_obj_test(void)
L
Luiz Capitulino 已提交
39
{
40
    QNum *qn;
L
Luiz Capitulino 已提交
41 42 43 44 45 46 47
    QDict *qdict;
    QDictEntry *ent;
    const int num = 42;

    qdict = qdict_new();

    // key "" will have tdb hash 12345
48
    qdict_put_int(qdict, "", num);
L
Luiz Capitulino 已提交
49

A
Anthony Liguori 已提交
50
    g_assert(qdict_size(qdict) == 1);
51
    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
52 53
    qn = qobject_to_qnum(ent->value);
    g_assert_cmpint(qnum_get_int(qn), ==, num);
L
Luiz Capitulino 已提交
54

55
    QDECREF(qdict);
L
Luiz Capitulino 已提交
56 57
}

A
Anthony Liguori 已提交
58
static void qdict_destroy_simple_test(void)
L
Luiz Capitulino 已提交
59 60 61 62
{
    QDict *qdict;

    qdict = qdict_new();
63 64
    qdict_put_int(qdict, "num", 0);
    qdict_put_str(qdict, "str", "foo");
L
Luiz Capitulino 已提交
65 66 67 68

    QDECREF(qdict);
}

A
Anthony Liguori 已提交
69
static void qdict_get_test(void)
L
Luiz Capitulino 已提交
70
{
71
    QNum *qn;
L
Luiz Capitulino 已提交
72 73 74
    QObject *obj;
    const int value = -42;
    const char *key = "test";
A
Anthony Liguori 已提交
75
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
76

77
    qdict_put_int(tests_dict, key, value);
L
Luiz Capitulino 已提交
78 79

    obj = qdict_get(tests_dict, key);
A
Anthony Liguori 已提交
80
    g_assert(obj != NULL);
L
Luiz Capitulino 已提交
81

82 83
    qn = qobject_to_qnum(obj);
    g_assert_cmpint(qnum_get_int(qn), ==, value);
A
Anthony Liguori 已提交
84 85

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
86 87
}

A
Anthony Liguori 已提交
88
static void qdict_get_int_test(void)
L
Luiz Capitulino 已提交
89 90 91 92
{
    int ret;
    const int value = 100;
    const char *key = "int";
A
Anthony Liguori 已提交
93
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
94

95
    qdict_put_int(tests_dict, key, value);
L
Luiz Capitulino 已提交
96 97

    ret = qdict_get_int(tests_dict, key);
A
Anthony Liguori 已提交
98 99 100
    g_assert(ret == value);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
101 102
}

A
Anthony Liguori 已提交
103
static void qdict_get_try_int_test(void)
L
Luiz Capitulino 已提交
104 105 106 107
{
    int ret;
    const int value = 100;
    const char *key = "int";
A
Anthony Liguori 已提交
108
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
109

110
    qdict_put_int(tests_dict, key, value);
111
    qdict_put_str(tests_dict, "string", "test");
L
Luiz Capitulino 已提交
112 113

    ret = qdict_get_try_int(tests_dict, key, 0);
A
Anthony Liguori 已提交
114 115
    g_assert(ret == value);

116 117 118 119 120 121
    ret = qdict_get_try_int(tests_dict, "missing", -42);
    g_assert_cmpuint(ret, ==, -42);

    ret = qdict_get_try_int(tests_dict, "string", -42);
    g_assert_cmpuint(ret, ==, -42);

A
Anthony Liguori 已提交
122
    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
123 124
}

A
Anthony Liguori 已提交
125
static void qdict_get_str_test(void)
L
Luiz Capitulino 已提交
126 127 128 129
{
    const char *p;
    const char *key = "key";
    const char *str = "string";
A
Anthony Liguori 已提交
130
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
131

132
    qdict_put_str(tests_dict, key, str);
L
Luiz Capitulino 已提交
133 134

    p = qdict_get_str(tests_dict, key);
A
Anthony Liguori 已提交
135 136 137 138
    g_assert(p != NULL);
    g_assert(strcmp(p, str) == 0);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
139 140
}

A
Anthony Liguori 已提交
141
static void qdict_get_try_str_test(void)
L
Luiz Capitulino 已提交
142 143 144 145
{
    const char *p;
    const char *key = "key";
    const char *str = "string";
A
Anthony Liguori 已提交
146
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
147

148
    qdict_put_str(tests_dict, key, str);
L
Luiz Capitulino 已提交
149 150

    p = qdict_get_try_str(tests_dict, key);
A
Anthony Liguori 已提交
151 152 153 154
    g_assert(p != NULL);
    g_assert(strcmp(p, str) == 0);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
static void qdict_defaults_test(void)
{
    QDict *dict, *copy;

    dict = qdict_new();
    copy = qdict_new();

    qdict_set_default_str(dict, "foo", "abc");
    qdict_set_default_str(dict, "foo", "def");
    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "abc");
    qdict_set_default_str(dict, "bar", "ghi");

    qdict_copy_default(copy, dict, "foo");
    g_assert_cmpstr(qdict_get_str(copy, "foo"), ==, "abc");
    qdict_set_default_str(copy, "bar", "xyz");
    qdict_copy_default(copy, dict, "bar");
    g_assert_cmpstr(qdict_get_str(copy, "bar"), ==, "xyz");

    QDECREF(copy);
    QDECREF(dict);
}

A
Anthony Liguori 已提交
179
static void qdict_haskey_not_test(void)
L
Luiz Capitulino 已提交
180
{
A
Anthony Liguori 已提交
181 182 183 184
    QDict *tests_dict = qdict_new();
    g_assert(qdict_haskey(tests_dict, "test") == 0);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
185 186
}

A
Anthony Liguori 已提交
187
static void qdict_haskey_test(void)
L
Luiz Capitulino 已提交
188 189
{
    const char *key = "test";
A
Anthony Liguori 已提交
190
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
191

192
    qdict_put_int(tests_dict, key, 0);
A
Anthony Liguori 已提交
193 194 195
    g_assert(qdict_haskey(tests_dict, key) == 1);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
196 197
}

A
Anthony Liguori 已提交
198
static void qdict_del_test(void)
L
Luiz Capitulino 已提交
199 200
{
    const char *key = "key test";
A
Anthony Liguori 已提交
201
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
202

203
    qdict_put_str(tests_dict, key, "foo");
A
Anthony Liguori 已提交
204
    g_assert(qdict_size(tests_dict) == 1);
L
Luiz Capitulino 已提交
205 206 207

    qdict_del(tests_dict, key);

A
Anthony Liguori 已提交
208 209 210 211
    g_assert(qdict_size(tests_dict) == 0);
    g_assert(qdict_haskey(tests_dict, key) == 0);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
212 213
}

A
Anthony Liguori 已提交
214
static void qobject_to_qdict_test(void)
L
Luiz Capitulino 已提交
215
{
A
Anthony Liguori 已提交
216 217 218 219
    QDict *tests_dict = qdict_new();
    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
220 221
}

A
Anthony Liguori 已提交
222
static void qdict_iterapi_test(void)
223 224 225
{
    int count;
    const QDictEntry *ent;
A
Anthony Liguori 已提交
226
    QDict *tests_dict = qdict_new();
227

A
Anthony Liguori 已提交
228
    g_assert(qdict_first(tests_dict) == NULL);
229

230 231 232
    qdict_put_int(tests_dict, "key1", 1);
    qdict_put_int(tests_dict, "key2", 2);
    qdict_put_int(tests_dict, "key3", 3);
233 234 235

    count = 0;
    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
A
Anthony Liguori 已提交
236
        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
237 238 239
        count++;
    }

A
Anthony Liguori 已提交
240
    g_assert(count == qdict_size(tests_dict));
241 242 243 244

    /* Do it again to test restarting */
    count = 0;
    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
A
Anthony Liguori 已提交
245
        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
246 247 248
        count++;
    }

A
Anthony Liguori 已提交
249 250 251
    g_assert(count == qdict_size(tests_dict));

    QDECREF(tests_dict);
252 253
}

M
Max Reitz 已提交
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
static void qdict_flatten_test(void)
{
    QList *list1 = qlist_new();
    QList *list2 = qlist_new();
    QDict *dict1 = qdict_new();
    QDict *dict2 = qdict_new();
    QDict *dict3 = qdict_new();

    /*
     * Test the flattening of
     *
     * {
     *     "e": [
     *         42,
     *         [
     *             23,
     *             66,
     *             {
     *                 "a": 0,
     *                 "b": 1
     *             }
     *         ]
     *     ],
     *     "f": {
     *         "c": 2,
     *         "d": 3,
     *     },
     *     "g": 4
     * }
     *
     * to
     *
     * {
     *     "e.0": 42,
     *     "e.1.0": 23,
     *     "e.1.1": 66,
     *     "e.1.2.a": 0,
     *     "e.1.2.b": 1,
     *     "f.c": 2,
     *     "f.d": 3,
     *     "g": 4
     * }
     */

298 299
    qdict_put_int(dict1, "a", 0);
    qdict_put_int(dict1, "b", 1);
M
Max Reitz 已提交
300

301 302
    qlist_append_int(list1, 23);
    qlist_append_int(list1, 66);
E
Eric Blake 已提交
303
    qlist_append(list1, dict1);
304
    qlist_append_int(list2, 42);
E
Eric Blake 已提交
305
    qlist_append(list2, list1);
M
Max Reitz 已提交
306

307 308
    qdict_put_int(dict2, "c", 2);
    qdict_put_int(dict2, "d", 3);
E
Eric Blake 已提交
309 310
    qdict_put(dict3, "e", list2);
    qdict_put(dict3, "f", dict2);
311
    qdict_put_int(dict3, "g", 4);
M
Max Reitz 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328

    qdict_flatten(dict3);

    g_assert(qdict_get_int(dict3, "e.0") == 42);
    g_assert(qdict_get_int(dict3, "e.1.0") == 23);
    g_assert(qdict_get_int(dict3, "e.1.1") == 66);
    g_assert(qdict_get_int(dict3, "e.1.2.a") == 0);
    g_assert(qdict_get_int(dict3, "e.1.2.b") == 1);
    g_assert(qdict_get_int(dict3, "f.c") == 2);
    g_assert(qdict_get_int(dict3, "f.d") == 3);
    g_assert(qdict_get_int(dict3, "g") == 4);

    g_assert(qdict_size(dict3) == 8);

    QDECREF(dict3);
}

329 330 331 332
static void qdict_array_split_test(void)
{
    QDict *test_dict = qdict_new();
    QDict *dict1, *dict2;
333
    QNum *int1;
334 335 336 337 338 339 340
    QList *test_list;

    /*
     * Test the split of
     *
     * {
     *     "1.x": 0,
341
     *     "4.y": 1,
342 343
     *     "0.a": 42,
     *     "o.o": 7,
344 345
     *     "0.b": 23,
     *     "2": 66
346 347 348 349 350 351 352 353 354 355 356
     * }
     *
     * to
     *
     * [
     *     {
     *         "a": 42,
     *         "b": 23
     *     },
     *     {
     *         "x": 0
357 358
     *     },
     *     66
359 360 361 362 363
     * ]
     *
     * and
     *
     * {
364
     *     "4.y": 1,
365 366 367 368 369 370 371 372
     *     "o.o": 7
     * }
     *
     * (remaining in the old QDict)
     *
     * This example is given in the comment of qdict_array_split().
     */

373 374 375 376 377 378
    qdict_put_int(test_dict, "1.x", 0);
    qdict_put_int(test_dict, "4.y", 1);
    qdict_put_int(test_dict, "0.a", 42);
    qdict_put_int(test_dict, "o.o", 7);
    qdict_put_int(test_dict, "0.b", 23);
    qdict_put_int(test_dict, "2", 66);
379 380 381 382 383

    qdict_array_split(test_dict, &test_list);

    dict1 = qobject_to_qdict(qlist_pop(test_list));
    dict2 = qobject_to_qdict(qlist_pop(test_list));
384
    int1 = qobject_to_qnum(qlist_pop(test_list));
385 386 387

    g_assert(dict1);
    g_assert(dict2);
388
    g_assert(int1);
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
    g_assert(qlist_empty(test_list));

    QDECREF(test_list);

    g_assert(qdict_get_int(dict1, "a") == 42);
    g_assert(qdict_get_int(dict1, "b") == 23);

    g_assert(qdict_size(dict1) == 2);

    QDECREF(dict1);

    g_assert(qdict_get_int(dict2, "x") == 0);

    g_assert(qdict_size(dict2) == 1);

    QDECREF(dict2);

406
    g_assert_cmpint(qnum_get_int(int1), ==, 66);
407 408 409 410

    QDECREF(int1);

    g_assert(qdict_get_int(test_dict, "4.y") == 1);
411 412 413 414 415
    g_assert(qdict_get_int(test_dict, "o.o") == 7);

    g_assert(qdict_size(test_dict) == 2);

    QDECREF(test_dict);
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

    /*
     * Test the split of
     *
     * {
     *     "0": 42,
     *     "1": 23,
     *     "1.x": 84
     * }
     *
     * to
     *
     * [
     *     42
     * ]
     *
     * and
     *
     * {
     *     "1": 23,
     *     "1.x": 84
     * }
     *
     * That is, test whether splitting stops if there is both an entry with key
     * of "%u" and other entries with keys prefixed "%u." for the same index.
     */

    test_dict = qdict_new();

445 446 447
    qdict_put_int(test_dict, "0", 42);
    qdict_put_int(test_dict, "1", 23);
    qdict_put_int(test_dict, "1.x", 84);
448 449 450

    qdict_array_split(test_dict, &test_list);

451
    int1 = qobject_to_qnum(qlist_pop(test_list));
452 453 454 455 456 457

    g_assert(int1);
    g_assert(qlist_empty(test_list));

    QDECREF(test_list);

458
    g_assert_cmpint(qnum_get_int(int1), ==, 42);
459 460 461 462 463 464 465 466 467

    QDECREF(int1);

    g_assert(qdict_get_int(test_dict, "1") == 23);
    g_assert(qdict_get_int(test_dict, "1.x") == 84);

    g_assert(qdict_size(test_dict) == 2);

    QDECREF(test_dict);
468 469
}

470 471 472 473 474 475
static void qdict_array_entries_test(void)
{
    QDict *dict = qdict_new();

    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);

476 477
    qdict_put_int(dict, "bar", 0);
    qdict_put_int(dict, "baz.0", 0);
478 479
    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);

480
    qdict_put_int(dict, "foo.1", 0);
481
    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
482
    qdict_put_int(dict, "foo.0", 0);
483
    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 2);
484
    qdict_put_int(dict, "foo.bar", 0);
485 486 487
    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
    qdict_del(dict, "foo.bar");

488 489 490
    qdict_put_int(dict, "foo.2.a", 0);
    qdict_put_int(dict, "foo.2.b", 0);
    qdict_put_int(dict, "foo.2.c", 0);
491 492 493 494 495 496
    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 3);
    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);

    QDECREF(dict);

    dict = qdict_new();
497
    qdict_put_int(dict, "1", 0);
498
    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
499
    qdict_put_int(dict, "0", 0);
500
    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 2);
501
    qdict_put_int(dict, "bar", 0);
502 503 504
    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
    qdict_del(dict, "bar");

505 506 507
    qdict_put_int(dict, "2.a", 0);
    qdict_put_int(dict, "2.b", 0);
    qdict_put_int(dict, "2.c", 0);
508 509 510 511 512
    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 3);

    QDECREF(dict);
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
static void qdict_join_test(void)
{
    QDict *dict1, *dict2;
    bool overwrite = false;
    int i;

    dict1 = qdict_new();
    dict2 = qdict_new();

    /* Test everything once without overwrite and once with */
    do
    {
        /* Test empty dicts */
        qdict_join(dict1, dict2, overwrite);

        g_assert(qdict_size(dict1) == 0);
        g_assert(qdict_size(dict2) == 0);

        /* First iteration: Test movement */
        /* Second iteration: Test empty source and non-empty destination */
533
        qdict_put_int(dict2, "foo", 42);
534 535 536 537 538 539 540 541 542 543 544

        for (i = 0; i < 2; i++) {
            qdict_join(dict1, dict2, overwrite);

            g_assert(qdict_size(dict1) == 1);
            g_assert(qdict_size(dict2) == 0);

            g_assert(qdict_get_int(dict1, "foo") == 42);
        }

        /* Test non-empty source and destination without conflict */
545
        qdict_put_int(dict2, "bar", 23);
546 547 548 549 550 551 552 553 554 555

        qdict_join(dict1, dict2, overwrite);

        g_assert(qdict_size(dict1) == 2);
        g_assert(qdict_size(dict2) == 0);

        g_assert(qdict_get_int(dict1, "foo") == 42);
        g_assert(qdict_get_int(dict1, "bar") == 23);

        /* Test conflict */
556
        qdict_put_int(dict2, "foo", 84);
557 558 559 560 561 562

        qdict_join(dict1, dict2, overwrite);

        g_assert(qdict_size(dict1) == 2);
        g_assert(qdict_size(dict2) == !overwrite);

563
        g_assert(qdict_get_int(dict1, "foo") == (overwrite ? 84 : 42));
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
        g_assert(qdict_get_int(dict1, "bar") == 23);

        if (!overwrite) {
            g_assert(qdict_get_int(dict2, "foo") == 84);
        }

        /* Check the references */
        g_assert(qdict_get(dict1, "foo")->refcnt == 1);
        g_assert(qdict_get(dict1, "bar")->refcnt == 1);

        if (!overwrite) {
            g_assert(qdict_get(dict2, "foo")->refcnt == 1);
        }

        /* Clean up */
        qdict_del(dict1, "foo");
        qdict_del(dict1, "bar");

        if (!overwrite) {
            qdict_del(dict2, "foo");
        }
    }
    while (overwrite ^= true);

    QDECREF(dict1);
    QDECREF(dict2);
}

592 593 594 595 596 597
static void qdict_crumple_test_recursive(void)
{
    QDict *src, *dst, *rule, *vnc, *acl, *listen;
    QList *rules;

    src = qdict_new();
598 599 600 601 602 603 604 605 606
    qdict_put_str(src, "vnc.listen.addr", "127.0.0.1");
    qdict_put_str(src, "vnc.listen.port", "5901");
    qdict_put_str(src, "vnc.acl.rules.0.match", "fred");
    qdict_put_str(src, "vnc.acl.rules.0.policy", "allow");
    qdict_put_str(src, "vnc.acl.rules.1.match", "bob");
    qdict_put_str(src, "vnc.acl.rules.1.policy", "deny");
    qdict_put_str(src, "vnc.acl.default", "deny");
    qdict_put_str(src, "vnc.acl..name", "acl0");
    qdict_put_str(src, "vnc.acl.rule..name", "acl0");
607

608 609
    dst = qobject_to_qdict(qdict_crumple(src, &error_abort));
    g_assert(dst);
610 611
    g_assert_cmpint(qdict_size(dst), ==, 1);

612 613
    vnc = qdict_get_qdict(dst, "vnc");
    g_assert(vnc);
614
    g_assert_cmpint(qdict_size(vnc), ==, 3);
615

616 617
    listen = qdict_get_qdict(vnc, "listen");
    g_assert(listen);
618
    g_assert_cmpint(qdict_size(listen), ==, 2);
619 620 621
    g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
    g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));

622 623
    acl = qdict_get_qdict(vnc, "acl");
    g_assert(acl);
624
    g_assert_cmpint(qdict_size(acl), ==, 3);
625

626 627
    rules = qdict_get_qlist(acl, "rules");
    g_assert(rules);
628 629 630
    g_assert_cmpint(qlist_size(rules), ==, 2);

    rule = qobject_to_qdict(qlist_pop(rules));
631
    g_assert(rule);
632 633 634 635 636 637
    g_assert_cmpint(qdict_size(rule), ==, 2);
    g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
    g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
    QDECREF(rule);

    rule = qobject_to_qdict(qlist_pop(rules));
638
    g_assert(rule);
639 640 641 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
    g_assert_cmpint(qdict_size(rule), ==, 2);
    g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
    g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
    QDECREF(rule);

    /* With recursive crumpling, we should see all names unescaped */
    g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
    g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));

    QDECREF(src);
    QDECREF(dst);
}

static void qdict_crumple_test_empty(void)
{
    QDict *src, *dst;

    src = qdict_new();

    dst = (QDict *)qdict_crumple(src, &error_abort);

    g_assert_cmpint(qdict_size(dst), ==, 0);

    QDECREF(src);
    QDECREF(dst);
}

static void qdict_crumple_test_bad_inputs(void)
{
    QDict *src;
    Error *error = NULL;

    src = qdict_new();
    /* rule.0 can't be both a string and a dict */
673 674
    qdict_put_str(src, "rule.0", "fred");
    qdict_put_str(src, "rule.0.policy", "allow");
675 676 677 678 679 680 681 682 683

    g_assert(qdict_crumple(src, &error) == NULL);
    g_assert(error != NULL);
    error_free(error);
    error = NULL;
    QDECREF(src);

    src = qdict_new();
    /* rule can't be both a list and a dict */
684 685
    qdict_put_str(src, "rule.0", "fred");
    qdict_put_str(src, "rule.a", "allow");
686 687 688 689 690 691 692 693 694 695

    g_assert(qdict_crumple(src, &error) == NULL);
    g_assert(error != NULL);
    error_free(error);
    error = NULL;
    QDECREF(src);

    src = qdict_new();
    /* The input should be flat, ie no dicts or lists */
    qdict_put(src, "rule.a", qdict_new());
696
    qdict_put_str(src, "rule.b", "allow");
697 698 699 700 701 702 703 704 705

    g_assert(qdict_crumple(src, &error) == NULL);
    g_assert(error != NULL);
    error_free(error);
    error = NULL;
    QDECREF(src);

    src = qdict_new();
    /* List indexes must not have gaps */
706 707
    qdict_put_str(src, "rule.0", "deny");
    qdict_put_str(src, "rule.3", "allow");
708 709 710 711 712 713 714 715 716

    g_assert(qdict_crumple(src, &error) == NULL);
    g_assert(error != NULL);
    error_free(error);
    error = NULL;
    QDECREF(src);

    src = qdict_new();
    /* List indexes must be in %zu format */
717 718
    qdict_put_str(src, "rule.0", "deny");
    qdict_put_str(src, "rule.+1", "allow");
719 720 721 722 723 724 725 726

    g_assert(qdict_crumple(src, &error) == NULL);
    g_assert(error != NULL);
    error_free(error);
    error = NULL;
    QDECREF(src);
}

L
Luiz Capitulino 已提交
727 728 729 730
/*
 * Errors test-cases
 */

A
Anthony Liguori 已提交
731
static void qdict_put_exists_test(void)
L
Luiz Capitulino 已提交
732 733 734
{
    int value;
    const char *key = "exists";
A
Anthony Liguori 已提交
735
    QDict *tests_dict = qdict_new();
L
Luiz Capitulino 已提交
736

737 738
    qdict_put_int(tests_dict, key, 1);
    qdict_put_int(tests_dict, key, 2);
L
Luiz Capitulino 已提交
739 740

    value = qdict_get_int(tests_dict, key);
A
Anthony Liguori 已提交
741
    g_assert(value == 2);
L
Luiz Capitulino 已提交
742

A
Anthony Liguori 已提交
743 744 745
    g_assert(qdict_size(tests_dict) == 1);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
746 747
}

A
Anthony Liguori 已提交
748
static void qdict_get_not_exists_test(void)
L
Luiz Capitulino 已提交
749
{
A
Anthony Liguori 已提交
750 751 752 753
    QDict *tests_dict = qdict_new();
    g_assert(qdict_get(tests_dict, "foo") == NULL);

    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
}

/*
 * Stress test-case
 *
 * This is a lot big for a unit-test, but there is no other place
 * to have it.
 */

static void remove_dots(char *string)
{
    char *p = strchr(string, ':');
    if (p)
        *p = '\0';
}

static QString *read_line(FILE *file, char *key)
{
    char value[128];

S
Stefan Weil 已提交
774
    if (fscanf(file, "%127s%127s", key, value) == EOF) {
L
Luiz Capitulino 已提交
775
        return NULL;
S
Stefan Weil 已提交
776
    }
L
Luiz Capitulino 已提交
777 778 779 780 781 782
    remove_dots(key);
    return qstring_from_str(value);
}

#define reset_file(file)    fseek(file, 0L, SEEK_SET)

A
Anthony Liguori 已提交
783
static void qdict_stress_test(void)
L
Luiz Capitulino 已提交
784 785 786 787 788 789 790 791 792
{
    size_t lines;
    char key[128];
    FILE *test_file;
    QDict *qdict;
    QString *value;
    const char *test_file_path = "qdict-test-data.txt";

    test_file = fopen(test_file_path, "r");
A
Anthony Liguori 已提交
793
    g_assert(test_file != NULL);
L
Luiz Capitulino 已提交
794 795 796

    // Create the dict
    qdict = qdict_new();
A
Anthony Liguori 已提交
797
    g_assert(qdict != NULL);
L
Luiz Capitulino 已提交
798 799 800 801 802 803 804 805 806

    // Add everything from the test file
    for (lines = 0;; lines++) {
        value = read_line(test_file, key);
        if (!value)
            break;

        qdict_put(qdict, key, value);
    }
A
Anthony Liguori 已提交
807
    g_assert(qdict_size(qdict) == lines);
L
Luiz Capitulino 已提交
808 809 810 811 812 813 814 815 816 817 818 819 820

    // Check if everything is really in there
    reset_file(test_file);
    for (;;) {
        const char *str1, *str2;

        value = read_line(test_file, key);
        if (!value)
            break;

        str1 = qstring_get_str(value);

        str2 = qdict_get_str(qdict, key);
A
Anthony Liguori 已提交
821
        g_assert(str2 != NULL);
L
Luiz Capitulino 已提交
822

A
Anthony Liguori 已提交
823
        g_assert(strcmp(str1, str2) == 0);
L
Luiz Capitulino 已提交
824 825 826 827 828 829 830 831 832 833 834 835 836 837

        QDECREF(value);
    }

    // Delete everything
    reset_file(test_file);
    for (;;) {
        value = read_line(test_file, key);
        if (!value)
            break;

        qdict_del(qdict, key);
        QDECREF(value);

A
Anthony Liguori 已提交
838
        g_assert(qdict_haskey(qdict, key) == 0);
L
Luiz Capitulino 已提交
839 840 841
    }
    fclose(test_file);

A
Anthony Liguori 已提交
842
    g_assert(qdict_size(qdict) == 0);
L
Luiz Capitulino 已提交
843 844 845
    QDECREF(qdict);
}

A
Anthony Liguori 已提交
846
int main(int argc, char **argv)
L
Luiz Capitulino 已提交
847
{
A
Anthony Liguori 已提交
848
    g_test_init(&argc, &argv, NULL);
L
Luiz Capitulino 已提交
849

A
Anthony Liguori 已提交
850 851 852
    g_test_add_func("/public/new", qdict_new_test);
    g_test_add_func("/public/put_obj", qdict_put_obj_test);
    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
L
Luiz Capitulino 已提交
853 854

    /* Continue, but now with fixtures */
A
Anthony Liguori 已提交
855 856 857 858 859
    g_test_add_func("/public/get", qdict_get_test);
    g_test_add_func("/public/get_int", qdict_get_int_test);
    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
    g_test_add_func("/public/get_str", qdict_get_str_test);
    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
860
    g_test_add_func("/public/defaults", qdict_defaults_test);
A
Anthony Liguori 已提交
861 862 863 864 865
    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
    g_test_add_func("/public/haskey", qdict_haskey_test);
    g_test_add_func("/public/del", qdict_del_test);
    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
    g_test_add_func("/public/iterapi", qdict_iterapi_test);
M
Max Reitz 已提交
866
    g_test_add_func("/public/flatten", qdict_flatten_test);
867
    g_test_add_func("/public/array_split", qdict_array_split_test);
868
    g_test_add_func("/public/array_entries", qdict_array_entries_test);
869
    g_test_add_func("/public/join", qdict_join_test);
A
Anthony Liguori 已提交
870 871 872

    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
L
Luiz Capitulino 已提交
873

874 875 876 877 878 879 880
    g_test_add_func("/public/crumple/recursive",
                    qdict_crumple_test_recursive);
    g_test_add_func("/public/crumple/empty",
                    qdict_crumple_test_empty);
    g_test_add_func("/public/crumple/bad_inputs",
                    qdict_crumple_test_bad_inputs);

L
Luiz Capitulino 已提交
881
    /* The Big one */
A
Anthony Liguori 已提交
882 883 884
    if (g_test_slow()) {
        g_test_add_func("/stress/test", qdict_stress_test);
    }
L
Luiz Capitulino 已提交
885

A
Anthony Liguori 已提交
886
    return g_test_run();
L
Luiz Capitulino 已提交
887
}