blob: ff0361e81e158118e4489dabcc9e6da331ea2f94 [file] [log] [blame]
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <ztest.h>
#include <json.h>
struct test_nested {
int nested_int;
bool nested_bool;
const char *nested_string;
};
struct test_struct {
const char *some_string;
int some_int;
bool some_bool;
struct test_nested some_nested_struct;
int some_array[16];
size_t some_array_len;
};
#define FIELD(struct_, member_, type_) { \
.field_name = #member_, \
.field_name_len = sizeof(#member_) - 1, \
.offset = offsetof(struct_, member_), \
.type = type_ \
}
static const struct json_obj_descr nested_descr[] = {
FIELD(struct test_nested, nested_int, JSON_TOK_NUMBER),
FIELD(struct test_nested, nested_bool, JSON_TOK_TRUE),
FIELD(struct test_nested, nested_string, JSON_TOK_STRING),
};
static const struct json_obj_descr test_descr[] = {
FIELD(struct test_struct, some_string, JSON_TOK_STRING),
FIELD(struct test_struct, some_int, JSON_TOK_NUMBER),
FIELD(struct test_struct, some_bool, JSON_TOK_TRUE),
JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
nested_descr),
JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
16, some_array_len, JSON_TOK_NUMBER),
};
#undef FIELD
static void test_json_encoding(void)
{
struct test_struct ts = {
.some_string = "zephyr 123",
.some_int = 42,
.some_bool = true,
.some_nested_struct = {
.nested_int = -1234,
.nested_bool = false,
.nested_string = "this should be escaped: \t"
},
.some_array[0] = 1,
.some_array[1] = 4,
.some_array[2] = 8,
.some_array[3] = 16,
.some_array[4] = 32,
.some_array_len = 5
};
char encoded[] = "{\"some_string\":\"zephyr 123\","
"\"some_int\":42,\"some_bool\":true,"
"\"some_nested_struct\":{\"nested_int\":-1234,"
"\"nested_bool\":false,\"nested_string\":"
"\"this should be escaped: \\t\"},"
"\"some_array\":[1,4,8,16,32]}";
char buffer[sizeof(encoded)];
int ret;
ret = json_obj_encode_buf(test_descr, ARRAY_SIZE(test_descr),
&ts, buffer, sizeof(buffer));
assert_equal(ret, 0, "Encoding function returned no errors");
ret = strncmp(buffer, encoded, sizeof(encoded) - 1);
assert_equal(ret, 0, "Encoded contents consistent");
}
static void test_json_decoding(void)
{
struct test_struct ts;
char encoded[] = "{\"some_string\":\"zephyr 123\","
"\"some_int\":\t42\n,"
"\"some_bool\":true \t "
"\n"
"\r ,"
"\"some_nested_struct\":{ "
"\"nested_int\":-1234,\n\n"
"\"nested_bool\":false,\t"
"\"nested_string\":\"this should be escaped: \\t\"},"
"\"some_array\":[11,22, 33,\t45,\n299]"
"}";
const int expected_array[] = { 11, 22, 33, 45, 299 };
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, (1 << ARRAY_SIZE(test_descr)) - 1,
"All fields decoded correctly");
assert_true(!strcmp(ts.some_string, "zephyr 123"),
"String decoded correctly");
assert_equal(ts.some_int, 42, "Positive integer decoded correctly");
assert_equal(ts.some_bool, true, "Boolean decoded correctly");
assert_equal(ts.some_nested_struct.nested_int, -1234,
"Nested negative integer decoded correctly");
assert_equal(ts.some_nested_struct.nested_bool, false,
"Nested boolean value decoded correctly");
assert_true(!strcmp(ts.some_nested_struct.nested_string,
"this should be escaped: \\t"),
"Nested string decoded correctly");
assert_equal(ts.some_array_len, 5, "Array has correct number of items");
assert_true(!memcmp(ts.some_array, expected_array,
sizeof(expected_array)),
"Array decoded with unexpected values");
}
static void test_json_invalid_unicode(void)
{
struct test_struct ts;
char encoded[] = "{\"some_string\":\"\\uABC@\"}";
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, -EINVAL, "Decoding has to fail");
}
static void test_json_missing_quote(void)
{
struct test_struct ts;
char encoded[] = "{\"some_string";
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, -EINVAL, "Decoding has to fail");
}
static void test_json_wrong_token(void)
{
struct test_struct ts;
char encoded[] = "{\"some_string\",}";
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, -EINVAL, "Decoding has to fail");
}
static void test_json_item_wrong_type(void)
{
struct test_struct ts;
char encoded[] = "{\"some_string\":false}";
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, -EINVAL, "Decoding has to fail");
}
static void test_json_key_not_in_descr(void)
{
struct test_struct ts;
char encoded[] = "{\"key_not_in_descr\":123456}";
int ret;
ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
ARRAY_SIZE(test_descr), &ts);
assert_equal(ret, 0, "No items should be decoded");
}
void test_main(void)
{
ztest_test_suite(lib_json_test,
ztest_unit_test(test_json_encoding),
ztest_unit_test(test_json_decoding),
ztest_unit_test(test_json_invalid_unicode),
ztest_unit_test(test_json_missing_quote),
ztest_unit_test(test_json_wrong_token),
ztest_unit_test(test_json_item_wrong_type),
ztest_unit_test(test_json_key_not_in_descr)
);
ztest_run_test_suite(lib_json_test);
}