qemu/tests/check-qjson.c
<<
>>
Prefs
   1/*
   2 * Copyright IBM, Corp. 2009
   3 * Copyright (c) 2013, 2015 Red Hat Inc.
   4 *
   5 * Authors:
   6 *  Anthony Liguori   <aliguori@us.ibm.com>
   7 *  Markus Armbruster <armbru@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 */
  13#include "qemu/osdep.h"
  14#include <glib.h>
  15
  16#include "qapi/qmp/qstring.h"
  17#include "qapi/qmp/qint.h"
  18#include "qapi/qmp/qdict.h"
  19#include "qapi/qmp/qlist.h"
  20#include "qapi/qmp/qfloat.h"
  21#include "qapi/qmp/qbool.h"
  22#include "qapi/qmp/qjson.h"
  23
  24#include "qemu-common.h"
  25
  26static void escaped_string(void)
  27{
  28    int i;
  29    struct {
  30        const char *encoded;
  31        const char *decoded;
  32        int skip;
  33    } test_cases[] = {
  34        { "\"\\b\"", "\b" },
  35        { "\"\\f\"", "\f" },
  36        { "\"\\n\"", "\n" },
  37        { "\"\\r\"", "\r" },
  38        { "\"\\t\"", "\t" },
  39        { "\"/\"", "/" },
  40        { "\"\\/\"", "/", .skip = 1 },
  41        { "\"\\\\\"", "\\" },
  42        { "\"\\\"\"", "\"" },
  43        { "\"hello world \\\"embedded string\\\"\"",
  44          "hello world \"embedded string\"" },
  45        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
  46        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
  47        { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
  48        { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
  49        { "'\\b'", "\b", .skip = 1 },
  50        { "'\\f'", "\f", .skip = 1 },
  51        { "'\\n'", "\n", .skip = 1 },
  52        { "'\\r'", "\r", .skip = 1 },
  53        { "'\\t'", "\t", .skip = 1 },
  54        { "'\\/'", "/", .skip = 1 },
  55        { "'\\\\'", "\\", .skip = 1 },
  56        {}
  57    };
  58
  59    for (i = 0; test_cases[i].encoded; i++) {
  60        QObject *obj;
  61        QString *str;
  62
  63        obj = qobject_from_json(test_cases[i].encoded);
  64
  65        g_assert(obj != NULL);
  66        g_assert(qobject_type(obj) == QTYPE_QSTRING);
  67        
  68        str = qobject_to_qstring(obj);
  69        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
  70
  71        if (test_cases[i].skip == 0) {
  72            str = qobject_to_json(obj);
  73            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
  74            qobject_decref(obj);
  75        }
  76
  77        QDECREF(str);
  78    }
  79}
  80
  81static void simple_string(void)
  82{
  83    int i;
  84    struct {
  85        const char *encoded;
  86        const char *decoded;
  87    } test_cases[] = {
  88        { "\"hello world\"", "hello world" },
  89        { "\"the quick brown fox jumped over the fence\"",
  90          "the quick brown fox jumped over the fence" },
  91        {}
  92    };
  93
  94    for (i = 0; test_cases[i].encoded; i++) {
  95        QObject *obj;
  96        QString *str;
  97
  98        obj = qobject_from_json(test_cases[i].encoded);
  99
 100        g_assert(obj != NULL);
 101        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 102        
 103        str = qobject_to_qstring(obj);
 104        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 105
 106        str = qobject_to_json(obj);
 107        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 108
 109        qobject_decref(obj);
 110        
 111        QDECREF(str);
 112    }
 113}
 114
 115static void single_quote_string(void)
 116{
 117    int i;
 118    struct {
 119        const char *encoded;
 120        const char *decoded;
 121    } test_cases[] = {
 122        { "'hello world'", "hello world" },
 123        { "'the quick brown fox \\' jumped over the fence'",
 124          "the quick brown fox ' jumped over the fence" },
 125        {}
 126    };
 127
 128    for (i = 0; test_cases[i].encoded; i++) {
 129        QObject *obj;
 130        QString *str;
 131
 132        obj = qobject_from_json(test_cases[i].encoded);
 133
 134        g_assert(obj != NULL);
 135        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 136        
 137        str = qobject_to_qstring(obj);
 138        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 139
 140        QDECREF(str);
 141    }
 142}
 143
 144static void utf8_string(void)
 145{
 146    /*
 147     * FIXME Current behavior for invalid UTF-8 sequences is
 148     * incorrect.  This test expects current, incorrect results.
 149     * They're all marked "bug:" below, and are to be replaced by
 150     * correct ones as the bugs get fixed.
 151     *
 152     * The JSON parser rejects some invalid sequences, but accepts
 153     * others without correcting the problem.
 154     *
 155     * We should either reject all invalid sequences, or minimize
 156     * overlong sequences and replace all other invalid sequences by a
 157     * suitable replacement character.  A common choice for
 158     * replacement is U+FFFD.
 159     *
 160     * Problem: we can't easily deal with embedded U+0000.  Parsing
 161     * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
 162     * which gets misinterpreted as NUL-terminated "this ".  We should
 163     * consider using overlong encoding \xC0\x80 for U+0000 ("modified
 164     * UTF-8").
 165     *
 166     * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
 167     * capability and stress test at
 168     * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
 169     */
 170    static const struct {
 171        const char *json_in;
 172        const char *utf8_out;
 173        const char *json_out;   /* defaults to @json_in */
 174        const char *utf8_in;    /* defaults to @utf8_out */
 175    } test_cases[] = {
 176        /*
 177         * Bug markers used here:
 178         * - bug: not corrected
 179         *   JSON parser fails to correct invalid sequence(s)
 180         * - bug: rejected
 181         *   JSON parser rejects invalid sequence(s)
 182         *   We may choose to define this as feature
 183         * - bug: want "..."
 184         *   JSON parser produces incorrect result, this is the
 185         *   correct one, assuming replacement character U+FFFF
 186         *   We may choose to reject instead of replace
 187         */
 188
 189        /* 1  Some correct UTF-8 text */
 190        {
 191            /* a bit of German */
 192            "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
 193            " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
 194            "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
 195            " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
 196            "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
 197            " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
 198        },
 199        {
 200            /* a bit of Greek */
 201            "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
 202            "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
 203            "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
 204        },
 205        /* 2  Boundary condition test cases */
 206        /* 2.1  First possible sequence of a certain length */
 207        /* 2.1.1  1 byte U+0000 */
 208        {
 209            "\"\\u0000\"",
 210            "",                 /* bug: want overlong "\xC0\x80" */
 211            "\"\\u0000\"",
 212            "\xC0\x80",
 213        },
 214        /* 2.1.2  2 bytes U+0080 */
 215        {
 216            "\"\xC2\x80\"",
 217            "\xC2\x80",
 218            "\"\\u0080\"",
 219        },
 220        /* 2.1.3  3 bytes U+0800 */
 221        {
 222            "\"\xE0\xA0\x80\"",
 223            "\xE0\xA0\x80",
 224            "\"\\u0800\"",
 225        },
 226        /* 2.1.4  4 bytes U+10000 */
 227        {
 228            "\"\xF0\x90\x80\x80\"",
 229            "\xF0\x90\x80\x80",
 230            "\"\\uD800\\uDC00\"",
 231        },
 232        /* 2.1.5  5 bytes U+200000 */
 233        {
 234            "\"\xF8\x88\x80\x80\x80\"",
 235            NULL,               /* bug: rejected */
 236            "\"\\uFFFD\"",
 237            "\xF8\x88\x80\x80\x80",
 238        },
 239        /* 2.1.6  6 bytes U+4000000 */
 240        {
 241            "\"\xFC\x84\x80\x80\x80\x80\"",
 242            NULL,               /* bug: rejected */
 243            "\"\\uFFFD\"",
 244            "\xFC\x84\x80\x80\x80\x80",
 245        },
 246        /* 2.2  Last possible sequence of a certain length */
 247        /* 2.2.1  1 byte U+007F */
 248        {
 249            "\"\x7F\"",
 250            "\x7F",
 251            "\"\\u007F\"",
 252        },
 253        /* 2.2.2  2 bytes U+07FF */
 254        {
 255            "\"\xDF\xBF\"",
 256            "\xDF\xBF",
 257            "\"\\u07FF\"",
 258        },
 259        /*
 260         * 2.2.3  3 bytes U+FFFC
 261         * The last possible sequence is actually U+FFFF.  But that's
 262         * a noncharacter, and already covered by its own test case
 263         * under 5.3.  Same for U+FFFE.  U+FFFD is the last character
 264         * in the BMP, and covered under 2.3.  Because of U+FFFD's
 265         * special role as replacement character, it's worth testing
 266         * U+FFFC here.
 267         */
 268        {
 269            "\"\xEF\xBF\xBC\"",
 270            "\xEF\xBF\xBC",
 271            "\"\\uFFFC\"",
 272        },
 273        /* 2.2.4  4 bytes U+1FFFFF */
 274        {
 275            "\"\xF7\xBF\xBF\xBF\"",
 276            NULL,               /* bug: rejected */
 277            "\"\\uFFFD\"",
 278            "\xF7\xBF\xBF\xBF",
 279        },
 280        /* 2.2.5  5 bytes U+3FFFFFF */
 281        {
 282            "\"\xFB\xBF\xBF\xBF\xBF\"",
 283            NULL,               /* bug: rejected */
 284            "\"\\uFFFD\"",
 285            "\xFB\xBF\xBF\xBF\xBF",
 286        },
 287        /* 2.2.6  6 bytes U+7FFFFFFF */
 288        {
 289            "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
 290            NULL,               /* bug: rejected */
 291            "\"\\uFFFD\"",
 292            "\xFD\xBF\xBF\xBF\xBF\xBF",
 293        },
 294        /* 2.3  Other boundary conditions */
 295        {
 296            /* last one before surrogate range: U+D7FF */
 297            "\"\xED\x9F\xBF\"",
 298            "\xED\x9F\xBF",
 299            "\"\\uD7FF\"",
 300        },
 301        {
 302            /* first one after surrogate range: U+E000 */
 303            "\"\xEE\x80\x80\"",
 304            "\xEE\x80\x80",
 305            "\"\\uE000\"",
 306        },
 307        {
 308            /* last one in BMP: U+FFFD */
 309            "\"\xEF\xBF\xBD\"",
 310            "\xEF\xBF\xBD",
 311            "\"\\uFFFD\"",
 312        },
 313        {
 314            /* last one in last plane: U+10FFFD */
 315            "\"\xF4\x8F\xBF\xBD\"",
 316            "\xF4\x8F\xBF\xBD",
 317            "\"\\uDBFF\\uDFFD\""
 318        },
 319        {
 320            /* first one beyond Unicode range: U+110000 */
 321            "\"\xF4\x90\x80\x80\"",
 322            "\xF4\x90\x80\x80",
 323            "\"\\uFFFD\"",
 324        },
 325        /* 3  Malformed sequences */
 326        /* 3.1  Unexpected continuation bytes */
 327        /* 3.1.1  First continuation byte */
 328        {
 329            "\"\x80\"",
 330            "\x80",             /* bug: not corrected */
 331            "\"\\uFFFD\"",
 332        },
 333        /* 3.1.2  Last continuation byte */
 334        {
 335            "\"\xBF\"",
 336            "\xBF",             /* bug: not corrected */
 337            "\"\\uFFFD\"",
 338        },
 339        /* 3.1.3  2 continuation bytes */
 340        {
 341            "\"\x80\xBF\"",
 342            "\x80\xBF",         /* bug: not corrected */
 343            "\"\\uFFFD\\uFFFD\"",
 344        },
 345        /* 3.1.4  3 continuation bytes */
 346        {
 347            "\"\x80\xBF\x80\"",
 348            "\x80\xBF\x80",     /* bug: not corrected */
 349            "\"\\uFFFD\\uFFFD\\uFFFD\"",
 350        },
 351        /* 3.1.5  4 continuation bytes */
 352        {
 353            "\"\x80\xBF\x80\xBF\"",
 354            "\x80\xBF\x80\xBF", /* bug: not corrected */
 355            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 356        },
 357        /* 3.1.6  5 continuation bytes */
 358        {
 359            "\"\x80\xBF\x80\xBF\x80\"",
 360            "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
 361            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 362        },
 363        /* 3.1.7  6 continuation bytes */
 364        {
 365            "\"\x80\xBF\x80\xBF\x80\xBF\"",
 366            "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
 367            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 368        },
 369        /* 3.1.8  7 continuation bytes */
 370        {
 371            "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
 372            "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
 373            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 374        },
 375        /* 3.1.9  Sequence of all 64 possible continuation bytes */
 376        {
 377            "\"\x80\x81\x82\x83\x84\x85\x86\x87"
 378            "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
 379            "\x90\x91\x92\x93\x94\x95\x96\x97"
 380            "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
 381            "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
 382            "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
 383            "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
 384            "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
 385             /* bug: not corrected */
 386            "\x80\x81\x82\x83\x84\x85\x86\x87"
 387            "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
 388            "\x90\x91\x92\x93\x94\x95\x96\x97"
 389            "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
 390            "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
 391            "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
 392            "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
 393            "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
 394            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 395            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 396            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 397            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 398            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 399            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 400            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 401            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
 402        },
 403        /* 3.2  Lonely start characters */
 404        /* 3.2.1  All 32 first bytes of 2-byte sequences, followed by space */
 405        {
 406            "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
 407            "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
 408            "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
 409            "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
 410            NULL,               /* bug: rejected */
 411            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 412            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 413            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 414            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 415            "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
 416            "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
 417            "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
 418            "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
 419        },
 420        /* 3.2.2  All 16 first bytes of 3-byte sequences, followed by space */
 421        {
 422            "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
 423            "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
 424            /* bug: not corrected */
 425            "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
 426            "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
 427            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 428            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 429        },
 430        /* 3.2.3  All 8 first bytes of 4-byte sequences, followed by space */
 431        {
 432            "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
 433            NULL,               /* bug: rejected */
 434            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 435            "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
 436        },
 437        /* 3.2.4  All 4 first bytes of 5-byte sequences, followed by space */
 438        {
 439            "\"\xF8 \xF9 \xFA \xFB \"",
 440            NULL,               /* bug: rejected */
 441            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 442            "\xF8 \xF9 \xFA \xFB ",
 443        },
 444        /* 3.2.5  All 2 first bytes of 6-byte sequences, followed by space */
 445        {
 446            "\"\xFC \xFD \"",
 447            NULL,               /* bug: rejected */
 448            "\"\\uFFFD \\uFFFD \"",
 449            "\xFC \xFD ",
 450        },
 451        /* 3.3  Sequences with last continuation byte missing */
 452        /* 3.3.1  2-byte sequence with last byte missing (U+0000) */
 453        {
 454            "\"\xC0\"",
 455            NULL,               /* bug: rejected */
 456            "\"\\uFFFD\"",
 457            "\xC0",
 458        },
 459        /* 3.3.2  3-byte sequence with last byte missing (U+0000) */
 460        {
 461            "\"\xE0\x80\"",
 462            "\xE0\x80",           /* bug: not corrected */
 463            "\"\\uFFFD\"",
 464        },
 465        /* 3.3.3  4-byte sequence with last byte missing (U+0000) */
 466        {
 467            "\"\xF0\x80\x80\"",
 468            "\xF0\x80\x80",     /* bug: not corrected */
 469            "\"\\uFFFD\"",
 470        },
 471        /* 3.3.4  5-byte sequence with last byte missing (U+0000) */
 472        {
 473            "\"\xF8\x80\x80\x80\"",
 474            NULL,                   /* bug: rejected */
 475            "\"\\uFFFD\"",
 476            "\xF8\x80\x80\x80",
 477        },
 478        /* 3.3.5  6-byte sequence with last byte missing (U+0000) */
 479        {
 480            "\"\xFC\x80\x80\x80\x80\"",
 481            NULL,                        /* bug: rejected */
 482            "\"\\uFFFD\"",
 483            "\xFC\x80\x80\x80\x80",
 484        },
 485        /* 3.3.6  2-byte sequence with last byte missing (U+07FF) */
 486        {
 487            "\"\xDF\"",
 488            "\xDF",             /* bug: not corrected */
 489            "\"\\uFFFD\"",
 490        },
 491        /* 3.3.7  3-byte sequence with last byte missing (U+FFFF) */
 492        {
 493            "\"\xEF\xBF\"",
 494            "\xEF\xBF",           /* bug: not corrected */
 495            "\"\\uFFFD\"",
 496        },
 497        /* 3.3.8  4-byte sequence with last byte missing (U+1FFFFF) */
 498        {
 499            "\"\xF7\xBF\xBF\"",
 500            NULL,               /* bug: rejected */
 501            "\"\\uFFFD\"",
 502            "\xF7\xBF\xBF",
 503        },
 504        /* 3.3.9  5-byte sequence with last byte missing (U+3FFFFFF) */
 505        {
 506            "\"\xFB\xBF\xBF\xBF\"",
 507            NULL,                 /* bug: rejected */
 508            "\"\\uFFFD\"",
 509            "\xFB\xBF\xBF\xBF",
 510        },
 511        /* 3.3.10  6-byte sequence with last byte missing (U+7FFFFFFF) */
 512        {
 513            "\"\xFD\xBF\xBF\xBF\xBF\"",
 514            NULL,                        /* bug: rejected */
 515            "\"\\uFFFD\"",
 516            "\xFD\xBF\xBF\xBF\xBF",
 517        },
 518        /* 3.4  Concatenation of incomplete sequences */
 519        {
 520            "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
 521            "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
 522            NULL,               /* bug: rejected */
 523            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 524            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 525            "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
 526            "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
 527        },
 528        /* 3.5  Impossible bytes */
 529        {
 530            "\"\xFE\"",
 531            NULL,               /* bug: rejected */
 532            "\"\\uFFFD\"",
 533            "\xFE",
 534        },
 535        {
 536            "\"\xFF\"",
 537            NULL,               /* bug: rejected */
 538            "\"\\uFFFD\"",
 539            "\xFF",
 540        },
 541        {
 542            "\"\xFE\xFE\xFF\xFF\"",
 543            NULL,                 /* bug: rejected */
 544            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 545            "\xFE\xFE\xFF\xFF",
 546        },
 547        /* 4  Overlong sequences */
 548        /* 4.1  Overlong '/' */
 549        {
 550            "\"\xC0\xAF\"",
 551            NULL,               /* bug: rejected */
 552            "\"\\uFFFD\"",
 553            "\xC0\xAF",
 554        },
 555        {
 556            "\"\xE0\x80\xAF\"",
 557            "\xE0\x80\xAF",     /* bug: not corrected */
 558            "\"\\uFFFD\"",
 559        },
 560        {
 561            "\"\xF0\x80\x80\xAF\"",
 562            "\xF0\x80\x80\xAF",  /* bug: not corrected */
 563            "\"\\uFFFD\"",
 564        },
 565        {
 566            "\"\xF8\x80\x80\x80\xAF\"",
 567            NULL,                        /* bug: rejected */
 568            "\"\\uFFFD\"",
 569            "\xF8\x80\x80\x80\xAF",
 570        },
 571        {
 572            "\"\xFC\x80\x80\x80\x80\xAF\"",
 573            NULL,                               /* bug: rejected */
 574            "\"\\uFFFD\"",
 575            "\xFC\x80\x80\x80\x80\xAF",
 576        },
 577        /*
 578         * 4.2  Maximum overlong sequences
 579         * Highest Unicode value that is still resulting in an
 580         * overlong sequence if represented with the given number of
 581         * bytes.  This is a boundary test for safe UTF-8 decoders.
 582         */
 583        {
 584            /* \U+007F */
 585            "\"\xC1\xBF\"",
 586            NULL,               /* bug: rejected */
 587            "\"\\uFFFD\"",
 588            "\xC1\xBF",
 589        },
 590        {
 591            /* \U+07FF */
 592            "\"\xE0\x9F\xBF\"",
 593            "\xE0\x9F\xBF",     /* bug: not corrected */
 594            "\"\\uFFFD\"",
 595        },
 596        {
 597            /*
 598             * \U+FFFC
 599             * The actual maximum would be U+FFFF, but that's a
 600             * noncharacter.  Testing U+FFFC seems more useful.  See
 601             * also 2.2.3
 602             */
 603            "\"\xF0\x8F\xBF\xBC\"",
 604            "\xF0\x8F\xBF\xBC",   /* bug: not corrected */
 605            "\"\\uFFFD\"",
 606        },
 607        {
 608            /* \U+1FFFFF */
 609            "\"\xF8\x87\xBF\xBF\xBF\"",
 610            NULL,                        /* bug: rejected */
 611            "\"\\uFFFD\"",
 612            "\xF8\x87\xBF\xBF\xBF",
 613        },
 614        {
 615            /* \U+3FFFFFF */
 616            "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
 617            NULL,                               /* bug: rejected */
 618            "\"\\uFFFD\"",
 619            "\xFC\x83\xBF\xBF\xBF\xBF",
 620        },
 621        /* 4.3  Overlong representation of the NUL character */
 622        {
 623            /* \U+0000 */
 624            "\"\xC0\x80\"",
 625            NULL,               /* bug: rejected */
 626            "\"\\u0000\"",
 627            "\xC0\x80",
 628        },
 629        {
 630            /* \U+0000 */
 631            "\"\xE0\x80\x80\"",
 632            "\xE0\x80\x80",     /* bug: not corrected */
 633            "\"\\uFFFD\"",
 634        },
 635        {
 636            /* \U+0000 */
 637            "\"\xF0\x80\x80\x80\"",
 638            "\xF0\x80\x80\x80",   /* bug: not corrected */
 639            "\"\\uFFFD\"",
 640        },
 641        {
 642            /* \U+0000 */
 643            "\"\xF8\x80\x80\x80\x80\"",
 644            NULL,                        /* bug: rejected */
 645            "\"\\uFFFD\"",
 646            "\xF8\x80\x80\x80\x80",
 647        },
 648        {
 649            /* \U+0000 */
 650            "\"\xFC\x80\x80\x80\x80\x80\"",
 651            NULL,                               /* bug: rejected */
 652            "\"\\uFFFD\"",
 653            "\xFC\x80\x80\x80\x80\x80",
 654        },
 655        /* 5  Illegal code positions */
 656        /* 5.1  Single UTF-16 surrogates */
 657        {
 658            /* \U+D800 */
 659            "\"\xED\xA0\x80\"",
 660            "\xED\xA0\x80",     /* bug: not corrected */
 661            "\"\\uFFFD\"",
 662        },
 663        {
 664            /* \U+DB7F */
 665            "\"\xED\xAD\xBF\"",
 666            "\xED\xAD\xBF",     /* bug: not corrected */
 667            "\"\\uFFFD\"",
 668        },
 669        {
 670            /* \U+DB80 */
 671            "\"\xED\xAE\x80\"",
 672            "\xED\xAE\x80",     /* bug: not corrected */
 673            "\"\\uFFFD\"",
 674        },
 675        {
 676            /* \U+DBFF */
 677            "\"\xED\xAF\xBF\"",
 678            "\xED\xAF\xBF",     /* bug: not corrected */
 679            "\"\\uFFFD\"",
 680        },
 681        {
 682            /* \U+DC00 */
 683            "\"\xED\xB0\x80\"",
 684            "\xED\xB0\x80",     /* bug: not corrected */
 685            "\"\\uFFFD\"",
 686        },
 687        {
 688            /* \U+DF80 */
 689            "\"\xED\xBE\x80\"",
 690            "\xED\xBE\x80",     /* bug: not corrected */
 691            "\"\\uFFFD\"",
 692        },
 693        {
 694            /* \U+DFFF */
 695            "\"\xED\xBF\xBF\"",
 696            "\xED\xBF\xBF",     /* bug: not corrected */
 697            "\"\\uFFFD\"",
 698        },
 699        /* 5.2  Paired UTF-16 surrogates */
 700        {
 701            /* \U+D800\U+DC00 */
 702            "\"\xED\xA0\x80\xED\xB0\x80\"",
 703            "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
 704            "\"\\uFFFD\\uFFFD\"",
 705        },
 706        {
 707            /* \U+D800\U+DFFF */
 708            "\"\xED\xA0\x80\xED\xBF\xBF\"",
 709            "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
 710            "\"\\uFFFD\\uFFFD\"",
 711        },
 712        {
 713            /* \U+DB7F\U+DC00 */
 714            "\"\xED\xAD\xBF\xED\xB0\x80\"",
 715            "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
 716            "\"\\uFFFD\\uFFFD\"",
 717        },
 718        {
 719            /* \U+DB7F\U+DFFF */
 720            "\"\xED\xAD\xBF\xED\xBF\xBF\"",
 721            "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
 722            "\"\\uFFFD\\uFFFD\"",
 723        },
 724        {
 725            /* \U+DB80\U+DC00 */
 726            "\"\xED\xAE\x80\xED\xB0\x80\"",
 727            "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
 728            "\"\\uFFFD\\uFFFD\"",
 729        },
 730        {
 731            /* \U+DB80\U+DFFF */
 732            "\"\xED\xAE\x80\xED\xBF\xBF\"",
 733            "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
 734            "\"\\uFFFD\\uFFFD\"",
 735        },
 736        {
 737            /* \U+DBFF\U+DC00 */
 738            "\"\xED\xAF\xBF\xED\xB0\x80\"",
 739            "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
 740            "\"\\uFFFD\\uFFFD\"",
 741        },
 742        {
 743            /* \U+DBFF\U+DFFF */
 744            "\"\xED\xAF\xBF\xED\xBF\xBF\"",
 745            "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
 746            "\"\\uFFFD\\uFFFD\"",
 747        },
 748        /* 5.3  Other illegal code positions */
 749        /* BMP noncharacters */
 750        {
 751            /* \U+FFFE */
 752            "\"\xEF\xBF\xBE\"",
 753            "\xEF\xBF\xBE",     /* bug: not corrected */
 754            "\"\\uFFFD\"",
 755        },
 756        {
 757            /* \U+FFFF */
 758            "\"\xEF\xBF\xBF\"",
 759            "\xEF\xBF\xBF",     /* bug: not corrected */
 760            "\"\\uFFFD\"",
 761        },
 762        {
 763            /* U+FDD0 */
 764            "\"\xEF\xB7\x90\"",
 765            "\xEF\xB7\x90",     /* bug: not corrected */
 766            "\"\\uFFFD\"",
 767        },
 768        {
 769            /* U+FDEF */
 770            "\"\xEF\xB7\xAF\"",
 771            "\xEF\xB7\xAF",     /* bug: not corrected */
 772            "\"\\uFFFD\"",
 773        },
 774        /* Plane 1 .. 16 noncharacters */
 775        {
 776            /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
 777            "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
 778            "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
 779            "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
 780            "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
 781            "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
 782            "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
 783            "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
 784            "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
 785            "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
 786            "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
 787            "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
 788            "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
 789            "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
 790            "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
 791            "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
 792            "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
 793            /* bug: not corrected */
 794            "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
 795            "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
 796            "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
 797            "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
 798            "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
 799            "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
 800            "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
 801            "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
 802            "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
 803            "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
 804            "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
 805            "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
 806            "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
 807            "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
 808            "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
 809            "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
 810            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 811            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 812            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 813            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 814        },
 815        {}
 816    };
 817    int i;
 818    QObject *obj;
 819    QString *str;
 820    const char *json_in, *utf8_out, *utf8_in, *json_out;
 821
 822    for (i = 0; test_cases[i].json_in; i++) {
 823        json_in = test_cases[i].json_in;
 824        utf8_out = test_cases[i].utf8_out;
 825        utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
 826        json_out = test_cases[i].json_out ?: test_cases[i].json_in;
 827
 828        obj = qobject_from_json(json_in);
 829        if (utf8_out) {
 830            g_assert(obj);
 831            g_assert(qobject_type(obj) == QTYPE_QSTRING);
 832            str = qobject_to_qstring(obj);
 833            g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
 834        } else {
 835            g_assert(!obj);
 836        }
 837        qobject_decref(obj);
 838
 839        obj = QOBJECT(qstring_from_str(utf8_in));
 840        str = qobject_to_json(obj);
 841        if (json_out) {
 842            g_assert(str);
 843            g_assert_cmpstr(qstring_get_str(str), ==, json_out);
 844        } else {
 845            g_assert(!str);
 846        }
 847        QDECREF(str);
 848        qobject_decref(obj);
 849
 850        /*
 851         * Disabled, because qobject_from_json() is buggy, and I can't
 852         * be bothered to add the expected incorrect results.
 853         * FIXME Enable once these bugs have been fixed.
 854         */
 855        if (0 && json_out != json_in) {
 856            obj = qobject_from_json(json_out);
 857            g_assert(obj);
 858            g_assert(qobject_type(obj) == QTYPE_QSTRING);
 859            str = qobject_to_qstring(obj);
 860            g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
 861        }
 862    }
 863}
 864
 865static void vararg_string(void)
 866{
 867    int i;
 868    struct {
 869        const char *decoded;
 870    } test_cases[] = {
 871        { "hello world" },
 872        { "the quick brown fox jumped over the fence" },
 873        {}
 874    };
 875
 876    for (i = 0; test_cases[i].decoded; i++) {
 877        QObject *obj;
 878        QString *str;
 879
 880        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
 881
 882        g_assert(obj != NULL);
 883        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 884        
 885        str = qobject_to_qstring(obj);
 886        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 887
 888        QDECREF(str);
 889    }
 890}
 891
 892static void simple_number(void)
 893{
 894    int i;
 895    struct {
 896        const char *encoded;
 897        int64_t decoded;
 898        int skip;
 899    } test_cases[] = {
 900        { "0", 0 },
 901        { "1234", 1234 },
 902        { "1", 1 },
 903        { "-32", -32 },
 904        { "-0", 0, .skip = 1 },
 905        { },
 906    };
 907
 908    for (i = 0; test_cases[i].encoded; i++) {
 909        QObject *obj;
 910        QInt *qint;
 911
 912        obj = qobject_from_json(test_cases[i].encoded);
 913        g_assert(obj != NULL);
 914        g_assert(qobject_type(obj) == QTYPE_QINT);
 915
 916        qint = qobject_to_qint(obj);
 917        g_assert(qint_get_int(qint) == test_cases[i].decoded);
 918        if (test_cases[i].skip == 0) {
 919            QString *str;
 920
 921            str = qobject_to_json(obj);
 922            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 923            QDECREF(str);
 924        }
 925
 926        QDECREF(qint);
 927    }
 928}
 929
 930static void float_number(void)
 931{
 932    int i;
 933    struct {
 934        const char *encoded;
 935        double decoded;
 936        int skip;
 937    } test_cases[] = {
 938        { "32.43", 32.43 },
 939        { "0.222", 0.222 },
 940        { "-32.12313", -32.12313 },
 941        { "-32.20e-10", -32.20e-10, .skip = 1 },
 942        { },
 943    };
 944
 945    for (i = 0; test_cases[i].encoded; i++) {
 946        QObject *obj;
 947        QFloat *qfloat;
 948
 949        obj = qobject_from_json(test_cases[i].encoded);
 950        g_assert(obj != NULL);
 951        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 952
 953        qfloat = qobject_to_qfloat(obj);
 954        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
 955
 956        if (test_cases[i].skip == 0) {
 957            QString *str;
 958
 959            str = qobject_to_json(obj);
 960            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 961            QDECREF(str);
 962        }
 963
 964        QDECREF(qfloat);
 965    }
 966}
 967
 968static void vararg_number(void)
 969{
 970    QObject *obj;
 971    QInt *qint;
 972    QFloat *qfloat;
 973    int value = 0x2342;
 974    int64_t value64 = 0x2342342343LL;
 975    double valuef = 2.323423423;
 976
 977    obj = qobject_from_jsonf("%d", value);
 978    g_assert(obj != NULL);
 979    g_assert(qobject_type(obj) == QTYPE_QINT);
 980
 981    qint = qobject_to_qint(obj);
 982    g_assert(qint_get_int(qint) == value);
 983
 984    QDECREF(qint);
 985
 986    obj = qobject_from_jsonf("%" PRId64, value64);
 987    g_assert(obj != NULL);
 988    g_assert(qobject_type(obj) == QTYPE_QINT);
 989
 990    qint = qobject_to_qint(obj);
 991    g_assert(qint_get_int(qint) == value64);
 992
 993    QDECREF(qint);
 994
 995    obj = qobject_from_jsonf("%f", valuef);
 996    g_assert(obj != NULL);
 997    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 998
 999    qfloat = qobject_to_qfloat(obj);
1000    g_assert(qfloat_get_double(qfloat) == valuef);
1001
1002    QDECREF(qfloat);
1003}
1004
1005static void keyword_literal(void)
1006{
1007    QObject *obj;
1008    QBool *qbool;
1009    QObject *null;
1010    QString *str;
1011
1012    obj = qobject_from_json("true");
1013    g_assert(obj != NULL);
1014    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1015
1016    qbool = qobject_to_qbool(obj);
1017    g_assert(qbool_get_bool(qbool) == true);
1018
1019    str = qobject_to_json(obj);
1020    g_assert(strcmp(qstring_get_str(str), "true") == 0);
1021    QDECREF(str);
1022
1023    QDECREF(qbool);
1024
1025    obj = qobject_from_json("false");
1026    g_assert(obj != NULL);
1027    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1028
1029    qbool = qobject_to_qbool(obj);
1030    g_assert(qbool_get_bool(qbool) == false);
1031
1032    str = qobject_to_json(obj);
1033    g_assert(strcmp(qstring_get_str(str), "false") == 0);
1034    QDECREF(str);
1035
1036    QDECREF(qbool);
1037
1038    obj = qobject_from_jsonf("%i", false);
1039    g_assert(obj != NULL);
1040    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1041
1042    qbool = qobject_to_qbool(obj);
1043    g_assert(qbool_get_bool(qbool) == false);
1044
1045    QDECREF(qbool);
1046
1047    /* Test that non-zero values other than 1 get collapsed to true */
1048    obj = qobject_from_jsonf("%i", 2);
1049    g_assert(obj != NULL);
1050    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1051
1052    qbool = qobject_to_qbool(obj);
1053    g_assert(qbool_get_bool(qbool) == true);
1054
1055    QDECREF(qbool);
1056
1057    obj = qobject_from_json("null");
1058    g_assert(obj != NULL);
1059    g_assert(qobject_type(obj) == QTYPE_QNULL);
1060
1061    null = qnull();
1062    g_assert(null == obj);
1063
1064    qobject_decref(obj);
1065    qobject_decref(null);
1066}
1067
1068typedef struct LiteralQDictEntry LiteralQDictEntry;
1069typedef struct LiteralQObject LiteralQObject;
1070
1071struct LiteralQObject
1072{
1073    int type;
1074    union {
1075        int64_t qint;
1076        const char *qstr;
1077        LiteralQDictEntry *qdict;
1078        LiteralQObject *qlist;
1079    } value;
1080};
1081
1082struct LiteralQDictEntry
1083{
1084    const char *key;
1085    LiteralQObject value;
1086};
1087
1088#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1089#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1090#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1091#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1092
1093typedef struct QListCompareHelper
1094{
1095    int index;
1096    LiteralQObject *objs;
1097    int result;
1098} QListCompareHelper;
1099
1100static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1101
1102static void compare_helper(QObject *obj, void *opaque)
1103{
1104    QListCompareHelper *helper = opaque;
1105
1106    if (helper->result == 0) {
1107        return;
1108    }
1109
1110    if (helper->objs[helper->index].type == QTYPE_NONE) {
1111        helper->result = 0;
1112        return;
1113    }
1114
1115    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1116}
1117
1118static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1119{
1120    if (lhs->type != qobject_type(rhs)) {
1121        return 0;
1122    }
1123
1124    switch (lhs->type) {
1125    case QTYPE_QINT:
1126        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1127    case QTYPE_QSTRING:
1128        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1129    case QTYPE_QDICT: {
1130        int i;
1131
1132        for (i = 0; lhs->value.qdict[i].key; i++) {
1133            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1134
1135            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1136                return 0;
1137            }
1138        }
1139
1140        return 1;
1141    }
1142    case QTYPE_QLIST: {
1143        QListCompareHelper helper;
1144
1145        helper.index = 0;
1146        helper.objs = lhs->value.qlist;
1147        helper.result = 1;
1148        
1149        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1150
1151        return helper.result;
1152    }
1153    default:
1154        break;
1155    }
1156
1157    return 0;
1158}
1159
1160static void simple_dict(void)
1161{
1162    int i;
1163    struct {
1164        const char *encoded;
1165        LiteralQObject decoded;
1166    } test_cases[] = {
1167        {
1168            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1169            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1170                        { "foo", QLIT_QINT(42) },
1171                        { "bar", QLIT_QSTR("hello world") },
1172                        { }
1173                    })),
1174        }, {
1175            .encoded = "{}",
1176            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1177                        { }
1178                    })),
1179        }, {
1180            .encoded = "{\"foo\": 43}",
1181            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1182                        { "foo", QLIT_QINT(43) },
1183                        { }
1184                    })),
1185        },
1186        { }
1187    };
1188
1189    for (i = 0; test_cases[i].encoded; i++) {
1190        QObject *obj;
1191        QString *str;
1192
1193        obj = qobject_from_json(test_cases[i].encoded);
1194        g_assert(obj != NULL);
1195        g_assert(qobject_type(obj) == QTYPE_QDICT);
1196
1197        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1198
1199        str = qobject_to_json(obj);
1200        qobject_decref(obj);
1201
1202        obj = qobject_from_json(qstring_get_str(str));
1203        g_assert(obj != NULL);
1204        g_assert(qobject_type(obj) == QTYPE_QDICT);
1205
1206        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1207        qobject_decref(obj);
1208        QDECREF(str);
1209    }
1210}
1211
1212/*
1213 * this generates json of the form:
1214 * a(0,m) = [0, 1, ..., m-1]
1215 * a(n,m) = {
1216 *            'key0': a(0,m),
1217 *            'key1': a(1,m),
1218 *            ...
1219 *            'key(n-1)': a(n-1,m)
1220 *          }
1221 */
1222static void gen_test_json(GString *gstr, int nest_level_max,
1223                          int elem_count)
1224{
1225    int i;
1226
1227    g_assert(gstr);
1228    if (nest_level_max == 0) {
1229        g_string_append(gstr, "[");
1230        for (i = 0; i < elem_count; i++) {
1231            g_string_append_printf(gstr, "%d", i);
1232            if (i < elem_count - 1) {
1233                g_string_append_printf(gstr, ", ");
1234            }
1235        }
1236        g_string_append(gstr, "]");
1237        return;
1238    }
1239
1240    g_string_append(gstr, "{");
1241    for (i = 0; i < nest_level_max; i++) {
1242        g_string_append_printf(gstr, "'key%d': ", i);
1243        gen_test_json(gstr, i, elem_count);
1244        if (i < nest_level_max - 1) {
1245            g_string_append(gstr, ",");
1246        }
1247    }
1248    g_string_append(gstr, "}");
1249}
1250
1251static void large_dict(void)
1252{
1253    GString *gstr = g_string_new("");
1254    QObject *obj;
1255
1256    gen_test_json(gstr, 10, 100);
1257    obj = qobject_from_json(gstr->str);
1258    g_assert(obj != NULL);
1259
1260    qobject_decref(obj);
1261    g_string_free(gstr, true);
1262}
1263
1264static void simple_list(void)
1265{
1266    int i;
1267    struct {
1268        const char *encoded;
1269        LiteralQObject decoded;
1270    } test_cases[] = {
1271        {
1272            .encoded = "[43,42]",
1273            .decoded = QLIT_QLIST(((LiteralQObject[]){
1274                        QLIT_QINT(43),
1275                        QLIT_QINT(42),
1276                        { }
1277                    })),
1278        },
1279        {
1280            .encoded = "[43]",
1281            .decoded = QLIT_QLIST(((LiteralQObject[]){
1282                        QLIT_QINT(43),
1283                        { }
1284                    })),
1285        },
1286        {
1287            .encoded = "[]",
1288            .decoded = QLIT_QLIST(((LiteralQObject[]){
1289                        { }
1290                    })),
1291        },
1292        {
1293            .encoded = "[{}]",
1294            .decoded = QLIT_QLIST(((LiteralQObject[]){
1295                        QLIT_QDICT(((LiteralQDictEntry[]){
1296                                    {},
1297                                        })),
1298                        {},
1299                            })),
1300        },
1301        { }
1302    };
1303
1304    for (i = 0; test_cases[i].encoded; i++) {
1305        QObject *obj;
1306        QString *str;
1307
1308        obj = qobject_from_json(test_cases[i].encoded);
1309        g_assert(obj != NULL);
1310        g_assert(qobject_type(obj) == QTYPE_QLIST);
1311
1312        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1313
1314        str = qobject_to_json(obj);
1315        qobject_decref(obj);
1316
1317        obj = qobject_from_json(qstring_get_str(str));
1318        g_assert(obj != NULL);
1319        g_assert(qobject_type(obj) == QTYPE_QLIST);
1320
1321        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1322        qobject_decref(obj);
1323        QDECREF(str);
1324    }
1325}
1326
1327static void simple_whitespace(void)
1328{
1329    int i;
1330    struct {
1331        const char *encoded;
1332        LiteralQObject decoded;
1333    } test_cases[] = {
1334        {
1335            .encoded = " [ 43 , 42 ]",
1336            .decoded = QLIT_QLIST(((LiteralQObject[]){
1337                        QLIT_QINT(43),
1338                        QLIT_QINT(42),
1339                        { }
1340                    })),
1341        },
1342        {
1343            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1344            .decoded = QLIT_QLIST(((LiteralQObject[]){
1345                        QLIT_QINT(43),
1346                        QLIT_QDICT(((LiteralQDictEntry[]){
1347                                    { "h", QLIT_QSTR("b") },
1348                                    { }})),
1349                        QLIT_QLIST(((LiteralQObject[]){
1350                                    { }})),
1351                        QLIT_QINT(42),
1352                        { }
1353                    })),
1354        },
1355        {
1356            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1357            .decoded = QLIT_QLIST(((LiteralQObject[]){
1358                        QLIT_QINT(43),
1359                        QLIT_QDICT(((LiteralQDictEntry[]){
1360                                    { "h", QLIT_QSTR("b") },
1361                                    { "a", QLIT_QINT(32) },
1362                                    { }})),
1363                        QLIT_QLIST(((LiteralQObject[]){
1364                                    { }})),
1365                        QLIT_QINT(42),
1366                        { }
1367                    })),
1368        },
1369        { }
1370    };
1371
1372    for (i = 0; test_cases[i].encoded; i++) {
1373        QObject *obj;
1374        QString *str;
1375
1376        obj = qobject_from_json(test_cases[i].encoded);
1377        g_assert(obj != NULL);
1378        g_assert(qobject_type(obj) == QTYPE_QLIST);
1379
1380        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1381
1382        str = qobject_to_json(obj);
1383        qobject_decref(obj);
1384
1385        obj = qobject_from_json(qstring_get_str(str));
1386        g_assert(obj != NULL);
1387        g_assert(qobject_type(obj) == QTYPE_QLIST);
1388
1389        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1390
1391        qobject_decref(obj);
1392        QDECREF(str);
1393    }
1394}
1395
1396static void simple_varargs(void)
1397{
1398    QObject *embedded_obj;
1399    QObject *obj;
1400    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1401            QLIT_QINT(1),
1402            QLIT_QINT(2),
1403            QLIT_QLIST(((LiteralQObject[]){
1404                        QLIT_QINT(32),
1405                        QLIT_QINT(42),
1406                        {}})),
1407            {}}));
1408
1409    embedded_obj = qobject_from_json("[32, 42]");
1410    g_assert(embedded_obj != NULL);
1411
1412    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1413    g_assert(obj != NULL);
1414
1415    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1416
1417    qobject_decref(obj);
1418}
1419
1420static void empty_input(void)
1421{
1422    const char *empty = "";
1423
1424    QObject *obj = qobject_from_json(empty);
1425    g_assert(obj == NULL);
1426}
1427
1428static void unterminated_string(void)
1429{
1430    QObject *obj = qobject_from_json("\"abc");
1431    g_assert(obj == NULL);
1432}
1433
1434static void unterminated_sq_string(void)
1435{
1436    QObject *obj = qobject_from_json("'abc");
1437    g_assert(obj == NULL);
1438}
1439
1440static void unterminated_escape(void)
1441{
1442    QObject *obj = qobject_from_json("\"abc\\\"");
1443    g_assert(obj == NULL);
1444}
1445
1446static void unterminated_array(void)
1447{
1448    QObject *obj = qobject_from_json("[32");
1449    g_assert(obj == NULL);
1450}
1451
1452static void unterminated_array_comma(void)
1453{
1454    QObject *obj = qobject_from_json("[32,");
1455    g_assert(obj == NULL);
1456}
1457
1458static void invalid_array_comma(void)
1459{
1460    QObject *obj = qobject_from_json("[32,}");
1461    g_assert(obj == NULL);
1462}
1463
1464static void unterminated_dict(void)
1465{
1466    QObject *obj = qobject_from_json("{'abc':32");
1467    g_assert(obj == NULL);
1468}
1469
1470static void unterminated_dict_comma(void)
1471{
1472    QObject *obj = qobject_from_json("{'abc':32,");
1473    g_assert(obj == NULL);
1474}
1475
1476static void invalid_dict_comma(void)
1477{
1478    QObject *obj = qobject_from_json("{'abc':32,}");
1479    g_assert(obj == NULL);
1480}
1481
1482static void unterminated_literal(void)
1483{
1484    QObject *obj = qobject_from_json("nul");
1485    g_assert(obj == NULL);
1486}
1487
1488static char *make_nest(char *buf, size_t cnt)
1489{
1490    memset(buf, '[', cnt - 1);
1491    buf[cnt - 1] = '{';
1492    buf[cnt] = '}';
1493    memset(buf + cnt + 1, ']', cnt - 1);
1494    buf[2 * cnt] = 0;
1495    return buf;
1496}
1497
1498static void limits_nesting(void)
1499{
1500    enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1501    char buf[2 * (max_nesting + 1) + 1];
1502    QObject *obj;
1503
1504    obj = qobject_from_json(make_nest(buf, max_nesting));
1505    g_assert(obj != NULL);
1506    qobject_decref(obj);
1507
1508    obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1509    g_assert(obj == NULL);
1510}
1511
1512int main(int argc, char **argv)
1513{
1514    g_test_init(&argc, &argv, NULL);
1515
1516    g_test_add_func("/literals/string/simple", simple_string);
1517    g_test_add_func("/literals/string/escaped", escaped_string);
1518    g_test_add_func("/literals/string/utf8", utf8_string);
1519    g_test_add_func("/literals/string/single_quote", single_quote_string);
1520    g_test_add_func("/literals/string/vararg", vararg_string);
1521
1522    g_test_add_func("/literals/number/simple", simple_number);
1523    g_test_add_func("/literals/number/float", float_number);
1524    g_test_add_func("/literals/number/vararg", vararg_number);
1525
1526    g_test_add_func("/literals/keyword", keyword_literal);
1527
1528    g_test_add_func("/dicts/simple_dict", simple_dict);
1529    g_test_add_func("/dicts/large_dict", large_dict);
1530    g_test_add_func("/lists/simple_list", simple_list);
1531
1532    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1533
1534    g_test_add_func("/varargs/simple_varargs", simple_varargs);
1535
1536    g_test_add_func("/errors/empty_input", empty_input);
1537    g_test_add_func("/errors/unterminated/string", unterminated_string);
1538    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1539    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1540    g_test_add_func("/errors/unterminated/array", unterminated_array);
1541    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1542    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1543    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1544    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1545    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1546    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1547    g_test_add_func("/errors/limits/nesting", limits_nesting);
1548
1549    return g_test_run();
1550}
1551