qemu/tests/check-qdict.c
<<
>>
Prefs
   1/*
   2 * QDict unit-tests.
   3 *
   4 * Copyright (C) 2009 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Luiz Capitulino <lcapitulino@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  10 * See the COPYING.LIB file in the top-level directory.
  11 */
  12#include "qemu/osdep.h"
  13
  14#include "qapi/qmp/qdict.h"
  15#include "qapi/qmp/qstring.h"
  16#include "qapi/error.h"
  17#include "qemu-common.h"
  18
  19/*
  20 * Public Interface test-cases
  21 *
  22 * (with some violations to access 'private' data)
  23 */
  24
  25static void qdict_new_test(void)
  26{
  27    QDict *qdict;
  28
  29    qdict = qdict_new();
  30    g_assert(qdict != NULL);
  31    g_assert(qdict_size(qdict) == 0);
  32    g_assert(qdict->base.refcnt == 1);
  33    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
  34
  35    QDECREF(qdict);
  36}
  37
  38static void qdict_put_obj_test(void)
  39{
  40    QNum *qn;
  41    QDict *qdict;
  42    QDictEntry *ent;
  43    const int num = 42;
  44
  45    qdict = qdict_new();
  46
  47    // key "" will have tdb hash 12345
  48    qdict_put_int(qdict, "", num);
  49
  50    g_assert(qdict_size(qdict) == 1);
  51    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
  52    qn = qobject_to_qnum(ent->value);
  53    g_assert_cmpint(qnum_get_int(qn), ==, num);
  54
  55    QDECREF(qdict);
  56}
  57
  58static void qdict_destroy_simple_test(void)
  59{
  60    QDict *qdict;
  61
  62    qdict = qdict_new();
  63    qdict_put_int(qdict, "num", 0);
  64    qdict_put_str(qdict, "str", "foo");
  65
  66    QDECREF(qdict);
  67}
  68
  69static void qdict_get_test(void)
  70{
  71    QNum *qn;
  72    QObject *obj;
  73    const int value = -42;
  74    const char *key = "test";
  75    QDict *tests_dict = qdict_new();
  76
  77    qdict_put_int(tests_dict, key, value);
  78
  79    obj = qdict_get(tests_dict, key);
  80    g_assert(obj != NULL);
  81
  82    qn = qobject_to_qnum(obj);
  83    g_assert_cmpint(qnum_get_int(qn), ==, value);
  84
  85    QDECREF(tests_dict);
  86}
  87
  88static void qdict_get_int_test(void)
  89{
  90    int ret;
  91    const int value = 100;
  92    const char *key = "int";
  93    QDict *tests_dict = qdict_new();
  94
  95    qdict_put_int(tests_dict, key, value);
  96
  97    ret = qdict_get_int(tests_dict, key);
  98    g_assert(ret == value);
  99
 100    QDECREF(tests_dict);
 101}
 102
 103static void qdict_get_try_int_test(void)
 104{
 105    int ret;
 106    const int value = 100;
 107    const char *key = "int";
 108    QDict *tests_dict = qdict_new();
 109
 110    qdict_put_int(tests_dict, key, value);
 111    qdict_put_str(tests_dict, "string", "test");
 112
 113    ret = qdict_get_try_int(tests_dict, key, 0);
 114    g_assert(ret == value);
 115
 116    ret = qdict_get_try_int(tests_dict, "missing", -42);
 117    g_assert_cmpuint(ret, ==, -42);
 118
 119    ret = qdict_get_try_int(tests_dict, "string", -42);
 120    g_assert_cmpuint(ret, ==, -42);
 121
 122    QDECREF(tests_dict);
 123}
 124
 125static void qdict_get_str_test(void)
 126{
 127    const char *p;
 128    const char *key = "key";
 129    const char *str = "string";
 130    QDict *tests_dict = qdict_new();
 131
 132    qdict_put_str(tests_dict, key, str);
 133
 134    p = qdict_get_str(tests_dict, key);
 135    g_assert(p != NULL);
 136    g_assert(strcmp(p, str) == 0);
 137
 138    QDECREF(tests_dict);
 139}
 140
 141static void qdict_get_try_str_test(void)
 142{
 143    const char *p;
 144    const char *key = "key";
 145    const char *str = "string";
 146    QDict *tests_dict = qdict_new();
 147
 148    qdict_put_str(tests_dict, key, str);
 149
 150    p = qdict_get_try_str(tests_dict, key);
 151    g_assert(p != NULL);
 152    g_assert(strcmp(p, str) == 0);
 153
 154    QDECREF(tests_dict);
 155}
 156
 157static void qdict_defaults_test(void)
 158{
 159    QDict *dict, *copy;
 160
 161    dict = qdict_new();
 162    copy = qdict_new();
 163
 164    qdict_set_default_str(dict, "foo", "abc");
 165    qdict_set_default_str(dict, "foo", "def");
 166    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "abc");
 167    qdict_set_default_str(dict, "bar", "ghi");
 168
 169    qdict_copy_default(copy, dict, "foo");
 170    g_assert_cmpstr(qdict_get_str(copy, "foo"), ==, "abc");
 171    qdict_set_default_str(copy, "bar", "xyz");
 172    qdict_copy_default(copy, dict, "bar");
 173    g_assert_cmpstr(qdict_get_str(copy, "bar"), ==, "xyz");
 174
 175    QDECREF(copy);
 176    QDECREF(dict);
 177}
 178
 179static void qdict_haskey_not_test(void)
 180{
 181    QDict *tests_dict = qdict_new();
 182    g_assert(qdict_haskey(tests_dict, "test") == 0);
 183
 184    QDECREF(tests_dict);
 185}
 186
 187static void qdict_haskey_test(void)
 188{
 189    const char *key = "test";
 190    QDict *tests_dict = qdict_new();
 191
 192    qdict_put_int(tests_dict, key, 0);
 193    g_assert(qdict_haskey(tests_dict, key) == 1);
 194
 195    QDECREF(tests_dict);
 196}
 197
 198static void qdict_del_test(void)
 199{
 200    const char *key = "key test";
 201    QDict *tests_dict = qdict_new();
 202
 203    qdict_put_str(tests_dict, key, "foo");
 204    g_assert(qdict_size(tests_dict) == 1);
 205
 206    qdict_del(tests_dict, key);
 207
 208    g_assert(qdict_size(tests_dict) == 0);
 209    g_assert(qdict_haskey(tests_dict, key) == 0);
 210
 211    QDECREF(tests_dict);
 212}
 213
 214static void qobject_to_qdict_test(void)
 215{
 216    QDict *tests_dict = qdict_new();
 217    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
 218
 219    QDECREF(tests_dict);
 220}
 221
 222static void qdict_iterapi_test(void)
 223{
 224    int count;
 225    const QDictEntry *ent;
 226    QDict *tests_dict = qdict_new();
 227
 228    g_assert(qdict_first(tests_dict) == NULL);
 229
 230    qdict_put_int(tests_dict, "key1", 1);
 231    qdict_put_int(tests_dict, "key2", 2);
 232    qdict_put_int(tests_dict, "key3", 3);
 233
 234    count = 0;
 235    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
 236        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
 237        count++;
 238    }
 239
 240    g_assert(count == qdict_size(tests_dict));
 241
 242    /* Do it again to test restarting */
 243    count = 0;
 244    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
 245        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
 246        count++;
 247    }
 248
 249    g_assert(count == qdict_size(tests_dict));
 250
 251    QDECREF(tests_dict);
 252}
 253
 254static void qdict_flatten_test(void)
 255{
 256    QList *list1 = qlist_new();
 257    QList *list2 = qlist_new();
 258    QDict *dict1 = qdict_new();
 259    QDict *dict2 = qdict_new();
 260    QDict *dict3 = qdict_new();
 261
 262    /*
 263     * Test the flattening of
 264     *
 265     * {
 266     *     "e": [
 267     *         42,
 268     *         [
 269     *             23,
 270     *             66,
 271     *             {
 272     *                 "a": 0,
 273     *                 "b": 1
 274     *             }
 275     *         ]
 276     *     ],
 277     *     "f": {
 278     *         "c": 2,
 279     *         "d": 3,
 280     *     },
 281     *     "g": 4
 282     * }
 283     *
 284     * to
 285     *
 286     * {
 287     *     "e.0": 42,
 288     *     "e.1.0": 23,
 289     *     "e.1.1": 66,
 290     *     "e.1.2.a": 0,
 291     *     "e.1.2.b": 1,
 292     *     "f.c": 2,
 293     *     "f.d": 3,
 294     *     "g": 4
 295     * }
 296     */
 297
 298    qdict_put_int(dict1, "a", 0);
 299    qdict_put_int(dict1, "b", 1);
 300
 301    qlist_append_int(list1, 23);
 302    qlist_append_int(list1, 66);
 303    qlist_append(list1, dict1);
 304    qlist_append_int(list2, 42);
 305    qlist_append(list2, list1);
 306
 307    qdict_put_int(dict2, "c", 2);
 308    qdict_put_int(dict2, "d", 3);
 309    qdict_put(dict3, "e", list2);
 310    qdict_put(dict3, "f", dict2);
 311    qdict_put_int(dict3, "g", 4);
 312
 313    qdict_flatten(dict3);
 314
 315    g_assert(qdict_get_int(dict3, "e.0") == 42);
 316    g_assert(qdict_get_int(dict3, "e.1.0") == 23);
 317    g_assert(qdict_get_int(dict3, "e.1.1") == 66);
 318    g_assert(qdict_get_int(dict3, "e.1.2.a") == 0);
 319    g_assert(qdict_get_int(dict3, "e.1.2.b") == 1);
 320    g_assert(qdict_get_int(dict3, "f.c") == 2);
 321    g_assert(qdict_get_int(dict3, "f.d") == 3);
 322    g_assert(qdict_get_int(dict3, "g") == 4);
 323
 324    g_assert(qdict_size(dict3) == 8);
 325
 326    QDECREF(dict3);
 327}
 328
 329static void qdict_array_split_test(void)
 330{
 331    QDict *test_dict = qdict_new();
 332    QDict *dict1, *dict2;
 333    QNum *int1;
 334    QList *test_list;
 335
 336    /*
 337     * Test the split of
 338     *
 339     * {
 340     *     "1.x": 0,
 341     *     "4.y": 1,
 342     *     "0.a": 42,
 343     *     "o.o": 7,
 344     *     "0.b": 23,
 345     *     "2": 66
 346     * }
 347     *
 348     * to
 349     *
 350     * [
 351     *     {
 352     *         "a": 42,
 353     *         "b": 23
 354     *     },
 355     *     {
 356     *         "x": 0
 357     *     },
 358     *     66
 359     * ]
 360     *
 361     * and
 362     *
 363     * {
 364     *     "4.y": 1,
 365     *     "o.o": 7
 366     * }
 367     *
 368     * (remaining in the old QDict)
 369     *
 370     * This example is given in the comment of qdict_array_split().
 371     */
 372
 373    qdict_put_int(test_dict, "1.x", 0);
 374    qdict_put_int(test_dict, "4.y", 1);
 375    qdict_put_int(test_dict, "0.a", 42);
 376    qdict_put_int(test_dict, "o.o", 7);
 377    qdict_put_int(test_dict, "0.b", 23);
 378    qdict_put_int(test_dict, "2", 66);
 379
 380    qdict_array_split(test_dict, &test_list);
 381
 382    dict1 = qobject_to_qdict(qlist_pop(test_list));
 383    dict2 = qobject_to_qdict(qlist_pop(test_list));
 384    int1 = qobject_to_qnum(qlist_pop(test_list));
 385
 386    g_assert(dict1);
 387    g_assert(dict2);
 388    g_assert(int1);
 389    g_assert(qlist_empty(test_list));
 390
 391    QDECREF(test_list);
 392
 393    g_assert(qdict_get_int(dict1, "a") == 42);
 394    g_assert(qdict_get_int(dict1, "b") == 23);
 395
 396    g_assert(qdict_size(dict1) == 2);
 397
 398    QDECREF(dict1);
 399
 400    g_assert(qdict_get_int(dict2, "x") == 0);
 401
 402    g_assert(qdict_size(dict2) == 1);
 403
 404    QDECREF(dict2);
 405
 406    g_assert_cmpint(qnum_get_int(int1), ==, 66);
 407
 408    QDECREF(int1);
 409
 410    g_assert(qdict_get_int(test_dict, "4.y") == 1);
 411    g_assert(qdict_get_int(test_dict, "o.o") == 7);
 412
 413    g_assert(qdict_size(test_dict) == 2);
 414
 415    QDECREF(test_dict);
 416
 417    /*
 418     * Test the split of
 419     *
 420     * {
 421     *     "0": 42,
 422     *     "1": 23,
 423     *     "1.x": 84
 424     * }
 425     *
 426     * to
 427     *
 428     * [
 429     *     42
 430     * ]
 431     *
 432     * and
 433     *
 434     * {
 435     *     "1": 23,
 436     *     "1.x": 84
 437     * }
 438     *
 439     * That is, test whether splitting stops if there is both an entry with key
 440     * of "%u" and other entries with keys prefixed "%u." for the same index.
 441     */
 442
 443    test_dict = qdict_new();
 444
 445    qdict_put_int(test_dict, "0", 42);
 446    qdict_put_int(test_dict, "1", 23);
 447    qdict_put_int(test_dict, "1.x", 84);
 448
 449    qdict_array_split(test_dict, &test_list);
 450
 451    int1 = qobject_to_qnum(qlist_pop(test_list));
 452
 453    g_assert(int1);
 454    g_assert(qlist_empty(test_list));
 455
 456    QDECREF(test_list);
 457
 458    g_assert_cmpint(qnum_get_int(int1), ==, 42);
 459
 460    QDECREF(int1);
 461
 462    g_assert(qdict_get_int(test_dict, "1") == 23);
 463    g_assert(qdict_get_int(test_dict, "1.x") == 84);
 464
 465    g_assert(qdict_size(test_dict) == 2);
 466
 467    QDECREF(test_dict);
 468}
 469
 470static void qdict_array_entries_test(void)
 471{
 472    QDict *dict = qdict_new();
 473
 474    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
 475
 476    qdict_put_int(dict, "bar", 0);
 477    qdict_put_int(dict, "baz.0", 0);
 478    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
 479
 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    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
 486    qdict_del(dict, "foo.bar");
 487
 488    qdict_put_int(dict, "foo.2.a", 0);
 489    qdict_put_int(dict, "foo.2.b", 0);
 490    qdict_put_int(dict, "foo.2.c", 0);
 491    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 3);
 492    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
 493
 494    QDECREF(dict);
 495
 496    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    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
 503    qdict_del(dict, "bar");
 504
 505    qdict_put_int(dict, "2.a", 0);
 506    qdict_put_int(dict, "2.b", 0);
 507    qdict_put_int(dict, "2.c", 0);
 508    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 3);
 509
 510    QDECREF(dict);
 511}
 512
 513static void qdict_join_test(void)
 514{
 515    QDict *dict1, *dict2;
 516    bool overwrite = false;
 517    int i;
 518
 519    dict1 = qdict_new();
 520    dict2 = qdict_new();
 521
 522    /* Test everything once without overwrite and once with */
 523    do
 524    {
 525        /* Test empty dicts */
 526        qdict_join(dict1, dict2, overwrite);
 527
 528        g_assert(qdict_size(dict1) == 0);
 529        g_assert(qdict_size(dict2) == 0);
 530
 531        /* First iteration: Test movement */
 532        /* Second iteration: Test empty source and non-empty destination */
 533        qdict_put_int(dict2, "foo", 42);
 534
 535        for (i = 0; i < 2; i++) {
 536            qdict_join(dict1, dict2, overwrite);
 537
 538            g_assert(qdict_size(dict1) == 1);
 539            g_assert(qdict_size(dict2) == 0);
 540
 541            g_assert(qdict_get_int(dict1, "foo") == 42);
 542        }
 543
 544        /* Test non-empty source and destination without conflict */
 545        qdict_put_int(dict2, "bar", 23);
 546
 547        qdict_join(dict1, dict2, overwrite);
 548
 549        g_assert(qdict_size(dict1) == 2);
 550        g_assert(qdict_size(dict2) == 0);
 551
 552        g_assert(qdict_get_int(dict1, "foo") == 42);
 553        g_assert(qdict_get_int(dict1, "bar") == 23);
 554
 555        /* Test conflict */
 556        qdict_put_int(dict2, "foo", 84);
 557
 558        qdict_join(dict1, dict2, overwrite);
 559
 560        g_assert(qdict_size(dict1) == 2);
 561        g_assert(qdict_size(dict2) == !overwrite);
 562
 563        g_assert(qdict_get_int(dict1, "foo") == (overwrite ? 84 : 42));
 564        g_assert(qdict_get_int(dict1, "bar") == 23);
 565
 566        if (!overwrite) {
 567            g_assert(qdict_get_int(dict2, "foo") == 84);
 568        }
 569
 570        /* Check the references */
 571        g_assert(qdict_get(dict1, "foo")->refcnt == 1);
 572        g_assert(qdict_get(dict1, "bar")->refcnt == 1);
 573
 574        if (!overwrite) {
 575            g_assert(qdict_get(dict2, "foo")->refcnt == 1);
 576        }
 577
 578        /* Clean up */
 579        qdict_del(dict1, "foo");
 580        qdict_del(dict1, "bar");
 581
 582        if (!overwrite) {
 583            qdict_del(dict2, "foo");
 584        }
 585    }
 586    while (overwrite ^= true);
 587
 588    QDECREF(dict1);
 589    QDECREF(dict2);
 590}
 591
 592static void qdict_crumple_test_recursive(void)
 593{
 594    QDict *src, *dst, *rule, *vnc, *acl, *listen;
 595    QList *rules;
 596
 597    src = qdict_new();
 598    qdict_put_str(src, "vnc.listen.addr", "127.0.0.1");
 599    qdict_put_str(src, "vnc.listen.port", "5901");
 600    qdict_put_str(src, "vnc.acl.rules.0.match", "fred");
 601    qdict_put_str(src, "vnc.acl.rules.0.policy", "allow");
 602    qdict_put_str(src, "vnc.acl.rules.1.match", "bob");
 603    qdict_put_str(src, "vnc.acl.rules.1.policy", "deny");
 604    qdict_put_str(src, "vnc.acl.default", "deny");
 605    qdict_put_str(src, "vnc.acl..name", "acl0");
 606    qdict_put_str(src, "vnc.acl.rule..name", "acl0");
 607
 608    dst = qobject_to_qdict(qdict_crumple(src, &error_abort));
 609    g_assert(dst);
 610    g_assert_cmpint(qdict_size(dst), ==, 1);
 611
 612    vnc = qdict_get_qdict(dst, "vnc");
 613    g_assert(vnc);
 614    g_assert_cmpint(qdict_size(vnc), ==, 3);
 615
 616    listen = qdict_get_qdict(vnc, "listen");
 617    g_assert(listen);
 618    g_assert_cmpint(qdict_size(listen), ==, 2);
 619    g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
 620    g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));
 621
 622    acl = qdict_get_qdict(vnc, "acl");
 623    g_assert(acl);
 624    g_assert_cmpint(qdict_size(acl), ==, 3);
 625
 626    rules = qdict_get_qlist(acl, "rules");
 627    g_assert(rules);
 628    g_assert_cmpint(qlist_size(rules), ==, 2);
 629
 630    rule = qobject_to_qdict(qlist_pop(rules));
 631    g_assert(rule);
 632    g_assert_cmpint(qdict_size(rule), ==, 2);
 633    g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
 634    g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
 635    QDECREF(rule);
 636
 637    rule = qobject_to_qdict(qlist_pop(rules));
 638    g_assert(rule);
 639    g_assert_cmpint(qdict_size(rule), ==, 2);
 640    g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
 641    g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
 642    QDECREF(rule);
 643
 644    /* With recursive crumpling, we should see all names unescaped */
 645    g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
 646    g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));
 647
 648    QDECREF(src);
 649    QDECREF(dst);
 650}
 651
 652static void qdict_crumple_test_empty(void)
 653{
 654    QDict *src, *dst;
 655
 656    src = qdict_new();
 657
 658    dst = (QDict *)qdict_crumple(src, &error_abort);
 659
 660    g_assert_cmpint(qdict_size(dst), ==, 0);
 661
 662    QDECREF(src);
 663    QDECREF(dst);
 664}
 665
 666static void qdict_crumple_test_bad_inputs(void)
 667{
 668    QDict *src;
 669    Error *error = NULL;
 670
 671    src = qdict_new();
 672    /* rule.0 can't be both a string and a dict */
 673    qdict_put_str(src, "rule.0", "fred");
 674    qdict_put_str(src, "rule.0.policy", "allow");
 675
 676    g_assert(qdict_crumple(src, &error) == NULL);
 677    g_assert(error != NULL);
 678    error_free(error);
 679    error = NULL;
 680    QDECREF(src);
 681
 682    src = qdict_new();
 683    /* rule can't be both a list and a dict */
 684    qdict_put_str(src, "rule.0", "fred");
 685    qdict_put_str(src, "rule.a", "allow");
 686
 687    g_assert(qdict_crumple(src, &error) == NULL);
 688    g_assert(error != NULL);
 689    error_free(error);
 690    error = NULL;
 691    QDECREF(src);
 692
 693    src = qdict_new();
 694    /* The input should be flat, ie no dicts or lists */
 695    qdict_put(src, "rule.a", qdict_new());
 696    qdict_put_str(src, "rule.b", "allow");
 697
 698    g_assert(qdict_crumple(src, &error) == NULL);
 699    g_assert(error != NULL);
 700    error_free(error);
 701    error = NULL;
 702    QDECREF(src);
 703
 704    src = qdict_new();
 705    /* List indexes must not have gaps */
 706    qdict_put_str(src, "rule.0", "deny");
 707    qdict_put_str(src, "rule.3", "allow");
 708
 709    g_assert(qdict_crumple(src, &error) == NULL);
 710    g_assert(error != NULL);
 711    error_free(error);
 712    error = NULL;
 713    QDECREF(src);
 714
 715    src = qdict_new();
 716    /* List indexes must be in %zu format */
 717    qdict_put_str(src, "rule.0", "deny");
 718    qdict_put_str(src, "rule.+1", "allow");
 719
 720    g_assert(qdict_crumple(src, &error) == NULL);
 721    g_assert(error != NULL);
 722    error_free(error);
 723    error = NULL;
 724    QDECREF(src);
 725}
 726
 727/*
 728 * Errors test-cases
 729 */
 730
 731static void qdict_put_exists_test(void)
 732{
 733    int value;
 734    const char *key = "exists";
 735    QDict *tests_dict = qdict_new();
 736
 737    qdict_put_int(tests_dict, key, 1);
 738    qdict_put_int(tests_dict, key, 2);
 739
 740    value = qdict_get_int(tests_dict, key);
 741    g_assert(value == 2);
 742
 743    g_assert(qdict_size(tests_dict) == 1);
 744
 745    QDECREF(tests_dict);
 746}
 747
 748static void qdict_get_not_exists_test(void)
 749{
 750    QDict *tests_dict = qdict_new();
 751    g_assert(qdict_get(tests_dict, "foo") == NULL);
 752
 753    QDECREF(tests_dict);
 754}
 755
 756/*
 757 * Stress test-case
 758 *
 759 * This is a lot big for a unit-test, but there is no other place
 760 * to have it.
 761 */
 762
 763static void remove_dots(char *string)
 764{
 765    char *p = strchr(string, ':');
 766    if (p)
 767        *p = '\0';
 768}
 769
 770static QString *read_line(FILE *file, char *key)
 771{
 772    char value[128];
 773
 774    if (fscanf(file, "%127s%127s", key, value) == EOF) {
 775        return NULL;
 776    }
 777    remove_dots(key);
 778    return qstring_from_str(value);
 779}
 780
 781#define reset_file(file)    fseek(file, 0L, SEEK_SET)
 782
 783static void qdict_stress_test(void)
 784{
 785    size_t lines;
 786    char key[128];
 787    FILE *test_file;
 788    QDict *qdict;
 789    QString *value;
 790    const char *test_file_path = "qdict-test-data.txt";
 791
 792    test_file = fopen(test_file_path, "r");
 793    g_assert(test_file != NULL);
 794
 795    // Create the dict
 796    qdict = qdict_new();
 797    g_assert(qdict != NULL);
 798
 799    // Add everything from the test file
 800    for (lines = 0;; lines++) {
 801        value = read_line(test_file, key);
 802        if (!value)
 803            break;
 804
 805        qdict_put(qdict, key, value);
 806    }
 807    g_assert(qdict_size(qdict) == lines);
 808
 809    // Check if everything is really in there
 810    reset_file(test_file);
 811    for (;;) {
 812        const char *str1, *str2;
 813
 814        value = read_line(test_file, key);
 815        if (!value)
 816            break;
 817
 818        str1 = qstring_get_str(value);
 819
 820        str2 = qdict_get_str(qdict, key);
 821        g_assert(str2 != NULL);
 822
 823        g_assert(strcmp(str1, str2) == 0);
 824
 825        QDECREF(value);
 826    }
 827
 828    // Delete everything
 829    reset_file(test_file);
 830    for (;;) {
 831        value = read_line(test_file, key);
 832        if (!value)
 833            break;
 834
 835        qdict_del(qdict, key);
 836        QDECREF(value);
 837
 838        g_assert(qdict_haskey(qdict, key) == 0);
 839    }
 840    fclose(test_file);
 841
 842    g_assert(qdict_size(qdict) == 0);
 843    QDECREF(qdict);
 844}
 845
 846int main(int argc, char **argv)
 847{
 848    g_test_init(&argc, &argv, NULL);
 849
 850    g_test_add_func("/public/new", qdict_new_test);
 851    g_test_add_func("/public/put_obj", qdict_put_obj_test);
 852    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
 853
 854    /* Continue, but now with fixtures */
 855    g_test_add_func("/public/get", qdict_get_test);
 856    g_test_add_func("/public/get_int", qdict_get_int_test);
 857    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
 858    g_test_add_func("/public/get_str", qdict_get_str_test);
 859    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
 860    g_test_add_func("/public/defaults", qdict_defaults_test);
 861    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
 862    g_test_add_func("/public/haskey", qdict_haskey_test);
 863    g_test_add_func("/public/del", qdict_del_test);
 864    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
 865    g_test_add_func("/public/iterapi", qdict_iterapi_test);
 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);
 870
 871    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
 872    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
 873
 874    g_test_add_func("/public/crumple/recursive",
 875                    qdict_crumple_test_recursive);
 876    g_test_add_func("/public/crumple/empty",
 877                    qdict_crumple_test_empty);
 878    g_test_add_func("/public/crumple/bad_inputs",
 879                    qdict_crumple_test_bad_inputs);
 880
 881    /* The Big one */
 882    if (g_test_slow()) {
 883        g_test_add_func("/stress/test", qdict_stress_test);
 884    }
 885
 886    return g_test_run();
 887}
 888