diff options
Diffstat (limited to 'tests/api/test-serialize.c')
| -rw-r--r-- | tests/api/test-serialize.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/tests/api/test-serialize.c b/tests/api/test-serialize.c new file mode 100644 index 000000000000..ef7bff0fcf95 --- /dev/null +++ b/tests/api/test-serialize.c @@ -0,0 +1,203 @@ +/* + * test-serialize.c + * Tests for spdxtool's JSON serialization value model. + * + * SPDX-License-Identifier: pkgconf + * + * Copyright (c) 2026 pkgconf authors (see AUTHORS). + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include <libpkgconf/stdinc.h> +#include <libpkgconf/libpkgconf.h> +#include "test-api.h" +#include "serialize.h" + +// Render a value to a freshly-allocated C string (caller frees) +static char * +render(spdxtool_serialize_value_t *value) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + TEST_ASSERT_TRUE(spdxtool_serialize_value_to_buf(&buf, value, 0)); + char *s = strdup(pkgconf_buffer_str_or_empty(&buf)); + pkgconf_buffer_finalize(&buf); + return s; +} + +// Render a container without taking ownership of it +static char * +render_object(spdxtool_serialize_object_list_t *o) +{ + spdxtool_serialize_value_t wrap = { .type = SPDXTOOL_SERIALIZE_TYPE_OBJECT, .value = { .o = o } }; + return render(&wrap); +} + +static char * +render_array(spdxtool_serialize_array_t *a) +{ + spdxtool_serialize_value_t wrap = { .type = SPDXTOOL_SERIALIZE_TYPE_ARRAY, .value = { .a = a } }; + return render(&wrap); +} + +// Scalar value types: string / int / bool / null +static void +test_serialize_value_string(void) +{ + spdxtool_serialize_value_t *v = spdxtool_serialize_value_string("hi"); + TEST_ASSERT_NONNULL(v); + char *s = render(v); + TEST_ASSERT_STRCMP_EQ(s, "\"hi\""); + free(s); + spdxtool_serialize_value_free(v); +} + +static void +test_serialize_value_int(void) +{ + spdxtool_serialize_value_t *v = spdxtool_serialize_value_int(123); + TEST_ASSERT_NONNULL(v); + char *s = render(v); + TEST_ASSERT_STRCMP_EQ(s, "123"); + free(s); + spdxtool_serialize_value_free(v); +} + +static void +test_serialize_value_bool(void) +{ + spdxtool_serialize_value_t *t = spdxtool_serialize_value_bool(true); + spdxtool_serialize_value_t *f = spdxtool_serialize_value_bool(false); + char *st = render(t); + char *sf = render(f); + TEST_ASSERT_STRCMP_EQ(st, "true"); + TEST_ASSERT_STRCMP_EQ(sf, "false"); + free(st); + free(sf); + spdxtool_serialize_value_free(t); + spdxtool_serialize_value_free(f); +} + +static void +test_serialize_value_null(void) +{ + spdxtool_serialize_value_t *v = spdxtool_serialize_value_null(); + TEST_ASSERT_NONNULL(v); + char *s = render(v); + TEST_ASSERT_STRCMP_EQ(s, "null"); + free(s); + spdxtool_serialize_value_free(v); +} + +// All JSON string escape sequences, including control characters +static void +test_serialize_escape_sequences(void) +{ + spdxtool_serialize_value_t *v = spdxtool_serialize_value_string("\"\\\b\f\n\r\t\x01" "Z"); + char *s = render(v); + + TEST_ASSERT_STRSTR(s, "\\\""); // quote + TEST_ASSERT_STRSTR(s, "\\\\"); // backslash + TEST_ASSERT_STRSTR(s, "\\b"); // backspace + TEST_ASSERT_STRSTR(s, "\\f"); // form feed + TEST_ASSERT_STRSTR(s, "\\n"); // newline + TEST_ASSERT_STRSTR(s, "\\r"); // carriage return + TEST_ASSERT_STRSTR(s, "\\t"); // tab + TEST_ASSERT_STRSTR(s, "\\u0001"); // other ctrl + TEST_ASSERT_STRSTR(s, "Z"); // printable passthrough + + free(s); + spdxtool_serialize_value_free(v); +} + +// Mixed-type object exercises the int/bool/null add helpers +static void +test_serialize_object_mixed_types(void) +{ + spdxtool_serialize_object_list_t *o = spdxtool_serialize_object_list_new(); + TEST_ASSERT_NONNULL(o); + + TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_string(o, "s", "x")); + TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_int(o, "i", 42)); + TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_bool(o, "b", true)); + TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_null(o, "n")); + + char *s = render_object(o); + TEST_ASSERT_STRSTR(s, "\"s\": \"x\""); + TEST_ASSERT_STRSTR(s, "\"i\": 42"); + TEST_ASSERT_STRSTR(s, "\"b\": true"); + TEST_ASSERT_STRSTR(s, "\"n\": null"); + + free(s); + spdxtool_serialize_object_list_free(o); +} + +// Mixed-type array exercises the int/bool/null array helpers +static void +test_serialize_array_mixed_types(void) +{ + spdxtool_serialize_array_t *a = spdxtool_serialize_array_new(); + TEST_ASSERT_NONNULL(a); + + TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_int(a, 7)); + TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_bool(a, false)); + TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_null(a)); + + char *s = render_array(a); + TEST_ASSERT_STRSTR(s, "7"); + TEST_ASSERT_STRSTR(s, "false"); + TEST_ASSERT_STRSTR(s, "null"); + + free(s); + spdxtool_serialize_array_free(a); +} + +// Defensive NULL handling that the CLI path never reaches +static void +test_serialize_null_guards(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + spdxtool_serialize_value_t *v = spdxtool_serialize_value_null(); + + // value_to_buf rejects NULL buffer or NULL value + TEST_ASSERT_FALSE(spdxtool_serialize_value_to_buf(NULL, v, 0)); + TEST_ASSERT_FALSE(spdxtool_serialize_value_to_buf(&buf, NULL, 0)); + pkgconf_buffer_finalize(&buf); + + // value_string(NULL) yields NULL + TEST_ASSERT_NULL(spdxtool_serialize_value_string(NULL)); + + // add_take with a NULL container frees the value and returns NULL + TEST_ASSERT_NULL(spdxtool_serialize_object_add_take(NULL, "k", v)); + TEST_ASSERT_NULL(spdxtool_serialize_array_add_take(NULL, spdxtool_serialize_value_null())); + + // free routines are NULL-safe + spdxtool_serialize_value_free(NULL); + spdxtool_serialize_object_free(NULL); + spdxtool_serialize_object_list_free(NULL); + spdxtool_serialize_array_free(NULL); +} + +int +main(int argc, const char **argv) +{ + (void) argc; + const char *basename = pkgconf_path_find_basename(argv[0]); + + TEST_RUN(basename, test_serialize_value_string); + TEST_RUN(basename, test_serialize_value_int); + TEST_RUN(basename, test_serialize_value_bool); + TEST_RUN(basename, test_serialize_value_null); + TEST_RUN(basename, test_serialize_escape_sequences); + TEST_RUN(basename, test_serialize_object_mixed_types); + TEST_RUN(basename, test_serialize_array_mixed_types); + TEST_RUN(basename, test_serialize_null_guards); + + return EXIT_SUCCESS; +} |
