Spdk/test/unit/lib/json/json_util.c/json_util_ut.c
Jim Harris 488570ebd4 Replace most BSD 3-clause license text with SPDX identifier.
Many open source projects have moved to using SPDX identifiers
to specify license information, reducing the amount of
boilerplate code in every source file.  This patch replaces
the bulk of SPDK .c, .cpp and Makefiles with the BSD-3-Clause
identifier.

Almost all of these files share the exact same license text,
and this patch only modifies the files that contain the
most common license text.  There can be slight variations
because the third clause contains company names - most say
"Intel Corporation", but there are instances for Nvidia,
Samsung, Eideticom and even "the copyright holder".

Used a bash script to automate replacement of the license text
with SPDX identifier which is checked into scripts/spdx.sh.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: Iaa88ab5e92ea471691dc298cfe41ebfb5d169780
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12904
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Dong Yi <dongx.yi@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: <qun.wan@intel.com>
2022-06-09 07:35:12 +00:00

959 lines
24 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk_cunit.h"
#include "json/json_util.c"
/* For spdk_json_parse() */
#include "json/json_parse.c"
#define NUM_SETUP(x) \
snprintf(buf, sizeof(buf), "%s", x); \
v.type = SPDK_JSON_VAL_NUMBER; \
v.start = buf; \
v.len = sizeof(x) - 1
#define NUM_UINT16_PASS(s, i) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_uint16(&v, &u16) == 0); \
CU_ASSERT(u16 == i)
#define NUM_UINT16_FAIL(s) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_uint16(&v, &u16) != 0)
#define NUM_INT32_PASS(s, i) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_int32(&v, &i32) == 0); \
CU_ASSERT(i32 == i)
#define NUM_INT32_FAIL(s) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_int32(&v, &i32) != 0)
#define NUM_UINT64_PASS(s, i) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_uint64(&v, &u64) == 0); \
CU_ASSERT(u64 == i)
#define NUM_UINT64_FAIL(s) \
NUM_SETUP(s); \
CU_ASSERT(spdk_json_number_to_uint64(&v, &u64) != 0)
static void
test_strequal(void)
{
struct spdk_json_val v;
v.type = SPDK_JSON_VAL_STRING;
v.start = "test";
v.len = sizeof("test") - 1;
CU_ASSERT(spdk_json_strequal(&v, "test") == true);
CU_ASSERT(spdk_json_strequal(&v, "TEST") == false);
CU_ASSERT(spdk_json_strequal(&v, "hello") == false);
CU_ASSERT(spdk_json_strequal(&v, "t") == false);
v.type = SPDK_JSON_VAL_NAME;
CU_ASSERT(spdk_json_strequal(&v, "test") == true);
v.type = SPDK_JSON_VAL_NUMBER;
CU_ASSERT(spdk_json_strequal(&v, "test") == false);
v.type = SPDK_JSON_VAL_STRING;
v.start = "test\0hello";
v.len = sizeof("test\0hello") - 1;
CU_ASSERT(spdk_json_strequal(&v, "test") == false);
}
static void
test_num_to_uint16(void)
{
struct spdk_json_val v;
char buf[100];
uint16_t u16 = 0;
NUM_SETUP("1234");
CU_ASSERT(spdk_json_number_to_uint16(&v, &u16) == 0);
CU_ASSERT(u16 == 1234);
NUM_UINT16_PASS("0", 0);
NUM_UINT16_PASS("1234", 1234);
NUM_UINT16_PASS("1234.00000", 1234);
NUM_UINT16_PASS("1.2e1", 12);
NUM_UINT16_PASS("12340e-1", 1234);
NUM_UINT16_FAIL("1.2");
NUM_UINT16_FAIL("-1234");
NUM_UINT16_FAIL("1.2E0");
NUM_UINT16_FAIL("1.234e1");
NUM_UINT16_FAIL("12341e-1");
}
static void
test_num_to_int32(void)
{
struct spdk_json_val v;
char buf[100];
int32_t i32 = 0;
NUM_SETUP("1234");
CU_ASSERT(spdk_json_number_to_int32(&v, &i32) == 0);
CU_ASSERT(i32 == 1234);
NUM_INT32_PASS("0", 0);
NUM_INT32_PASS("1234", 1234);
NUM_INT32_PASS("-1234", -1234);
NUM_INT32_PASS("1234.00000", 1234);
NUM_INT32_PASS("1.2e1", 12);
NUM_INT32_PASS("12340e-1", 1234);
NUM_INT32_PASS("-0", 0);
NUM_INT32_FAIL("1.2");
NUM_INT32_FAIL("1.2E0");
NUM_INT32_FAIL("1.234e1");
NUM_INT32_FAIL("12341e-1");
}
static void
test_num_to_uint64(void)
{
struct spdk_json_val v;
char buf[100];
uint64_t u64 = 0;
NUM_SETUP("1234");
CU_ASSERT(spdk_json_number_to_uint64(&v, &u64) == 0);
CU_ASSERT(u64 == 1234);
NUM_UINT64_PASS("0", 0);
NUM_UINT64_PASS("1234", 1234);
NUM_UINT64_PASS("1234.00000", 1234);
NUM_UINT64_PASS("1.2e1", 12);
NUM_UINT64_PASS("12340e-1", 1234);
NUM_UINT64_PASS("123456780e-1", 12345678);
NUM_UINT64_FAIL("1.2");
NUM_UINT64_FAIL("-1234");
NUM_UINT64_FAIL("1.2E0");
NUM_UINT64_FAIL("1.234e1");
NUM_UINT64_FAIL("12341e-1");
NUM_UINT64_FAIL("123456781e-1");
}
static void
test_decode_object(void)
{
struct my_object {
char *my_name;
uint32_t my_int;
bool my_bool;
};
struct spdk_json_val object[] = {
{"", 6, SPDK_JSON_VAL_OBJECT_BEGIN},
{"first", 5, SPDK_JSON_VAL_NAME},
{"HELLO", 5, SPDK_JSON_VAL_STRING},
{"second", 6, SPDK_JSON_VAL_NAME},
{"234", 3, SPDK_JSON_VAL_NUMBER},
{"third", 5, SPDK_JSON_VAL_NAME},
{"", 1, SPDK_JSON_VAL_TRUE},
{"", 0, SPDK_JSON_VAL_OBJECT_END},
};
struct spdk_json_object_decoder decoders[] = {
{"first", offsetof(struct my_object, my_name), spdk_json_decode_string, false},
{"second", offsetof(struct my_object, my_int), spdk_json_decode_uint32, false},
{"third", offsetof(struct my_object, my_bool), spdk_json_decode_bool, false},
{"fourth", offsetof(struct my_object, my_bool), spdk_json_decode_bool, true},
};
struct my_object output = {
.my_name = NULL,
.my_int = 0,
.my_bool = false,
};
uint32_t answer = 234;
char *answer_str = "HELLO";
bool answer_bool = true;
/* Passing Test: object containing simple types */
CU_ASSERT(spdk_json_decode_object(object, decoders, 4, &output) == 0);
SPDK_CU_ASSERT_FATAL(output.my_name != NULL);
CU_ASSERT(memcmp(output.my_name, answer_str, 6) == 0);
CU_ASSERT(output.my_int == answer);
CU_ASSERT(output.my_bool == answer_bool);
/* Failing Test: member with no matching decoder */
/* i.e. I remove the matching decoder from the boolean argument */
CU_ASSERT(spdk_json_decode_object(object, decoders, 2, &output) != 0);
/* Failing Test: non-optional decoder with no corresponding member */
decoders[3].optional = false;
CU_ASSERT(spdk_json_decode_object(object, decoders, 4, &output) != 0);
/* return to base state */
decoders[3].optional = true;
/* Failing Test: duplicated names for json values */
object[3].start = "first";
object[3].len = 5;
CU_ASSERT(spdk_json_decode_object(object, decoders, 3, &output) != 0);
/* return to base state */
object[3].start = "second";
object[3].len = 6;
/* Failing Test: invalid value for decoder */
object[2].start = "HELO";
CU_ASSERT(spdk_json_decode_object(object, decoders, 3, &output) != 0);
/* return to base state */
object[2].start = "HELLO";
/* Failing Test: not an object */
object[0].type = SPDK_JSON_VAL_ARRAY_BEGIN;
CU_ASSERT(spdk_json_decode_object(object, decoders, 3, &output) != 0);
free(output.my_name);
}
static void
test_free_object(void)
{
struct my_object {
char *my_name;
uint32_t my_int;
char *my_other_name;
char *empty_string;
};
struct spdk_json_object_decoder decoders[] = {
{"first", offsetof(struct my_object, my_name), spdk_json_decode_string, false},
{"second", offsetof(struct my_object, my_int), spdk_json_decode_uint32, false},
{"third", offsetof(struct my_object, my_other_name), spdk_json_decode_string, true},
{"fourth", offsetof(struct my_object, empty_string), spdk_json_decode_string, false},
};
struct my_object output = {
.my_name = strdup("hello"),
.my_int = 3,
.my_other_name = strdup("world"),
.empty_string = NULL
};
SPDK_CU_ASSERT_FATAL(output.my_name != NULL);
SPDK_CU_ASSERT_FATAL(output.my_other_name != NULL);
spdk_json_free_object(decoders, 4, &output);
CU_ASSERT(output.my_name == NULL);
CU_ASSERT(output.my_other_name == NULL);
CU_ASSERT(output.empty_string == NULL);
}
static void
test_decode_array(void)
{
struct spdk_json_val values[4];
uint32_t my_int[2] = {0, 0};
char *my_string[2] = {NULL, NULL};
size_t out_size;
/* passing integer test */
values[0].type = SPDK_JSON_VAL_ARRAY_BEGIN;
values[0].len = 2;
values[1].type = SPDK_JSON_VAL_NUMBER;
values[1].len = 4;
values[1].start = "1234";
values[2].type = SPDK_JSON_VAL_NUMBER;
values[2].len = 4;
values[2].start = "5678";
values[3].type = SPDK_JSON_VAL_ARRAY_END;
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_uint32, my_int, 2, &out_size,
sizeof(uint32_t)) == 0);
CU_ASSERT(my_int[0] == 1234);
CU_ASSERT(my_int[1] == 5678);
CU_ASSERT(out_size == 2);
/* array length exceeds max */
values[0].len = 3;
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_uint32, my_int, 2, &out_size,
sizeof(uint32_t)) != 0);
/* mixed types */
values[0].len = 2;
values[2].type = SPDK_JSON_VAL_STRING;
values[2].len = 5;
values[2].start = "HELLO";
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_uint32, my_int, 2, &out_size,
sizeof(uint32_t)) != 0);
/* no array start */
values[0].type = SPDK_JSON_VAL_NUMBER;
values[2].type = SPDK_JSON_VAL_NUMBER;
values[2].len = 4;
values[2].start = "5678";
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_uint32, my_int, 2, &out_size,
sizeof(uint32_t)) != 0);
/* mismatched array type and parser */
values[0].type = SPDK_JSON_VAL_ARRAY_BEGIN;
values[1].type = SPDK_JSON_VAL_STRING;
values[1].len = 5;
values[1].start = "HELLO";
values[2].type = SPDK_JSON_VAL_STRING;
values[2].len = 5;
values[2].start = "WORLD";
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_uint32, my_int, 2, &out_size,
sizeof(uint32_t)) != 0);
/* passing String example */
CU_ASSERT(spdk_json_decode_array(values, spdk_json_decode_string, my_string, 2, &out_size,
sizeof(char *)) == 0);
SPDK_CU_ASSERT_FATAL(my_string[0] != NULL);
SPDK_CU_ASSERT_FATAL(my_string[1] != NULL);
CU_ASSERT(memcmp(my_string[0], "HELLO", 6) == 0);
CU_ASSERT(memcmp(my_string[1], "WORLD", 6) == 0);
CU_ASSERT(out_size == 2);
free(my_string[0]);
free(my_string[1]);
}
static void
test_decode_bool(void)
{
struct spdk_json_val v;
bool b;
/* valid bool (true) */
v.type = SPDK_JSON_VAL_TRUE;
b = false;
CU_ASSERT(spdk_json_decode_bool(&v, &b) == 0);
CU_ASSERT(b == true);
/* valid bool (false) */
v.type = SPDK_JSON_VAL_FALSE;
b = true;
CU_ASSERT(spdk_json_decode_bool(&v, &b) == 0);
CU_ASSERT(b == false);
/* incorrect type */
v.type = SPDK_JSON_VAL_NULL;
CU_ASSERT(spdk_json_decode_bool(&v, &b) != 0);
}
static void
test_decode_int32(void)
{
struct spdk_json_val v;
int32_t i;
/* correct type and valid value */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "33";
v.len = 2;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == 33);
/* correct type and invalid value (float) */
v.start = "32.45";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* incorrect type */
v.type = SPDK_JSON_VAL_STRING;
v.start = "String";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* incorrect type */
v.type = SPDK_JSON_VAL_TRUE;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* edge case (integer max) */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "2147483647";
v.len = 10;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == 2147483647);
/* invalid value (overflow) */
v.start = "2147483648";
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* edge case (integer min) */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "-2147483648";
v.len = 11;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == -2147483648);
/* invalid value (overflow) */
v.start = "-2147483649";
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* valid exponent */
v.start = "4e3";
v.len = 3;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == 4000);
/* invalid negative exponent */
v.start = "-400e-4";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* invalid negative exponent */
v.start = "400e-4";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* valid negative exponent */
v.start = "-400e-2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == -4);
/* invalid exponent (overflow) */
v.start = "-2e32";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
/* valid exponent with decimal */
v.start = "2.13e2";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) == 0);
CU_ASSERT(i == 213);
/* invalid exponent with decimal */
v.start = "2.134e2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_int32(&v, &i) != 0);
}
static void
test_decode_uint16(void)
{
struct spdk_json_val v;
uint32_t i;
/* incorrect type */
v.type = SPDK_JSON_VAL_STRING;
v.start = "Strin";
v.len = 5;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* invalid value (float) */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "123.4";
v.len = 5;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* edge case (0) */
v.start = "0";
v.len = 1;
i = 456;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) == 0);
CU_ASSERT(i == 0);
/* invalid value (negative) */
v.start = "-1";
v.len = 2;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* edge case (maximum) */
v.start = "65535";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) == 0);
CU_ASSERT(i == 65535);
/* invalid value (overflow) */
v.start = "65536";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* valid exponent */
v.start = "66E2";
v.len = 4;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) == 0);
CU_ASSERT(i == 6600);
/* invalid exponent (overflow) */
v.start = "66E3";
v.len = 4;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* invalid exponent (decimal) */
v.start = "65.535E2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* valid exponent with decimal */
v.start = "65.53E2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) == 0);
CU_ASSERT(i == 6553);
/* invalid negative exponent */
v.start = "40e-2";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* invalid negative exponent */
v.start = "-40e-1";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) != 0);
/* valid negative exponent */
v.start = "40e-1";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint16(&v, &i) == 0);
CU_ASSERT(i == 4);
}
static void
test_decode_uint32(void)
{
struct spdk_json_val v;
uint32_t i;
/* incorrect type */
v.type = SPDK_JSON_VAL_STRING;
v.start = "String";
v.len = 6;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* invalid value (float) */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "123.45";
v.len = 6;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* edge case (0) */
v.start = "0";
v.len = 1;
i = 456;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 0);
/* invalid value (negative) */
v.start = "-1";
v.len = 2;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* edge case (maximum) */
v.start = "4294967295";
v.len = 10;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 4294967295);
/* invalid value (overflow) */
v.start = "4294967296";
v.len = 10;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* valid exponent */
v.start = "42E2";
v.len = 4;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 4200);
/* invalid exponent (overflow) */
v.start = "42e32";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* invalid exponent (decimal) */
v.start = "42.323E2";
v.len = 8;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* valid exponent with decimal */
v.start = "42.32E2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 4232);
/* invalid negative exponent */
v.start = "400e-4";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* invalid negative exponent */
v.start = "-400e-2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) != 0);
/* valid negative exponent */
v.start = "400e-2";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 4);
/* valid negative exponent */
v.start = "10e-1";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint32(&v, &i) == 0);
CU_ASSERT(i == 1);
}
static void
test_decode_uint64(void)
{
struct spdk_json_val v;
uint64_t i;
/* incorrect type */
v.type = SPDK_JSON_VAL_STRING;
v.start = "String";
v.len = 6;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* invalid value (float) */
v.type = SPDK_JSON_VAL_NUMBER;
v.start = "123.45";
v.len = 6;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* edge case (0) */
v.start = "0";
v.len = 1;
i = 456;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) == 0);
CU_ASSERT(i == 0);
/* invalid value (negative) */
v.start = "-1";
v.len = 2;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* edge case (maximum) */
v.start = "18446744073709551615";
v.len = 20;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) == 0);
CU_ASSERT(i == 18446744073709551615U);
/* invalid value (overflow) */
v.start = "18446744073709551616";
v.len = 20;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* valid exponent */
v.start = "42E2";
v.len = 4;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) == 0);
CU_ASSERT(i == 4200);
/* invalid exponent (overflow) */
v.start = "42e64";
v.len = 5;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* invalid exponent (decimal) */
v.start = "42.323E2";
v.len = 8;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* valid exponent with decimal */
v.start = "42.32E2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) == 0);
CU_ASSERT(i == 4232);
/* invalid negative exponent */
v.start = "400e-4";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* invalid negative exponent */
v.start = "-400e-2";
v.len = 7;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) != 0);
/* valid negative exponent */
v.start = "400e-2";
v.len = 6;
i = 0;
CU_ASSERT(spdk_json_decode_uint64(&v, &i) == 0);
CU_ASSERT(i == 4);
}
static void
test_decode_string(void)
{
struct spdk_json_val v;
char *value = NULL;
/* Passing Test: Standard */
v.type = SPDK_JSON_VAL_STRING;
v.start = "HELLO";
v.len = 5;
CU_ASSERT(spdk_json_decode_string(&v, &value) == 0);
SPDK_CU_ASSERT_FATAL(value != NULL);
CU_ASSERT(memcmp(value, v.start, 6) == 0);
/* Edge Test: Empty String */
v.start = "";
v.len = 0;
CU_ASSERT(spdk_json_decode_string(&v, &value) == 0);
SPDK_CU_ASSERT_FATAL(value != NULL);
CU_ASSERT(memcmp(value, v.start, 1) == 0);
/*
* Failing Test: Null Terminator In String
* It is valid for a json string to contain \u0000 and the parser will accept it.
* However, a null terminated C string cannot contain '\0' and should be rejected
* if that character is found before the end of the string.
*/
v.start = "HELO";
v.len = 5;
CU_ASSERT(spdk_json_decode_string(&v, &value) != 0);
/* Failing Test: Wrong Type */
v.start = "45673";
v.type = SPDK_JSON_VAL_NUMBER;
CU_ASSERT(spdk_json_decode_string(&v, &value) != 0);
/* Passing Test: Special Characters */
v.type = SPDK_JSON_VAL_STRING;
v.start = "HE\bLL\tO\\WORLD";
v.len = 13;
CU_ASSERT(spdk_json_decode_string(&v, &value) == 0);
SPDK_CU_ASSERT_FATAL(value != NULL);
CU_ASSERT(memcmp(value, v.start, 14) == 0);
free(value);
}
char ut_json_text[] =
"{"
" \"string\": \"Some string data\","
" \"object\": { "
" \"another_string\": \"Yet another string data\","
" \"array name with space\": [1, [], {} ]"
" },"
" \"array\": [ \"Text\", 2, {} ]"
"}"
;
static void
test_find(void)
{
struct spdk_json_val *values, *key, *val, *key2, *val2;
ssize_t values_cnt;
ssize_t rc;
values_cnt = spdk_json_parse(ut_json_text, strlen(ut_json_text), NULL, 0, NULL, 0);
SPDK_CU_ASSERT_FATAL(values_cnt > 0);
values = calloc(values_cnt, sizeof(struct spdk_json_val));
SPDK_CU_ASSERT_FATAL(values != NULL);
rc = spdk_json_parse(ut_json_text, strlen(ut_json_text), values, values_cnt, NULL, 0);
SPDK_CU_ASSERT_FATAL(values_cnt == rc);
key = val = NULL;
rc = spdk_json_find(values, "string", &key, &val, SPDK_JSON_VAL_STRING);
CU_ASSERT(rc == 0);
CU_ASSERT(key != NULL && spdk_json_strequal(key, "string") == true);
CU_ASSERT(val != NULL && spdk_json_strequal(val, "Some string data") == true);
key = val = NULL;
rc = spdk_json_find(values, "object", &key, &val, SPDK_JSON_VAL_OBJECT_BEGIN);
CU_ASSERT(rc == 0);
CU_ASSERT(key != NULL && spdk_json_strequal(key, "object") == true);
/* Find key in "object" by passing SPDK_JSON_VAL_ANY to match any type */
key2 = val2 = NULL;
rc = spdk_json_find(val, "array name with space", &key2, &val2, SPDK_JSON_VAL_ANY);
CU_ASSERT(rc == 0);
CU_ASSERT(key2 != NULL && spdk_json_strequal(key2, "array name with space") == true);
CU_ASSERT(val2 != NULL && val2->type == SPDK_JSON_VAL_ARRAY_BEGIN);
/* Find the "array" key in "object" by passing SPDK_JSON_VAL_ARRAY_BEGIN to match only array */
key2 = val2 = NULL;
rc = spdk_json_find(val, "array name with space", &key2, &val2, SPDK_JSON_VAL_ARRAY_BEGIN);
CU_ASSERT(rc == 0);
CU_ASSERT(key2 != NULL && spdk_json_strequal(key2, "array name with space") == true);
CU_ASSERT(val2 != NULL && val2->type == SPDK_JSON_VAL_ARRAY_BEGIN);
/* Negative test - key doesn't exist */
key2 = val2 = NULL;
rc = spdk_json_find(val, "this_key_does_not_exist", &key2, &val2, SPDK_JSON_VAL_ANY);
CU_ASSERT(rc == -ENOENT);
/* Negative test - key type doesn't match */
key2 = val2 = NULL;
rc = spdk_json_find(val, "another_string", &key2, &val2, SPDK_JSON_VAL_ARRAY_BEGIN);
CU_ASSERT(rc == -EDOM);
free(values);
}
static void
test_iterating(void)
{
struct spdk_json_val *values;
struct spdk_json_val *string_key;
struct spdk_json_val *object_key, *object_val;
struct spdk_json_val *array_key, *array_val;
struct spdk_json_val *another_string_key;
struct spdk_json_val *array_name_with_space_key, *array_name_with_space_val;
struct spdk_json_val *it;
ssize_t values_cnt;
ssize_t rc;
values_cnt = spdk_json_parse(ut_json_text, strlen(ut_json_text), NULL, 0, NULL, 0);
SPDK_CU_ASSERT_FATAL(values_cnt > 0);
values = calloc(values_cnt, sizeof(struct spdk_json_val));
SPDK_CU_ASSERT_FATAL(values != NULL);
rc = spdk_json_parse(ut_json_text, strlen(ut_json_text), values, values_cnt, NULL, 0);
SPDK_CU_ASSERT_FATAL(values_cnt == rc);
/* Iterate over object keys. JSON spec doesn't guarantee order of keys in object but
* SPDK implementation implicitly does.
*/
string_key = spdk_json_object_first(values);
CU_ASSERT(spdk_json_strequal(string_key, "string") == true);
object_key = spdk_json_next(string_key);
object_val = json_value(object_key);
CU_ASSERT(spdk_json_strequal(object_key, "object") == true);
array_key = spdk_json_next(object_key);
array_val = json_value(array_key);
CU_ASSERT(spdk_json_strequal(array_key, "array") == true);
/* NULL '}' */
CU_ASSERT(spdk_json_next(array_key) == NULL);
/* Iterate over subobjects */
another_string_key = spdk_json_object_first(object_val);
CU_ASSERT(spdk_json_strequal(another_string_key, "another_string") == true);
array_name_with_space_key = spdk_json_next(another_string_key);
array_name_with_space_val = json_value(array_name_with_space_key);
CU_ASSERT(spdk_json_strequal(array_name_with_space_key, "array name with space") == true);
CU_ASSERT(spdk_json_next(array_name_with_space_key) == NULL);
/* Iterate over array in subobject */
it = spdk_json_array_first(array_name_with_space_val);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_NUMBER);
it = spdk_json_next(it);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_ARRAY_BEGIN);
it = spdk_json_next(it);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_OBJECT_BEGIN);
it = spdk_json_next(it);
CU_ASSERT(it == NULL);
/* Iterate over array in root object */
it = spdk_json_array_first(array_val);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_STRING);
it = spdk_json_next(it);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_NUMBER);
it = spdk_json_next(it);
SPDK_CU_ASSERT_FATAL(it != NULL);
CU_ASSERT(it->type == SPDK_JSON_VAL_OBJECT_BEGIN);
/* Array end */
it = spdk_json_next(it);
CU_ASSERT(it == NULL);
free(values);
}
int main(int argc, char **argv)
{
CU_pSuite suite = NULL;
unsigned int num_failures;
CU_set_error_action(CUEA_ABORT);
CU_initialize_registry();
suite = CU_add_suite("json", NULL, NULL);
CU_ADD_TEST(suite, test_strequal);
CU_ADD_TEST(suite, test_num_to_uint16);
CU_ADD_TEST(suite, test_num_to_int32);
CU_ADD_TEST(suite, test_num_to_uint64);
CU_ADD_TEST(suite, test_decode_object);
CU_ADD_TEST(suite, test_decode_array);
CU_ADD_TEST(suite, test_decode_bool);
CU_ADD_TEST(suite, test_decode_uint16);
CU_ADD_TEST(suite, test_decode_int32);
CU_ADD_TEST(suite, test_decode_uint32);
CU_ADD_TEST(suite, test_decode_uint64);
CU_ADD_TEST(suite, test_decode_string);
CU_ADD_TEST(suite, test_find);
CU_ADD_TEST(suite, test_iterating);
CU_ADD_TEST(suite, test_free_object);
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
num_failures = CU_get_number_of_failures();
CU_cleanup_registry();
return num_failures;
}