xref: /freebsd/contrib/pkgconf/tests/api/test-serialize.c (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
1*592efe25SPierre Pronchery /*
2*592efe25SPierre Pronchery  * test-serialize.c
3*592efe25SPierre Pronchery  * Tests for spdxtool's JSON serialization value model.
4*592efe25SPierre Pronchery  *
5*592efe25SPierre Pronchery  * SPDX-License-Identifier: pkgconf
6*592efe25SPierre Pronchery  *
7*592efe25SPierre Pronchery  * Copyright (c) 2026 pkgconf authors (see AUTHORS).
8*592efe25SPierre Pronchery  *
9*592efe25SPierre Pronchery  * Permission to use, copy, modify, and/or distribute this software for any
10*592efe25SPierre Pronchery  * purpose with or without fee is hereby granted, provided that the above
11*592efe25SPierre Pronchery  * copyright notice and this permission notice appear in all copies.
12*592efe25SPierre Pronchery  *
13*592efe25SPierre Pronchery  * This software is provided 'as is' and without any warranty, express or
14*592efe25SPierre Pronchery  * implied.  In no event shall the authors be liable for any damages arising
15*592efe25SPierre Pronchery  * from the use of this software.
16*592efe25SPierre Pronchery  */
17*592efe25SPierre Pronchery 
18*592efe25SPierre Pronchery #include <libpkgconf/stdinc.h>
19*592efe25SPierre Pronchery #include <libpkgconf/libpkgconf.h>
20*592efe25SPierre Pronchery #include "test-api.h"
21*592efe25SPierre Pronchery #include "serialize.h"
22*592efe25SPierre Pronchery 
23*592efe25SPierre Pronchery // Render a value to a freshly-allocated C string (caller frees)
24*592efe25SPierre Pronchery static char *
render(spdxtool_serialize_value_t * value)25*592efe25SPierre Pronchery render(spdxtool_serialize_value_t *value)
26*592efe25SPierre Pronchery {
27*592efe25SPierre Pronchery 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
28*592efe25SPierre Pronchery 	TEST_ASSERT_TRUE(spdxtool_serialize_value_to_buf(&buf, value, 0));
29*592efe25SPierre Pronchery 	char *s = strdup(pkgconf_buffer_str_or_empty(&buf));
30*592efe25SPierre Pronchery 	pkgconf_buffer_finalize(&buf);
31*592efe25SPierre Pronchery 	return s;
32*592efe25SPierre Pronchery }
33*592efe25SPierre Pronchery 
34*592efe25SPierre Pronchery // Render a container without taking ownership of it
35*592efe25SPierre Pronchery static char *
render_object(spdxtool_serialize_object_list_t * o)36*592efe25SPierre Pronchery render_object(spdxtool_serialize_object_list_t *o)
37*592efe25SPierre Pronchery {
38*592efe25SPierre Pronchery 	spdxtool_serialize_value_t wrap = { .type = SPDXTOOL_SERIALIZE_TYPE_OBJECT, .value = { .o = o } };
39*592efe25SPierre Pronchery 	return render(&wrap);
40*592efe25SPierre Pronchery }
41*592efe25SPierre Pronchery 
42*592efe25SPierre Pronchery static char *
render_array(spdxtool_serialize_array_t * a)43*592efe25SPierre Pronchery render_array(spdxtool_serialize_array_t *a)
44*592efe25SPierre Pronchery {
45*592efe25SPierre Pronchery 	spdxtool_serialize_value_t wrap = { .type = SPDXTOOL_SERIALIZE_TYPE_ARRAY, .value = { .a = a } };
46*592efe25SPierre Pronchery 	return render(&wrap);
47*592efe25SPierre Pronchery }
48*592efe25SPierre Pronchery 
49*592efe25SPierre Pronchery // Scalar value types: string / int / bool / null
50*592efe25SPierre Pronchery static void
test_serialize_value_string(void)51*592efe25SPierre Pronchery test_serialize_value_string(void)
52*592efe25SPierre Pronchery {
53*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *v = spdxtool_serialize_value_string("hi");
54*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(v);
55*592efe25SPierre Pronchery 	char *s = render(v);
56*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(s, "\"hi\"");
57*592efe25SPierre Pronchery 	free(s);
58*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(v);
59*592efe25SPierre Pronchery }
60*592efe25SPierre Pronchery 
61*592efe25SPierre Pronchery static void
test_serialize_value_int(void)62*592efe25SPierre Pronchery test_serialize_value_int(void)
63*592efe25SPierre Pronchery {
64*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *v = spdxtool_serialize_value_int(123);
65*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(v);
66*592efe25SPierre Pronchery 	char *s = render(v);
67*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(s, "123");
68*592efe25SPierre Pronchery 	free(s);
69*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(v);
70*592efe25SPierre Pronchery }
71*592efe25SPierre Pronchery 
72*592efe25SPierre Pronchery static void
test_serialize_value_bool(void)73*592efe25SPierre Pronchery test_serialize_value_bool(void)
74*592efe25SPierre Pronchery {
75*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *t = spdxtool_serialize_value_bool(true);
76*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *f = spdxtool_serialize_value_bool(false);
77*592efe25SPierre Pronchery 	char *st = render(t);
78*592efe25SPierre Pronchery 	char *sf = render(f);
79*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(st, "true");
80*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(sf, "false");
81*592efe25SPierre Pronchery 	free(st);
82*592efe25SPierre Pronchery 	free(sf);
83*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(t);
84*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(f);
85*592efe25SPierre Pronchery }
86*592efe25SPierre Pronchery 
87*592efe25SPierre Pronchery static void
test_serialize_value_null(void)88*592efe25SPierre Pronchery test_serialize_value_null(void)
89*592efe25SPierre Pronchery {
90*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *v = spdxtool_serialize_value_null();
91*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(v);
92*592efe25SPierre Pronchery 	char *s = render(v);
93*592efe25SPierre Pronchery 	TEST_ASSERT_STRCMP_EQ(s, "null");
94*592efe25SPierre Pronchery 	free(s);
95*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(v);
96*592efe25SPierre Pronchery }
97*592efe25SPierre Pronchery 
98*592efe25SPierre Pronchery // All JSON string escape sequences, including control characters
99*592efe25SPierre Pronchery static void
test_serialize_escape_sequences(void)100*592efe25SPierre Pronchery test_serialize_escape_sequences(void)
101*592efe25SPierre Pronchery {
102*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *v = spdxtool_serialize_value_string("\"\\\b\f\n\r\t\x01" "Z");
103*592efe25SPierre Pronchery 	char *s = render(v);
104*592efe25SPierre Pronchery 
105*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\\"");     // quote
106*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\\\");     // backslash
107*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\b");      // backspace
108*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\f");      // form feed
109*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\n");      // newline
110*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\r");      // carriage return
111*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\t");      // tab
112*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\\u0001");  // other ctrl
113*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "Z");        // printable passthrough
114*592efe25SPierre Pronchery 
115*592efe25SPierre Pronchery 	free(s);
116*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(v);
117*592efe25SPierre Pronchery }
118*592efe25SPierre Pronchery 
119*592efe25SPierre Pronchery // Mixed-type object exercises the int/bool/null add helpers
120*592efe25SPierre Pronchery static void
test_serialize_object_mixed_types(void)121*592efe25SPierre Pronchery test_serialize_object_mixed_types(void)
122*592efe25SPierre Pronchery {
123*592efe25SPierre Pronchery 	spdxtool_serialize_object_list_t *o = spdxtool_serialize_object_list_new();
124*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(o);
125*592efe25SPierre Pronchery 
126*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_string(o, "s", "x"));
127*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_int(o, "i", 42));
128*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_bool(o, "b", true));
129*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_object_add_null(o, "n"));
130*592efe25SPierre Pronchery 
131*592efe25SPierre Pronchery 	char *s = render_object(o);
132*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\"s\": \"x\"");
133*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\"i\": 42");
134*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\"b\": true");
135*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "\"n\": null");
136*592efe25SPierre Pronchery 
137*592efe25SPierre Pronchery 	free(s);
138*592efe25SPierre Pronchery 	spdxtool_serialize_object_list_free(o);
139*592efe25SPierre Pronchery }
140*592efe25SPierre Pronchery 
141*592efe25SPierre Pronchery // Mixed-type array exercises the int/bool/null array helpers
142*592efe25SPierre Pronchery static void
test_serialize_array_mixed_types(void)143*592efe25SPierre Pronchery test_serialize_array_mixed_types(void)
144*592efe25SPierre Pronchery {
145*592efe25SPierre Pronchery 	spdxtool_serialize_array_t *a = spdxtool_serialize_array_new();
146*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(a);
147*592efe25SPierre Pronchery 
148*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_int(a, 7));
149*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_bool(a, false));
150*592efe25SPierre Pronchery 	TEST_ASSERT_NONNULL(spdxtool_serialize_array_add_null(a));
151*592efe25SPierre Pronchery 
152*592efe25SPierre Pronchery 	char *s = render_array(a);
153*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "7");
154*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "false");
155*592efe25SPierre Pronchery 	TEST_ASSERT_STRSTR(s, "null");
156*592efe25SPierre Pronchery 
157*592efe25SPierre Pronchery 	free(s);
158*592efe25SPierre Pronchery 	spdxtool_serialize_array_free(a);
159*592efe25SPierre Pronchery }
160*592efe25SPierre Pronchery 
161*592efe25SPierre Pronchery // Defensive NULL handling that the CLI path never reaches
162*592efe25SPierre Pronchery static void
test_serialize_null_guards(void)163*592efe25SPierre Pronchery test_serialize_null_guards(void)
164*592efe25SPierre Pronchery {
165*592efe25SPierre Pronchery 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
166*592efe25SPierre Pronchery 	spdxtool_serialize_value_t *v = spdxtool_serialize_value_null();
167*592efe25SPierre Pronchery 
168*592efe25SPierre Pronchery 	// value_to_buf rejects NULL buffer or NULL value
169*592efe25SPierre Pronchery 	TEST_ASSERT_FALSE(spdxtool_serialize_value_to_buf(NULL, v, 0));
170*592efe25SPierre Pronchery 	TEST_ASSERT_FALSE(spdxtool_serialize_value_to_buf(&buf, NULL, 0));
171*592efe25SPierre Pronchery 	pkgconf_buffer_finalize(&buf);
172*592efe25SPierre Pronchery 
173*592efe25SPierre Pronchery 	// value_string(NULL) yields NULL
174*592efe25SPierre Pronchery 	TEST_ASSERT_NULL(spdxtool_serialize_value_string(NULL));
175*592efe25SPierre Pronchery 
176*592efe25SPierre Pronchery 	// add_take with a NULL container frees the value and returns NULL
177*592efe25SPierre Pronchery 	TEST_ASSERT_NULL(spdxtool_serialize_object_add_take(NULL, "k", v));
178*592efe25SPierre Pronchery 	TEST_ASSERT_NULL(spdxtool_serialize_array_add_take(NULL, spdxtool_serialize_value_null()));
179*592efe25SPierre Pronchery 
180*592efe25SPierre Pronchery 	// free routines are NULL-safe
181*592efe25SPierre Pronchery 	spdxtool_serialize_value_free(NULL);
182*592efe25SPierre Pronchery 	spdxtool_serialize_object_free(NULL);
183*592efe25SPierre Pronchery 	spdxtool_serialize_object_list_free(NULL);
184*592efe25SPierre Pronchery 	spdxtool_serialize_array_free(NULL);
185*592efe25SPierre Pronchery }
186*592efe25SPierre Pronchery 
187*592efe25SPierre Pronchery int
main(int argc,const char ** argv)188*592efe25SPierre Pronchery main(int argc, const char **argv)
189*592efe25SPierre Pronchery {
190*592efe25SPierre Pronchery 	(void) argc;
191*592efe25SPierre Pronchery 	const char *basename = pkgconf_path_find_basename(argv[0]);
192*592efe25SPierre Pronchery 
193*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_value_string);
194*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_value_int);
195*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_value_bool);
196*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_value_null);
197*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_escape_sequences);
198*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_object_mixed_types);
199*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_array_mixed_types);
200*592efe25SPierre Pronchery 	TEST_RUN(basename, test_serialize_null_guards);
201*592efe25SPierre Pronchery 
202*592efe25SPierre Pronchery 	return EXIT_SUCCESS;
203*592efe25SPierre Pronchery }
204