Blame src/util/support/t_json.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* util/support/t_json.c - JSON test program */
Packit fd8b60
/*
Packit fd8b60
 * Copyright (c) 2010 Kungliga Tekniska Högskolan
Packit fd8b60
 * (Royal Institute of Technology, Stockholm, Sweden).
Packit fd8b60
 * All rights reserved.
Packit fd8b60
 *
Packit fd8b60
 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
Packit fd8b60
 *
Packit fd8b60
 * Redistribution and use in source and binary forms, with or without
Packit fd8b60
 * modification, are permitted provided that the following conditions
Packit fd8b60
 * are met:
Packit fd8b60
 *
Packit fd8b60
 * 1. Redistributions of source code must retain the above copyright
Packit fd8b60
 *    notice, this list of conditions and the following disclaimer.
Packit fd8b60
 *
Packit fd8b60
 * 2. Redistributions in binary form must reproduce the above copyright
Packit fd8b60
 *    notice, this list of conditions and the following disclaimer in the
Packit fd8b60
 *    documentation and/or other materials provided with the distribution.
Packit fd8b60
 *
Packit fd8b60
 * 3. Neither the name of the Institute nor the names of its contributors
Packit fd8b60
 *    may be used to endorse or promote products derived from this software
Packit fd8b60
 *    without specific prior written permission.
Packit fd8b60
 *
Packit fd8b60
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
Packit fd8b60
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit fd8b60
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit fd8b60
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
Packit fd8b60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit fd8b60
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit fd8b60
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit fd8b60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit fd8b60
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit fd8b60
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit fd8b60
 * SUCH DAMAGE.
Packit fd8b60
 */
