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
#include "qapi/qmp/qdict.h"
15
#include "qapi/qmp/qnum.h"
16
#include "qapi/qmp/qstring.h"
17
#include "qapi/error.h"
L
Luiz Capitulino 已提交
18 19 20 21 22 23 24 25
#include "qemu-common.h"

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

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

    qdict = qdict_new();
A
Anthony Liguori 已提交
31 32 33 34
    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 已提交
35

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

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

    qdict = qdict_new();

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

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

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

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

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

    QDECREF(qdict);
}

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

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

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

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

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

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

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

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

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

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

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

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

117 118 119 120 121 122
    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 已提交
123
    QDECREF(tests_dict);
L
Luiz Capitulino 已提交
124 125
}

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

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

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

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

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

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

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

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

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
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 已提交
180
static void qdict_haskey_not_test(void)
L
Luiz Capitulino 已提交
181
{
A
Anthony Liguori 已提交
182 183 184 185
    QDict *tests_dict = qdict_new();
    g_assert(qdict_haskey(tests_dict, "test") == 0);

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

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

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

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

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

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

    qdict_del(tests_dict, key);

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

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

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

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

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

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

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

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

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

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

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

    QDECREF(tests_dict);
253 254
}

M
Max Reitz 已提交
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
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
     * }
     */

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

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

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

    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);
}

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

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

374 375 376 377 378 379
    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);
380 381 382 383 384

    qdict_array_split(test_dict, &test_list);

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

    g_assert(dict1);
    g_assert(dict2);
389
    g_assert(int1);
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
    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);

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

    QDECREF(int1);

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

    g_assert(qdict_size(test_dict) == 2);

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

    /*
     * 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();

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

    qdict_array_split(test_dict, &test_list);

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

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

    QDECREF(test_list);

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

    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);
469 470
}

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

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

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

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

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

    QDECREF(dict);

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

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

    QDECREF(dict);
}

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
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 */
534
        qdict_put_int(dict2, "foo", 42);
535 536 537 538 539 540 541 542 543 544 545

        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 */
546
        qdict_put_int(dict2, "bar", 23);
547 548 549 550 551 552 553 554 555 556

        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 */
557
        qdict_put_int(dict2, "foo", 84);
558 559 560 561 562 563

        qdict_join(dict1, dict2, overwrite);

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

564
        g_assert(qdict_get_int(dict1, "foo") == (overwrite ? 84 : 42));
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 592
        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);
}

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

    src = qdict_new();
599 600 601 602 603 604 605 606 607
    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");
608

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

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

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

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

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

    rule = qobject_to_qdict(qlist_pop(rules));
632
    g_assert(rule);
633 634 635 636 637 638
    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));
639
    g_assert(rule);
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 673
    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 */
674 675
    qdict_put_str(src, "rule.0", "fred");
    qdict_put_str(src, "rule.0.policy", "allow");
676 677 678 679 680 681 682 683 684

    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 */
685 686
    qdict_put_str(src, "rule.0", "fred");
    qdict_put_str(src, "rule.a", "allow");
687 688 689 690 691 692 693 694 695 696

    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());
697
    qdict_put_str(src, "rule.b", "allow");
698 699 700 701 702 703 704 705 706

    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 */
707 708
    qdict_put_str(src, "rule.0", "deny");
    qdict_put_str(src, "rule.3", "allow");
709 710 711 712 713 714 715 716 717

    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 */
718 719
    qdict_put_str(src, "rule.0", "deny");
    qdict_put_str(src, "rule.+1", "allow");
720 721 722 723 724 725 726 727

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

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

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

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

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

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

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

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

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

/*
 * 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 已提交
775
    if (fscanf(file, "%127s%127s", key, value) == EOF) {
L
Luiz Capitulino 已提交
776
        return NULL;
S
Stefan Weil 已提交
777
    }
L
Luiz Capitulino 已提交
778 779 780 781 782 783
    remove_dots(key);
    return qstring_from_str(value);
}

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

A
Anthony Liguori 已提交
784
static void qdict_stress_test(void)
L
Luiz Capitulino 已提交
785 786 787 788 789 790 791 792 793
{
    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 已提交
794
    g_assert(test_file != NULL);
L
Luiz Capitulino 已提交
795 796 797

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

    // 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 已提交
808
    g_assert(qdict_size(qdict) == lines);
L
Luiz Capitulino 已提交
809 810 811 812 813 814 815 816 817 818 819 820 821

    // 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 已提交
822
        g_assert(str2 != NULL);
L
Luiz Capitulino 已提交
823

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

        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 已提交
839
        g_assert(qdict_haskey(qdict, key) == 0);
L
Luiz Capitulino 已提交
840 841 842
    }
    fclose(test_file);

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

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

A
Anthony Liguori 已提交
851 852 853
    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 已提交
854 855

    /* Continue, but now with fixtures */
A
Anthony Liguori 已提交
856 857 858 859 860
    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);
861
    g_test_add_func("/public/defaults", qdict_defaults_test);
A
Anthony Liguori 已提交
862 863 864 865 866
    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 已提交
867
    g_test_add_func("/public/flatten", qdict_flatten_test);
868
    g_test_add_func("/public/array_split", qdict_array_split_test);
869
    g_test_add_func("/public/array_entries", qdict_array_entries_test);
870
    g_test_add_func("/public/join", qdict_join_test);
A
Anthony Liguori 已提交
871 872 873

    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 已提交
874

875 876 877 878 879 880 881
    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 已提交
882
    /* The Big one */
A
Anthony Liguori 已提交
883 884 885
    if (g_test_slow()) {
        g_test_add_func("/stress/test", qdict_stress_test);
    }
L
Luiz Capitulino 已提交
886

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