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