2009-10-27 23:46:57 +08:00
|
|
|
/*
|
2016-09-18 19:17:03 +08:00
|
|
|
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
2009-10-27 23:46:57 +08:00
|
|
|
*
|
|
|
|
* Jansson is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
|
|
*/
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
#include "util.h"
|
2009-10-27 23:46:57 +08:00
|
|
|
#include <jansson.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void file_not_found() {
|
2009-10-27 23:46:57 +08:00
|
|
|
json_t *json;
|
2010-10-27 02:05:40 +08:00
|
|
|
json_error_t error;
|
2012-01-31 03:23:15 +08:00
|
|
|
char *pos;
|
2009-10-27 23:46:57 +08:00
|
|
|
|
2010-08-14 03:19:20 +08:00
|
|
|
json = json_load_file("/path/to/nonexistent/file.json", 0, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json)
|
2011-04-05 20:04:16 +08:00
|
|
|
fail("json_load_file returned non-NULL for a nonexistent file");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (error.line != -1)
|
2009-10-27 23:46:57 +08:00
|
|
|
fail("json_load_file returned an invalid line number");
|
2012-01-31 03:23:15 +08:00
|
|
|
|
|
|
|
/* The error message is locale specific, only check the beginning
|
|
|
|
of the error message. */
|
|
|
|
|
|
|
|
pos = strchr(error.text, ':');
|
2019-10-17 14:08:51 +08:00
|
|
|
if (!pos)
|
2012-01-31 03:23:15 +08:00
|
|
|
fail("json_load_file returne an invalid error message");
|
|
|
|
|
|
|
|
*pos = '\0';
|
|
|
|
|
2019-10-20 01:35:28 +08:00
|
|
|
if (strcmp(error.text, "unable to open /path/to/nonexistent/file.json") != 0)
|
2009-10-27 23:46:57 +08:00
|
|
|
fail("json_load_file returned an invalid error message");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_error_code(&error) != json_error_cannot_open_file)
|
2017-10-03 17:42:07 +08:00
|
|
|
fail("json_load_file returned an invalid error code");
|
2011-05-15 18:57:48 +08:00
|
|
|
}
|
|
|
|
|
2014-12-19 14:35:31 +08:00
|
|
|
static void very_long_file_name() {
|
|
|
|
json_t *json;
|
|
|
|
json_error_t error;
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
json = json_load_file("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
|
|
0, &error);
|
|
|
|
if (json)
|
2014-12-19 14:35:31 +08:00
|
|
|
fail("json_load_file returned non-NULL for a nonexistent file");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (error.line != -1)
|
2014-12-19 14:35:31 +08:00
|
|
|
fail("json_load_file returned an invalid line number");
|
|
|
|
|
|
|
|
if (strncmp(error.source, "...aaa", 6) != 0)
|
|
|
|
fail("error source was set incorrectly");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_error_code(&error) != json_error_cannot_open_file)
|
2017-10-03 17:42:07 +08:00
|
|
|
fail("error code was set incorrectly");
|
2014-12-19 14:35:31 +08:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void reject_duplicates() {
|
2011-05-15 18:57:48 +08:00
|
|
|
json_error_t error;
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_loads("{\"foo\": 1, \"foo\": 2}", JSON_REJECT_DUPLICATES, &error))
|
2011-05-15 18:57:48 +08:00
|
|
|
fail("json_loads did not detect a duplicate key");
|
2019-10-17 14:08:51 +08:00
|
|
|
check_error(json_error_duplicate_key, "duplicate object key near '\"foo\"'",
|
|
|
|
"<string>", 1, 16, 16);
|
2011-05-15 18:57:48 +08:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void disable_eof_check() {
|
2011-05-30 02:19:28 +08:00
|
|
|
json_error_t error;
|
|
|
|
json_t *json;
|
|
|
|
|
|
|
|
const char *text = "{\"foo\": 1} garbage";
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_loads(text, 0, &error))
|
2011-05-30 02:19:28 +08:00
|
|
|
fail("json_loads did not detect garbage after JSON text");
|
2019-10-20 01:35:28 +08:00
|
|
|
check_error(json_error_end_of_input_expected, "end of file expected near 'garbage'",
|
|
|
|
"<string>", 1, 18, 18);
|
2011-05-30 02:19:28 +08:00
|
|
|
|
|
|
|
json = json_loads(text, JSON_DISABLE_EOF_CHECK, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (!json)
|
2011-05-30 02:19:28 +08:00
|
|
|
fail("json_loads failed with JSON_DISABLE_EOF_CHECK");
|
|
|
|
|
|
|
|
json_decref(json);
|
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void decode_any() {
|
2011-11-12 02:17:29 +08:00
|
|
|
json_t *json;
|
|
|
|
json_error_t error;
|
|
|
|
|
|
|
|
json = json_loads("\"foo\"", JSON_DECODE_ANY, &error);
|
|
|
|
if (!json || !json_is_string(json))
|
|
|
|
fail("json_load decoded any failed - string");
|
|
|
|
json_decref(json);
|
|
|
|
|
|
|
|
json = json_loads("42", JSON_DECODE_ANY, &error);
|
|
|
|
if (!json || !json_is_integer(json))
|
|
|
|
fail("json_load decoded any failed - integer");
|
|
|
|
json_decref(json);
|
|
|
|
|
|
|
|
json = json_loads("true", JSON_DECODE_ANY, &error);
|
|
|
|
if (!json || !json_is_true(json))
|
|
|
|
fail("json_load decoded any failed - boolean");
|
|
|
|
json_decref(json);
|
|
|
|
|
|
|
|
json = json_loads("null", JSON_DECODE_ANY, &error);
|
|
|
|
if (!json || !json_is_null(json))
|
|
|
|
fail("json_load decoded any failed - null");
|
|
|
|
json_decref(json);
|
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void decode_int_as_real() {
|
2013-06-09 22:34:30 +08:00
|
|
|
json_t *json;
|
|
|
|
json_error_t error;
|
|
|
|
|
2013-06-13 18:37:07 +08:00
|
|
|
#if JSON_INTEGER_IS_LONG_LONG
|
2013-06-12 13:36:51 +08:00
|
|
|
const char *imprecise;
|
|
|
|
json_int_t expected;
|
2013-06-13 18:37:07 +08:00
|
|
|
#endif
|
2013-06-11 22:09:08 +08:00
|
|
|
|
2014-12-18 21:16:14 +08:00
|
|
|
char big[311];
|
|
|
|
|
2013-06-11 18:53:35 +08:00
|
|
|
json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
|
2013-06-09 22:34:30 +08:00
|
|
|
if (!json || !json_is_real(json) || json_real_value(json) != 42.0)
|
2013-06-11 22:09:08 +08:00
|
|
|
fail("json_load decode int as real failed - int");
|
|
|
|
json_decref(json);
|
|
|
|
|
2013-06-12 13:36:51 +08:00
|
|
|
#if JSON_INTEGER_IS_LONG_LONG
|
|
|
|
/* This number cannot be represented exactly by a double */
|
|
|
|
imprecise = "9007199254740993";
|
|
|
|
expected = 9007199254740992ll;
|
|
|
|
|
2019-10-20 01:35:28 +08:00
|
|
|
json = json_loads(imprecise, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
|
|
|
|
if (!json || !json_is_real(json) || expected != (json_int_t)json_real_value(json))
|
2013-06-12 13:36:51 +08:00
|
|
|
fail("json_load decode int as real failed - expected imprecision");
|
2013-06-09 22:34:30 +08:00
|
|
|
json_decref(json);
|
2013-06-12 13:36:51 +08:00
|
|
|
#endif
|
2014-12-18 21:16:14 +08:00
|
|
|
|
|
|
|
/* 1E309 overflows. Here we create 1E309 as a decimal number, i.e.
|
|
|
|
1000...(309 zeroes)...0. */
|
|
|
|
big[0] = '1';
|
|
|
|
memset(big + 1, '0', 309);
|
|
|
|
big[310] = '\0';
|
|
|
|
|
|
|
|
json = json_loads(big, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
|
2017-10-03 17:42:07 +08:00
|
|
|
if (json || strcmp(error.text, "real number overflow") != 0 ||
|
|
|
|
json_error_code(&error) != json_error_numeric_overflow)
|
2014-12-18 21:16:14 +08:00
|
|
|
fail("json_load decode int as real failed - expected overflow");
|
|
|
|
json_decref(json);
|
2013-06-09 22:34:30 +08:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void allow_nul() {
|
2013-09-30 15:44:35 +08:00
|
|
|
const char *text = "\"nul byte \\u0000 in string\"";
|
|
|
|
const char *expected = "nul byte \0 in string";
|
|
|
|
size_t len = 20;
|
|
|
|
json_t *json;
|
|
|
|
|
|
|
|
json = json_loads(text, JSON_ALLOW_NUL | JSON_DECODE_ANY, NULL);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (!json || !json_is_string(json))
|
2013-09-30 15:44:35 +08:00
|
|
|
fail("unable to decode embedded NUL byte");
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_string_length(json) != len)
|
2013-09-30 15:44:35 +08:00
|
|
|
fail("decoder returned wrong string length");
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
if (memcmp(json_string_value(json), expected, len + 1))
|
2013-09-30 15:44:35 +08:00
|
|
|
fail("decoder returned wrong string content");
|
|
|
|
|
|
|
|
json_decref(json);
|
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void load_wrong_args() {
|
2011-11-12 02:17:50 +08:00
|
|
|
json_t *json;
|
|
|
|
json_error_t error;
|
|
|
|
|
|
|
|
json = json_loads(NULL, 0, &error);
|
|
|
|
if (json)
|
|
|
|
fail("json_loads should return NULL if the first argument is NULL");
|
|
|
|
|
|
|
|
json = json_loadb(NULL, 0, 0, &error);
|
|
|
|
if (json)
|
|
|
|
fail("json_loadb should return NULL if the first argument is NULL");
|
|
|
|
|
|
|
|
json = json_loadf(NULL, 0, &error);
|
|
|
|
if (json)
|
|
|
|
fail("json_loadf should return NULL if the first argument is NULL");
|
|
|
|
|
2017-01-27 00:23:31 +08:00
|
|
|
json = json_loadfd(-1, 0, &error);
|
|
|
|
if (json)
|
|
|
|
fail("json_loadfd should return NULL if the first argument is < 0");
|
|
|
|
|
2011-11-12 02:17:50 +08:00
|
|
|
json = json_load_file(NULL, 0, &error);
|
|
|
|
if (json)
|
2017-01-27 00:23:31 +08:00
|
|
|
fail("json_load_file should return NULL if the first argument is NULL");
|
2011-11-12 02:17:50 +08:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void position() {
|
2012-01-24 03:18:04 +08:00
|
|
|
json_t *json;
|
|
|
|
size_t flags = JSON_DISABLE_EOF_CHECK;
|
|
|
|
json_error_t error;
|
|
|
|
|
|
|
|
json = json_loads("{\"foo\": \"bar\"}", 0, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (error.position != 14)
|
2012-01-24 03:18:04 +08:00
|
|
|
fail("json_loads returned a wrong position");
|
|
|
|
json_decref(json);
|
|
|
|
|
|
|
|
json = json_loads("{\"foo\": \"bar\"} baz quux", flags, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (error.position != 14)
|
2012-01-24 03:18:04 +08:00
|
|
|
fail("json_loads returned a wrong position");
|
|
|
|
json_decref(json);
|
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void error_code() {
|
2017-10-03 17:42:07 +08:00
|
|
|
json_error_t error;
|
|
|
|
json_t *json = json_loads("[123] garbage", 0, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json != NULL)
|
2017-10-03 17:42:07 +08:00
|
|
|
fail("json_loads returned not NULL");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (strlen(error.text) >= JSON_ERROR_TEXT_LENGTH)
|
2017-10-03 17:42:07 +08:00
|
|
|
fail("error.text longer than expected");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_error_code(&error) != json_error_end_of_input_expected)
|
2017-10-03 17:42:07 +08:00
|
|
|
fail("json_loads returned incorrect error code");
|
2017-12-21 01:27:04 +08:00
|
|
|
|
|
|
|
json = json_loads("{\"foo\": ", 0, &error);
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json != NULL)
|
2017-12-21 01:27:04 +08:00
|
|
|
fail("json_loads returned not NULL");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (strlen(error.text) >= JSON_ERROR_TEXT_LENGTH)
|
2017-12-21 01:27:04 +08:00
|
|
|
fail("error.text longer than expected");
|
2019-10-17 14:08:51 +08:00
|
|
|
if (json_error_code(&error) != json_error_premature_end_of_input)
|
2017-12-21 01:27:04 +08:00
|
|
|
fail("json_loads returned incorrect error code");
|
2017-10-03 17:42:07 +08:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:08:51 +08:00
|
|
|
static void run_tests() {
|
2011-05-15 18:57:48 +08:00
|
|
|
file_not_found();
|
2014-12-19 14:35:31 +08:00
|
|
|
very_long_file_name();
|
2011-05-15 18:57:48 +08:00
|
|
|
reject_duplicates();
|
2011-05-30 02:19:28 +08:00
|
|
|
disable_eof_check();
|
2011-11-12 02:17:29 +08:00
|
|
|
decode_any();
|
2013-06-11 22:09:08 +08:00
|
|
|
decode_int_as_real();
|
2013-09-30 15:44:35 +08:00
|
|
|
allow_nul();
|
2011-11-12 02:17:50 +08:00
|
|
|
load_wrong_args();
|
2012-01-24 03:18:04 +08:00
|
|
|
position();
|
2017-10-03 17:42:07 +08:00
|
|
|
error_code();
|
2009-10-27 23:46:57 +08:00
|
|
|
}
|