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