Packit fd8b60
/*
Packit fd8b60
 * Copyright (C) 2012 by the Massachusetts Institute of Technology.
Packit fd8b60
 * All rights reserved.
Packit fd8b60
 *
Packit fd8b60
 * Redistribution and use in source and binary forms, with or without
Packit fd8b60
 * modification, are permitted provided that the following conditions
Packit fd8b60
 * are met:
Packit fd8b60
 *
Packit fd8b60
 * * Redistributions of source code must retain the above copyright
Packit fd8b60
 *   notice, this list of conditions and the following disclaimer.
Packit fd8b60
 *
Packit fd8b60
 * * Redistributions in binary form must reproduce the above copyright
Packit fd8b60
 *   notice, this list of conditions and the following disclaimer in
Packit fd8b60
 *   the documentation and/or other materials provided with the
Packit fd8b60
 *   distribution.
Packit fd8b60
 *
Packit fd8b60
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit fd8b60
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit fd8b60
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit fd8b60
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit fd8b60
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Packit fd8b60
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit fd8b60
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit fd8b60
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit fd8b60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
Packit fd8b60
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit fd8b60
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
Packit fd8b60
 * OF THE POSSIBILITY OF SUCH DAMAGE.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include <errno.h>
Packit fd8b60
#include <stdio.h>
Packit fd8b60
#include <stdlib.h>
Packit fd8b60
#include <string.h>
Packit fd8b60
Packit fd8b60
#include <k5-json.h>
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
err(const char *str)
Packit fd8b60
{
Packit fd8b60
    fprintf(stderr, "%s\n", str);
Packit fd8b60
    exit(1);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
check(int pred, const char *str)
Packit fd8b60
{
Packit fd8b60
    if (!pred)
Packit fd8b60
        err(str);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test_array()
Packit fd8b60
{
Packit fd8b60
    k5_json_string v1;
Packit fd8b60
    k5_json_number v2;
Packit fd8b60
    k5_json_null v3;
Packit fd8b60
    k5_json_array a;
Packit fd8b60
    k5_json_value v;
Packit fd8b60
Packit fd8b60
    k5_json_array_create(&a);
Packit fd8b60
    k5_json_string_create("abc", &v1;;
Packit fd8b60
    k5_json_array_add(a, v1);
Packit fd8b60
    k5_json_number_create(2, &v2;;
Packit fd8b60
    k5_json_array_add(a, v2);
Packit fd8b60
    k5_json_null_create(&v3;;
Packit fd8b60
    k5_json_array_add(a, v3);
Packit fd8b60
Packit fd8b60
    check(k5_json_array_length(a) == 3, "array length");
Packit fd8b60
    v = k5_json_array_get(a, 2);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "array[2] tid");
Packit fd8b60
    v = k5_json_array_get(a, 1);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "array[1] tid");
Packit fd8b60
    check(k5_json_number_value(v) == 2, "array[1] value");
Packit fd8b60
    v = k5_json_array_get(a, 0);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "array[0] tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v), "abc") == 0, "array[0] value");
Packit fd8b60
Packit fd8b60
    k5_json_release(v1);
Packit fd8b60
    k5_json_release(v2);
Packit fd8b60
    k5_json_release(a);
Packit fd8b60
Packit fd8b60
    k5_json_array_fmt(&a, "vnbiLssB", v3, 1, 9, (long long)-6, "def", NULL,
Packit fd8b60
                      (void *)"ghij", (size_t)4);
Packit fd8b60
    v = k5_json_array_get(a, 0);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[0] tid");
Packit fd8b60
    v = k5_json_array_get(a, 1);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[1] tid");
Packit fd8b60
    v = k5_json_array_get(a, 2);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_BOOL, "fmt array[2] tid");
Packit fd8b60
    check(k5_json_bool_value(v), "fmt array[2] value");
Packit fd8b60
    v = k5_json_array_get(a, 3);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "fmt array[3] tid");
Packit fd8b60
    check(k5_json_number_value(v) == 9, "fmt array[3] value");
Packit fd8b60
    v = k5_json_array_get(a, 4);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "fmt array[4] tid");
Packit fd8b60
    check(k5_json_number_value(v) == -6, "fmt array[4] value");
Packit fd8b60
    v = k5_json_array_get(a, 5);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "fmt array[5] tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v), "def") == 0, "fmt array[5] value");
Packit fd8b60
    v = k5_json_array_get(a, 6);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[6] tid");
Packit fd8b60
    v = k5_json_array_get(a, 7);
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "fmt array[7] tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v), "Z2hpag==") == 0,
Packit fd8b60
          "fmt array[7] value");
Packit fd8b60
    k5_json_release(v3);
Packit fd8b60
    k5_json_release(a);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test_object(void)
Packit fd8b60
{
Packit fd8b60
    k5_json_object object;
Packit fd8b60
    k5_json_number n, v1;
Packit fd8b60
    k5_json_string s, v2;
Packit fd8b60
Packit fd8b60
    k5_json_object_create(&object);
Packit fd8b60
    k5_json_number_create(1, &v1;;
Packit fd8b60
    k5_json_object_set(object, "key1", v1);
Packit fd8b60
    k5_json_string_create("hejsan", &v2;;
Packit fd8b60
    k5_json_object_set(object, "key2", v2);
Packit fd8b60
Packit fd8b60
    n = k5_json_object_get(object, "key1");
Packit fd8b60
    if (k5_json_number_value(n) != 1)
Packit fd8b60
        err("Retrieving key1 from object failed");
Packit fd8b60
Packit fd8b60
    s = k5_json_object_get(object, "key2");
Packit fd8b60
    if (strcmp(k5_json_string_utf8(s), "hejsan") != 0)
Packit fd8b60
        err("Retrieving key2 from object failed");
Packit fd8b60
Packit fd8b60
    check(k5_json_object_get(object, "key3") == NULL,
Packit fd8b60
          "object nonexistent key");
Packit fd8b60
Packit fd8b60
    k5_json_object_set(object, "key1", NULL);
Packit fd8b60
    check(k5_json_object_get(object, "key1") == NULL,
Packit fd8b60
          "object removed key");
Packit fd8b60
    check(k5_json_object_get(object, "key2") != NULL,
Packit fd8b60
          "object remaining key");
Packit fd8b60
Packit fd8b60
    k5_json_release(v1);
Packit fd8b60
    k5_json_release(v2);
Packit fd8b60
    k5_json_release(object);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test_string(void)
Packit fd8b60
{
Packit fd8b60
    k5_json_string s1, s2, s3;
Packit fd8b60
    unsigned char *data;
Packit fd8b60
    size_t len;
Packit fd8b60
Packit fd8b60
    k5_json_string_create("hejsan", &s1;;
Packit fd8b60
    k5_json_string_create("hejsan", &s2;;
Packit fd8b60
    k5_json_string_create_base64("55555", 5, &s3;;
Packit fd8b60
Packit fd8b60
    if (strcmp(k5_json_string_utf8(s1), k5_json_string_utf8(s2)) != 0)
Packit fd8b60
        err("Identical strings are not identical");
Packit fd8b60
    if (strcmp(k5_json_string_utf8(s3), "NTU1NTU=") != 0)
Packit fd8b60
        err("base64 string has incorrect value");
Packit fd8b60
    k5_json_string_unbase64(s3, &data, &len;;
Packit fd8b60
    if (len != 5 || memcmp(data, "55555", 5) != 0)
Packit fd8b60
        err("base64 string doesn't decode to correct value");
Packit fd8b60
    free(data);
Packit fd8b60
Packit fd8b60
    k5_json_release(s1);
Packit fd8b60
    k5_json_release(s2);
Packit fd8b60
    k5_json_release(s3);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test_json(void)
Packit fd8b60
{
Packit fd8b60
    static char *tests[] = {
Packit fd8b60
        "{\"k1\":\"s1\",\"k2\":\"s2\"}",
Packit fd8b60
        "{\"k1\":[\"s1\",\"s2\",\"s3\"],\"k2\":\"s3\"}",
Packit fd8b60
        "{\"k1\":{\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"},\"k5\":\"s4\"}",
Packit fd8b60
        "[\"v1\",\"v2\",[\"v3\",\"v4\",[\"v 5\",\" v 7 \"]],-123456789,"
Packit fd8b60
        "null,true,false,123456789,\"\"]",
Packit fd8b60
        "-1",
Packit fd8b60
        "\"\\\\abc\\\"\\nde\\b\\r/\\ff\\tghi\\u0001\\u001F\"",
Packit fd8b60
        "9223372036854775807",
Packit fd8b60
        "-9223372036854775808",
Packit fd8b60
        NULL
Packit fd8b60
    };
Packit fd8b60
    char **tptr, *s, *enc, *p, orig;
Packit fd8b60
    int i;
Packit fd8b60
    k5_json_value v, v2;
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("\"string\"", &v) == 0, "string1");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "string1 tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v), "string") == 0, "string1 utf8");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("\t \"foo\\\"bar\" ", &v) == 0, "string2");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "string2 tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v), "foo\"bar") == 0, "string2 utf8");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode(" { \"key\" : \"value\" }", &v) == 0, "object1");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_OBJECT, "object1 tid");
Packit fd8b60
    v2 = k5_json_object_get(v, "key");
Packit fd8b60
    check(v2 != NULL, "object[key]");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_STRING, "object1[key] tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v2), "value") == 0, "object1[key] utf8");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("{ \"k1\" : { \"k2\" : \"s2\", \"k3\" : \"s3\" }, "
Packit fd8b60
                         "\"k4\" : \"s4\" }", &v) == 0, "object2");
Packit fd8b60
    v2 = k5_json_object_get(v, "k1");
Packit fd8b60
    check(v2 != NULL, "object2[k1]");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_OBJECT, "object2[k1] tid");
Packit fd8b60
    v2 = k5_json_object_get(v2, "k3");
Packit fd8b60
    check(v2 != NULL, "object2[k1][k3]");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_STRING, "object2[k1][k3] tid");
Packit fd8b60
    check(strcmp(k5_json_string_utf8(v2), "s3") == 0, "object2[k1][k3] utf8");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("{ \"k1\" : 1 }", &v) == 0, "object3");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_OBJECT, "object3 id");
Packit fd8b60
    v2 = k5_json_object_get(v, "k1");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "object3[k1] tid");
Packit fd8b60
    check(k5_json_number_value(v2) == 1, "object3[k1] value");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("-10", &v) == 0, "number1");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "number1 tid");
Packit fd8b60
    check(k5_json_number_value(v) == -10, "number1 value");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("99", &v) == 0, "number2");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "number2 tid");
Packit fd8b60
    check(k5_json_number_value(v) == 99, "number2 value");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode(" [ 1 ]", &v) == 0, "array1");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_ARRAY, "array1 tid");
Packit fd8b60
    check(k5_json_array_length(v) == 1, "array1 len");
Packit fd8b60
    v2 = k5_json_array_get(v, 0);
Packit fd8b60
    check(v2 != NULL, "array1[0]");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "array1[0] tid");
Packit fd8b60
    check(k5_json_number_value(v2) == 1, "array1[0] value");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode(" [ -1 ]", &v) == 0, "array2");
Packit fd8b60
    check(k5_json_get_tid(v) == K5_JSON_TID_ARRAY, "array2 tid");
Packit fd8b60
    check(k5_json_array_length(v) == 1, "array2 len");
Packit fd8b60
    v2 = k5_json_array_get(v, 0);
Packit fd8b60
    check(v2 != NULL, "array2[0]");
Packit fd8b60
    check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "array2[0] tid");
Packit fd8b60
    check(k5_json_number_value(v2) == -1, "array2[0] value");
Packit fd8b60
    k5_json_release(v);
Packit fd8b60
Packit fd8b60
    check(k5_json_decode("18446744073709551616", &v) == EOVERFLOW,
Packit fd8b60
          "unsigned 64-bit overflow");
Packit fd8b60
    check(k5_json_decode("9223372036854775808", &v) == EOVERFLOW,
Packit fd8b60
          "signed 64-bit positive overflow");
Packit fd8b60
    check(k5_json_decode("-9223372036854775809", &v) == EOVERFLOW,
Packit fd8b60
          "signed 64-bit negative overflow");
Packit fd8b60
Packit fd8b60
    for (tptr = tests; *tptr != NULL; tptr++) {
Packit fd8b60
        s = strdup(*tptr);
Packit fd8b60
        if (k5_json_decode(s, &v))
Packit fd8b60
            err(s);
Packit fd8b60
        if (k5_json_encode(v, &enc) || strcmp(enc, s) != 0)
Packit fd8b60
            err(s);
Packit fd8b60
        free(enc);
Packit fd8b60
        k5_json_release(v);
Packit fd8b60
Packit fd8b60
        /* Fuzz bytes.  Parsing may succeed or fail; we're just looking for
Packit fd8b60
         * memory access bugs. */
Packit fd8b60
        for (p = s; *p != '\0'; p++) {
Packit fd8b60
            orig = *p;
Packit fd8b60
            for (i = 0; i <= 255; i++) {
Packit fd8b60
                *p = i;
Packit fd8b60
                k5_json_decode(s, &v);
Packit fd8b60
                k5_json_release(v);
Packit fd8b60
            }
Packit fd8b60
            *p = orig;
Packit fd8b60
        }
Packit fd8b60
        free(s);
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
int
Packit fd8b60
main(int argc, char **argv)
Packit fd8b60
{
Packit fd8b60
    test_array();
Packit fd8b60
    test_object();
Packit fd8b60
    test_string();
Packit fd8b60
    test_json();
Packit fd8b60
    return 0;
Packit fd8b60
}