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