1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/socket.h>
5 #include <sys/sysmacros.h>
10 #include "alloc-util.h"
13 #include "format-util.h"
15 #include "iovec-util.h"
16 #include "json-internal.h"
17 #include "json-util.h"
18 #include "math-util.h"
19 #include "ordered-set.h"
22 #include "string-table.h"
24 #include "tmpfile-util.h"
26 static void test_tokenizer_one(const char *data
, ...) {
27 unsigned line
= 0, column
= 0;
31 _cleanup_free_
char *cdata
= NULL
;
32 assert_se(cdata
= cescape(data
));
33 log_info("/* %s data=\"%s\" */", __func__
, cdata
);
38 unsigned token_line
, token_column
;
39 _cleanup_free_
char *str
= NULL
;
40 JsonValue v
= JSON_VALUE_NULL
;
43 t
= json_tokenize(&data
, &str
, &v
, &token_line
, &token_column
, &state
, &line
, &column
);
48 if (t
== JSON_TOKEN_END
|| t
< 0)
51 else if (t
== JSON_TOKEN_STRING
) {
54 nn
= va_arg(ap
, const char *);
55 ASSERT_STREQ(nn
, str
);
57 } else if (t
== JSON_TOKEN_REAL
) {
60 d
= va_arg(ap
, double);
62 assert_se(fabs(d
- v
.real
) < 1e-10 ||
63 fabs((d
- v
.real
) / v
.real
) < 1e-10);
65 } else if (t
== JSON_TOKEN_INTEGER
) {
68 i
= va_arg(ap
, int64_t);
69 assert_se(i
== v
.integer
);
71 } else if (t
== JSON_TOKEN_UNSIGNED
) {
74 u
= va_arg(ap
, uint64_t);
75 assert_se(u
== v
.unsig
);
77 } else if (t
== JSON_TOKEN_BOOLEAN
) {
81 assert_se(b
== v
.boolean
);
88 typedef void (*Test
)(sd_json_variant
*);
90 static void test_variant_one(const char *data
, Test test
) {
91 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
, *w
= NULL
;
92 _cleanup_free_
char *s
= NULL
;
95 _cleanup_free_
char *cdata
;
96 assert_se(cdata
= cescape(data
));
97 log_info("/* %s data=\"%s\" */", __func__
, cdata
);
99 r
= sd_json_parse(data
, 0, &v
, NULL
, NULL
);
103 r
= sd_json_variant_format(v
, 0, &s
);
106 assert_se((size_t) r
== strlen(s
));
108 log_info("formatted normally: %s", s
);
110 r
= sd_json_parse(data
, SD_JSON_PARSE_SENSITIVE
, &w
, NULL
, NULL
);
113 assert_se(sd_json_variant_has_type(v
, sd_json_variant_type(w
)));
114 assert_se(sd_json_variant_has_type(w
, sd_json_variant_type(v
)));
115 assert_se(sd_json_variant_equal(v
, w
));
118 r
= sd_json_variant_format(w
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
);
120 ASSERT_STREQ(s
, "\"<sensitive data>\"");
123 r
= sd_json_variant_format(w
, SD_JSON_FORMAT_PRETTY
, &s
);
126 assert_se((size_t) r
== strlen(s
));
129 w
= sd_json_variant_unref(w
);
131 r
= sd_json_variant_format(v
, SD_JSON_FORMAT_PRETTY
, &s
);
134 assert_se((size_t) r
== strlen(s
));
136 log_info("formatted prettily:\n%s", s
);
138 r
= sd_json_parse(data
, 0, &w
, NULL
, NULL
);
142 assert_se(sd_json_variant_has_type(v
, sd_json_variant_type(w
)));
143 assert_se(sd_json_variant_has_type(w
, sd_json_variant_type(v
)));
144 assert_se(sd_json_variant_equal(v
, w
));
147 r
= sd_json_variant_format(v
, SD_JSON_FORMAT_COLOR
, &s
);
150 assert_se((size_t) r
== strlen(s
));
151 printf("Normal with color: %s\n", s
);
154 r
= sd_json_variant_format(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, &s
);
157 assert_se((size_t) r
== strlen(s
));
158 printf("Pretty with color:\n%s\n", s
);
164 static void test_1(sd_json_variant
*v
) {
165 sd_json_variant
*p
, *q
;
168 log_info("/* %s */", __func__
);
170 /* 3 keys + 3 values */
171 assert_se(sd_json_variant_elements(v
) == 6);
174 p
= sd_json_variant_by_key(v
, "k");
175 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_STRING
);
178 ASSERT_STREQ(sd_json_variant_string(p
), "v");
181 p
= sd_json_variant_by_key(v
, "foo");
182 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_ARRAY
&& sd_json_variant_elements(p
) == 3);
184 /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */
185 for (i
= 0; i
< 3; ++i
) {
186 q
= sd_json_variant_by_index(p
, i
);
187 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_UNSIGNED
&& sd_json_variant_unsigned(q
) == (i
+1));
188 assert_se(q
&& sd_json_variant_has_type(q
, SD_JSON_VARIANT_INTEGER
) && sd_json_variant_integer(q
) == (i
+1));
192 p
= sd_json_variant_by_key(v
, "bar");
193 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_OBJECT
&& sd_json_variant_elements(p
) == 2);
196 q
= sd_json_variant_by_key(p
, "zap");
197 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_NULL
);
200 static void test_2(sd_json_variant
*v
) {
201 sd_json_variant
*p
, *q
;
203 log_info("/* %s */", __func__
);
205 /* 2 keys + 2 values */
206 assert_se(sd_json_variant_elements(v
) == 4);
209 p
= sd_json_variant_by_key(v
, "mutant");
210 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_ARRAY
&& sd_json_variant_elements(p
) == 4);
213 q
= sd_json_variant_by_index(p
, 0);
214 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_UNSIGNED
&& sd_json_variant_unsigned(q
) == 1);
215 assert_se(q
&& sd_json_variant_has_type(q
, SD_JSON_VARIANT_INTEGER
) && sd_json_variant_integer(q
) == 1);
217 /* mutant[1] == null */
218 q
= sd_json_variant_by_index(p
, 1);
219 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_NULL
);
221 /* mutant[2] == "1" */
222 q
= sd_json_variant_by_index(p
, 2);
223 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_STRING
&& streq(sd_json_variant_string(q
), "1"));
225 /* mutant[3] == SD_JSON_VARIANT_OBJECT */
226 q
= sd_json_variant_by_index(p
, 3);
227 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_OBJECT
&& sd_json_variant_elements(q
) == 2);
230 p
= sd_json_variant_by_key(q
, "1");
231 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_ARRAY
&& sd_json_variant_elements(p
) == 2);
234 q
= sd_json_variant_by_index(p
, 0);
235 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_UNSIGNED
&& sd_json_variant_unsigned(q
) == 1);
236 assert_se(q
&& sd_json_variant_has_type(q
, SD_JSON_VARIANT_INTEGER
) && sd_json_variant_integer(q
) == 1);
239 q
= sd_json_variant_by_index(p
, 1);
240 assert_se(q
&& sd_json_variant_type(q
) == SD_JSON_VARIANT_STRING
&& streq(sd_json_variant_string(q
), "1"));
242 /* has thisisaverylongproperty */
243 p
= sd_json_variant_by_key(v
, "thisisaverylongproperty");
244 assert_se(p
&& sd_json_variant_type(p
) == SD_JSON_VARIANT_REAL
&& fabs(sd_json_variant_real(p
) - 1.27) < 0.001);
247 static void test_zeroes(sd_json_variant
*v
) {
248 /* Make sure zero is how we expect it. */
249 log_info("/* %s */", __func__
);
251 assert_se(sd_json_variant_elements(v
) == 13);
253 for (size_t i
= 0; i
< sd_json_variant_elements(v
); i
++) {
257 assert_se(w
= sd_json_variant_by_index(v
, i
));
259 assert_se(sd_json_variant_integer(w
) == 0);
260 assert_se(sd_json_variant_unsigned(w
) == 0U);
262 assert_se(iszero_safe(sd_json_variant_real(w
)));
264 assert_se(sd_json_variant_is_integer(w
));
265 assert_se(sd_json_variant_is_unsigned(w
));
266 assert_se(sd_json_variant_is_real(w
));
267 assert_se(sd_json_variant_is_number(w
));
269 assert_se(!sd_json_variant_is_negative(w
));
271 assert_se(IN_SET(sd_json_variant_type(w
), SD_JSON_VARIANT_INTEGER
, SD_JSON_VARIANT_UNSIGNED
, SD_JSON_VARIANT_REAL
));
273 for (j
= 0; j
< sd_json_variant_elements(v
); j
++) {
276 assert_se(q
= sd_json_variant_by_index(v
, j
));
278 assert_se(sd_json_variant_equal(w
, q
));
283 static int test_callback(sd_json_variant
**ret
, const char *name
, void *userdata
) {
285 if (streq_ptr(name
, "mypid1"))
286 assert_se(PTR_TO_INT(userdata
) == 4711);
287 else if (streq_ptr(name
, "mypid2"))
288 assert_se(PTR_TO_INT(userdata
) == 4712);
289 else if (streq_ptr(name
, "mypid3"))
292 assert_not_reached();
294 return sd_json_build(ret
, SD_JSON_BUILD_INTEGER(getpid()));
298 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*a
= NULL
, *b
= NULL
;
299 _cleanup_free_
char *s
= NULL
, *t
= NULL
;
301 assert_se(sd_json_build(&a
, SD_JSON_BUILD_STRING("hallo")) >= 0);
302 assert_se(sd_json_build(&b
, SD_JSON_BUILD_LITERAL(" \"hallo\" ")) >= 0);
303 assert_se(sd_json_variant_equal(a
, b
));
305 b
= sd_json_variant_unref(b
);
307 assert_se(sd_json_build(&b
, SD_JSON_BUILD_VARIANT(a
)) >= 0);
308 assert_se(sd_json_variant_equal(a
, b
));
310 b
= sd_json_variant_unref(b
);
311 assert_se(sd_json_build(&b
, SD_JSON_BUILD_STRING("pief")) >= 0);
312 assert_se(!sd_json_variant_equal(a
, b
));
314 a
= sd_json_variant_unref(a
);
315 b
= sd_json_variant_unref(b
);
317 assert_se(sd_json_buildo(&a
,
318 SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_INTEGER(7)),
319 SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_REAL(2.0)),
320 SD_JSON_BUILD_PAIR("four", JSON_BUILD_STRING_UNDERSCORIFY("foo-bar-baz")),
321 SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_INTEGER(0))) >= 0);
323 assert_se(sd_json_buildo(&b
,
324 SD_JSON_BUILD_PAIR("two", SD_JSON_BUILD_INTEGER(2)),
325 SD_JSON_BUILD_PAIR("four", SD_JSON_BUILD_STRING("foo_bar_baz")),
326 SD_JSON_BUILD_PAIR("three", SD_JSON_BUILD_REAL(0)),
327 SD_JSON_BUILD_PAIR("one", SD_JSON_BUILD_REAL(7))) >= 0);
329 assert_se(sd_json_variant_equal(a
, b
));
331 a
= sd_json_variant_unref(a
);
332 b
= sd_json_variant_unref(b
);
334 const char* arr_1234
[] = {"one", "two", "three", "four", NULL
};
335 assert_se(sd_json_build(&a
, SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_BOOLEAN(true)),
336 SD_JSON_BUILD_PAIR("y", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("this", SD_JSON_BUILD_NULL
)))),
337 SD_JSON_BUILD_VARIANT(NULL
),
338 SD_JSON_BUILD_LITERAL(NULL
),
339 SD_JSON_BUILD_STRING(NULL
),
341 SD_JSON_BUILD_INTEGER(77),
342 SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")),
343 SD_JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))),
344 SD_JSON_BUILD_STRV((char**) arr_1234
))) >= 0);
346 assert_se(sd_json_variant_format(a
, 0, &s
) >= 0);
347 log_info("GOT: %s", s
);
348 assert_se(sd_json_parse(s
, 0, &b
, NULL
, NULL
) >= 0);
349 assert_se(sd_json_variant_equal(a
, b
));
351 a
= sd_json_variant_unref(a
);
352 b
= sd_json_variant_unref(b
);
354 assert_se(sd_json_build(&a
, SD_JSON_BUILD_REAL(M_PI
)) >= 0);
357 assert_se(sd_json_variant_format(a
, 0, &s
) >= 0);
358 log_info("GOT: %s", s
);
359 assert_se(sd_json_parse(s
, 0, &b
, NULL
, NULL
) >= 0);
360 assert_se(sd_json_variant_format(b
, 0, &t
) >= 0);
361 log_info("GOT: %s", t
);
365 a
= sd_json_variant_unref(a
);
366 b
= sd_json_variant_unref(b
);
368 assert_se(sd_json_build(&a
, SD_JSON_BUILD_OBJECT(
369 SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_STRING("y")),
370 SD_JSON_BUILD_PAIR("z", JSON_BUILD_CONST_STRING("a")),
371 SD_JSON_BUILD_PAIR("b", JSON_BUILD_CONST_STRING("c"))
374 assert_se(sd_json_build(&b
, SD_JSON_BUILD_OBJECT(
375 SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_STRING("y")),
376 SD_JSON_BUILD_PAIR_CONDITION(false, "p", SD_JSON_BUILD_STRING("q")),
377 SD_JSON_BUILD_PAIR_CONDITION(true, "z", JSON_BUILD_CONST_STRING("a")),
378 SD_JSON_BUILD_PAIR_CONDITION(false, "j", SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_STRING("k"), JSON_BUILD_CONST_STRING("u"), JSON_BUILD_CONST_STRING("i"))),
379 SD_JSON_BUILD_PAIR("b", JSON_BUILD_CONST_STRING("c"))
382 assert_se(sd_json_variant_equal(a
, b
));
384 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*x
= NULL
;
385 assert_se(sd_json_build(&x
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("foo", SD_JSON_BUILD_INTEGER(77)),
386 SD_JSON_BUILD_PAIR("bar", SD_JSON_BUILD_INTEGER(88)))) >= 0);
388 sd_json_variant
*array
[] = { a
, a
, b
, b
, x
, x
};
389 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*va
= NULL
;
391 assert_se(sd_json_build(&va
, SD_JSON_BUILD_VARIANT_ARRAY(array
, ELEMENTSOF(array
))) >= 0);
393 assert_se(sd_json_variant_is_array(va
));
394 assert_se(sd_json_variant_elements(va
) == 6);
395 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 0), a
));
396 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 1), b
));
397 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 2), a
));
398 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 3), b
));
399 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 4), x
));
400 assert_se(sd_json_variant_equal(sd_json_variant_by_index(va
, 5), x
));
402 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*y
= NULL
;
403 assert_se(sd_json_build(&y
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("mypid1", SD_JSON_BUILD_CALLBACK(test_callback
, INT_TO_PTR(4711))),
404 SD_JSON_BUILD_PAIR("mypid2", SD_JSON_BUILD_CALLBACK(test_callback
, INT_TO_PTR(4712))))) >= 0);
406 _cleanup_free_
char *f1
= NULL
, *f2
= NULL
;
407 assert_se(asprintf(&f1
, "{\"mypid1\":" PID_FMT
",\"mypid2\":" PID_FMT
"}", getpid(), getpid()) >= 0);
409 assert_se(sd_json_variant_format(y
, /* flags= */ 0, &f2
));
410 ASSERT_STREQ(f1
, f2
);
412 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*z
= NULL
;
413 ASSERT_OK(sd_json_build(&z
, SD_JSON_BUILD_OBJECT(JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid3", test_callback
, INT_TO_PTR(4713)))));
414 ASSERT_TRUE(sd_json_variant_is_blank_object(z
));
415 z
= sd_json_variant_unref(z
);
417 ASSERT_OK(sd_json_build(&z
, SD_JSON_BUILD_OBJECT(JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid1", test_callback
, INT_TO_PTR(4711)),
418 JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid2", test_callback
, INT_TO_PTR(4712)))));
419 ASSERT_OK(sd_json_variant_format(z
, /* flags= */ 0, &f2
));
420 ASSERT_STREQ(f1
, f2
);
422 _cleanup_set_free_ Set
*ss
= NULL
;
423 assert_se(set_ensure_put(&ss
, &string_hash_ops_free
, ASSERT_PTR(strdup("pief"))) >= 0);
424 assert_se(set_ensure_put(&ss
, &string_hash_ops_free
, ASSERT_PTR(strdup("xxxx"))) >= 0);
425 assert_se(set_ensure_put(&ss
, &string_hash_ops_free
, ASSERT_PTR(strdup("kawumm"))) >= 0);
427 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*ssv
= NULL
;
428 assert_se(sd_json_build(&ssv
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("zzz", JSON_BUILD_STRING_SET(ss
)))) >= 0);
429 assert_se(sd_json_variant_sort(&ssv
) >= 0);
431 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*ssv2
= NULL
;
432 assert_se(sd_json_build(&ssv2
, SD_JSON_BUILD_LITERAL("{\"zzz\":[\"kawumm\",\"pief\",\"xxxx\"]}")) >= 0);
434 assert_se(sd_json_variant_equal(ssv
, ssv2
));
436 _cleanup_ordered_set_free_ OrderedSet
*oss
= NULL
;
437 assert_se(ordered_set_ensure_put(&oss
, &string_hash_ops_free
, ASSERT_PTR(strdup("pief"))) >= 0);
438 assert_se(ordered_set_ensure_put(&oss
, &string_hash_ops_free
, ASSERT_PTR(strdup("xxxx"))) >= 0);
439 assert_se(ordered_set_ensure_put(&oss
, &string_hash_ops_free
, ASSERT_PTR(strdup("kawumm"))) >= 0);
441 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*ossv
= NULL
;
442 assert_se(sd_json_build(&ossv
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("zzz", JSON_BUILD_STRING_ORDERED_SET(oss
)))) >= 0);
444 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*ossv2
= NULL
;
445 assert_se(sd_json_build(&ossv2
, SD_JSON_BUILD_LITERAL("{\"zzz\":[\"pief\",\"xxxx\",\"kawumm\"]}")) >= 0);
447 assert_se(sd_json_variant_equal(ossv
, ossv2
));
451 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*a
= NULL
, *b
= NULL
;
453 assert_se(sd_json_buildo(&a
,
454 SD_JSON_BUILD_PAIR("foo", SD_JSON_BUILD_INTEGER(4711)),
455 SD_JSON_BUILD_PAIR("bar", SD_JSON_BUILD_STRING("xxxx"))) >= 0);
457 assert_se(sd_json_build(&b
,
458 SD_JSON_BUILD_OBJECT(
459 SD_JSON_BUILD_PAIR("bar", SD_JSON_BUILD_STRING("xxxx")),
460 SD_JSON_BUILD_PAIR("foo", SD_JSON_BUILD_INTEGER(4711)))) >= 0);
462 assert_se(sd_json_variant_equal(a
, b
));
465 TEST(json_parse_file_empty
) {
466 _cleanup_fclose_
FILE *f
= NULL
;
467 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
469 assert_se(fopen_unlocked("/dev/null", "re", &f
) >= 0);
470 assert_se(sd_json_parse_file(f
, "waldo", 0, &v
, NULL
, NULL
) == -ENODATA
);
474 TEST(json_parse_file_invalid
) {
475 _cleanup_fclose_
FILE *f
= NULL
;
476 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
478 assert_se(f
= fmemopen_unlocked((void*) "kookoo", 6, "r"));
479 assert_se(sd_json_parse_file(f
, "waldo", 0, &v
, NULL
, NULL
) == -EINVAL
);
484 static const char data
[] =
488 "\"foo\" : \"bar\", \n"
489 "\"qüüx\" : [ 1, 2, 3,\n"
492 "\"miep\" : { \"hallo\" : 1 },\n"
500 _cleanup_fclose_
FILE *f
= NULL
;
501 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
503 printf("--- original begin ---\n"
505 "--- original end ---\n", data
);
507 assert_se(f
= fmemopen_unlocked((void*) data
, strlen(data
), "r"));
509 assert_se(sd_json_parse_file(f
, "waldo", 0, &v
, NULL
, NULL
) >= 0);
511 printf("--- non-pretty begin ---\n");
512 sd_json_variant_dump(v
, 0, stdout
, NULL
);
513 printf("\n--- non-pretty end ---\n");
515 printf("--- pretty begin ---\n");
516 sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY
|SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_SOURCE
, stdout
, NULL
);
517 printf("--- pretty end ---\n");
521 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
524 v
= JSON_VARIANT_STRING_CONST("start");
526 /* Let's verify that the maximum depth checks work */
528 for (unsigned i
= 0;; i
++) {
529 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*w
= NULL
;
531 assert_se(i
<= UINT16_MAX
);
533 r
= sd_json_variant_new_array(&w
, &v
, 1);
535 r
= sd_json_variant_new_object(&w
, (sd_json_variant
*[]) { JSON_VARIANT_STRING_CONST("key"), v
}, 2);
537 log_info("max depth at %u", i
);
540 #if HAS_FEATURE_MEMORY_SANITIZER
541 /* msan doesn't like the stack nesting to be too deep. Let's quit early. */
543 log_info("quitting early at depth %u", i
);
550 sd_json_variant_unref(v
);
554 sd_json_variant_dump(v
, 0, stdout
, NULL
);
559 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
, *w
= NULL
;
560 _cleanup_free_
char *t
= NULL
;
562 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
563 SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("x")),
564 SD_JSON_BUILD_PAIR("c", JSON_BUILD_CONST_STRING("y")),
565 SD_JSON_BUILD_PAIR("a", JSON_BUILD_CONST_STRING("z")))) >= 0);
567 assert_se(!sd_json_variant_is_sorted(v
));
568 assert_se(!sd_json_variant_is_normalized(v
));
570 assert_se(sd_json_variant_format(v
, 0, &t
) >= 0);
571 ASSERT_STREQ(t
, "{\"b\":\"x\",\"c\":\"y\",\"a\":\"z\"}");
574 assert_se(sd_json_build(&w
, SD_JSON_BUILD_OBJECT(
575 SD_JSON_BUILD_PAIR("bar", SD_JSON_BUILD_STRING("zzz")),
576 SD_JSON_BUILD_PAIR("foo", SD_JSON_BUILD_VARIANT(v
)))) >= 0);
578 assert_se(sd_json_variant_is_sorted(w
));
579 assert_se(!sd_json_variant_is_normalized(w
));
581 assert_se(sd_json_variant_format(w
, 0, &t
) >= 0);
582 ASSERT_STREQ(t
, "{\"bar\":\"zzz\",\"foo\":{\"b\":\"x\",\"c\":\"y\",\"a\":\"z\"}}");
585 assert_se(sd_json_variant_sort(&v
) >= 0);
586 assert_se(sd_json_variant_is_sorted(v
));
587 assert_se(sd_json_variant_is_normalized(v
));
589 assert_se(sd_json_variant_format(v
, 0, &t
) >= 0);
590 ASSERT_STREQ(t
, "{\"a\":\"z\",\"b\":\"x\",\"c\":\"y\"}");
593 assert_se(sd_json_variant_normalize(&w
) >= 0);
594 assert_se(sd_json_variant_is_sorted(w
));
595 assert_se(sd_json_variant_is_normalized(w
));
597 assert_se(sd_json_variant_format(w
, 0, &t
) >= 0);
598 ASSERT_STREQ(t
, "{\"bar\":\"zzz\",\"foo\":{\"a\":\"z\",\"b\":\"x\",\"c\":\"y\"}}");
603 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
605 /* Tests the bisection logic in sd_json_variant_by_key() */
607 for (char c
= 'z'; c
>= 'a'; c
--) {
612 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*w
= NULL
;
613 assert_se(sd_json_variant_new_stringn(&w
, (char[4]) { '<', c
, c
, '>' }, 4) >= 0);
614 assert_se(sd_json_variant_set_field(&v
, (char[2]) { c
, 0 }, w
) >= 0);
617 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
619 assert_se(!sd_json_variant_is_sorted(v
));
620 assert_se(!sd_json_variant_is_normalized(v
));
621 assert_se(sd_json_variant_normalize(&v
) >= 0);
622 assert_se(sd_json_variant_is_sorted(v
));
623 assert_se(sd_json_variant_is_normalized(v
));
625 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
627 for (char c
= 'a'; c
<= 'z'; c
++) {
631 k
= sd_json_variant_by_key(v
, (char[2]) { c
, 0 });
632 assert_se(!k
== ((c
% 3) == 0));
637 assert_se(sd_json_variant_is_string(k
));
639 z
= (char[5]){ '<', c
, c
, '>', 0};
640 ASSERT_STREQ(sd_json_variant_string(k
), z
);
644 static void test_float_match(sd_json_variant
*v
) {
645 const double delta
= 0.0001;
647 assert_se(sd_json_variant_is_array(v
));
648 assert_se(sd_json_variant_elements(v
) == 11);
649 assert_se(fabs(1.0 - (DBL_MIN
/ sd_json_variant_real(sd_json_variant_by_index(v
, 0)))) <= delta
);
650 assert_se(fabs(1.0 - (DBL_MAX
/ sd_json_variant_real(sd_json_variant_by_index(v
, 1)))) <= delta
);
651 assert_se(sd_json_variant_is_null(sd_json_variant_by_index(v
, 2))); /* nan is not supported by json → null */
652 assert_se(sd_json_variant_is_null(sd_json_variant_by_index(v
, 3))); /* +inf is not supported by json → null */
653 assert_se(sd_json_variant_is_null(sd_json_variant_by_index(v
, 4))); /* -inf is not supported by json → null */
654 assert_se(sd_json_variant_is_null(sd_json_variant_by_index(v
, 5)) ||
655 fabs(1.0 - (HUGE_VAL
/ sd_json_variant_real(sd_json_variant_by_index(v
, 5)))) <= delta
); /* HUGE_VAL might be +inf, but might also be something else */
656 assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v
, 6)) &&
657 sd_json_variant_is_integer(sd_json_variant_by_index(v
, 6)) &&
658 sd_json_variant_integer(sd_json_variant_by_index(v
, 6)) == 0);
659 assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v
, 7)) &&
660 sd_json_variant_is_integer(sd_json_variant_by_index(v
, 7)) &&
661 sd_json_variant_integer(sd_json_variant_by_index(v
, 7)) == 10);
662 assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v
, 8)) &&
663 sd_json_variant_is_integer(sd_json_variant_by_index(v
, 8)) &&
664 sd_json_variant_integer(sd_json_variant_by_index(v
, 8)) == -10);
665 assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v
, 9)) &&
666 !sd_json_variant_is_integer(sd_json_variant_by_index(v
, 9)));
667 assert_se(fabs(1.0 - (DBL_MIN
/ 2 / sd_json_variant_real(sd_json_variant_by_index(v
, 9)))) <= delta
);
668 assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v
, 10)) &&
669 !sd_json_variant_is_integer(sd_json_variant_by_index(v
, 10)));
670 assert_se(fabs(1.0 - (-DBL_MIN
/ 2 / sd_json_variant_real(sd_json_variant_by_index(v
, 10)))) <= delta
);
674 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
, *w
= NULL
;
675 _cleanup_free_
char *text
= NULL
;
677 assert_se(sd_json_build(&v
, SD_JSON_BUILD_ARRAY(
678 SD_JSON_BUILD_REAL(DBL_MIN
),
679 SD_JSON_BUILD_REAL(DBL_MAX
),
680 SD_JSON_BUILD_REAL(NAN
),
681 SD_JSON_BUILD_REAL(INFINITY
),
682 SD_JSON_BUILD_REAL(-INFINITY
),
683 SD_JSON_BUILD_REAL(HUGE_VAL
),
684 SD_JSON_BUILD_REAL(0),
685 SD_JSON_BUILD_REAL(10),
686 SD_JSON_BUILD_REAL(-10),
687 SD_JSON_BUILD_REAL(DBL_MIN
/ 2),
688 SD_JSON_BUILD_REAL(-DBL_MIN
/ 2))) >= 0);
690 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
694 assert_se(sd_json_variant_format(v
, 0, &text
) >= 0);
695 assert_se(sd_json_parse(text
, 0, &w
, NULL
, NULL
) >= 0);
697 sd_json_variant_dump(w
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
702 static void test_equal_text(sd_json_variant
*v
, const char *text
) {
703 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*w
= NULL
;
705 assert_se(sd_json_parse(text
, 0, &w
, NULL
, NULL
) >= 0);
706 assert_se(sd_json_variant_equal(v
, w
) || (!v
&& sd_json_variant_is_null(w
)));
710 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
712 test_equal_text(v
, "null");
713 assert_se(sd_json_variant_set_field(&v
, "foo", NULL
) >= 0);
714 test_equal_text(v
, "{\"foo\" : null}");
715 assert_se(sd_json_variant_set_field(&v
, "bar", JSON_VARIANT_STRING_CONST("quux")) >= 0);
716 test_equal_text(v
, "{\"foo\" : null, \"bar\" : \"quux\"}");
717 assert_se(sd_json_variant_set_field(&v
, "foo", JSON_VARIANT_STRING_CONST("quux2")) >= 0);
718 test_equal_text(v
, "{\"foo\" : \"quux2\", \"bar\" : \"quux\"}");
719 assert_se(sd_json_variant_set_field(&v
, "bar", NULL
) >= 0);
720 test_equal_text(v
, "{\"foo\" : \"quux2\", \"bar\" : null}");
724 test_tokenizer_one("x", -EINVAL
);
725 test_tokenizer_one("", JSON_TOKEN_END
);
726 test_tokenizer_one(" ", JSON_TOKEN_END
);
727 test_tokenizer_one("0", JSON_TOKEN_UNSIGNED
, (uint64_t) 0, JSON_TOKEN_END
);
728 test_tokenizer_one("-0", JSON_TOKEN_INTEGER
, (int64_t) 0, JSON_TOKEN_END
);
729 test_tokenizer_one("1234", JSON_TOKEN_UNSIGNED
, (uint64_t) 1234, JSON_TOKEN_END
);
730 test_tokenizer_one("-1234", JSON_TOKEN_INTEGER
, (int64_t) -1234, JSON_TOKEN_END
);
731 test_tokenizer_one("18446744073709551615", JSON_TOKEN_UNSIGNED
, (uint64_t) UINT64_MAX
, JSON_TOKEN_END
);
732 test_tokenizer_one("-9223372036854775808", JSON_TOKEN_INTEGER
, (int64_t) INT64_MIN
, JSON_TOKEN_END
);
733 test_tokenizer_one("18446744073709551616", JSON_TOKEN_REAL
, (double) 18446744073709551616.0L, JSON_TOKEN_END
);
734 test_tokenizer_one("-9223372036854775809", JSON_TOKEN_REAL
, (double) -9223372036854775809.0L, JSON_TOKEN_END
);
735 test_tokenizer_one("-1234", JSON_TOKEN_INTEGER
, (int64_t) -1234, JSON_TOKEN_END
);
736 test_tokenizer_one("3.141", JSON_TOKEN_REAL
, (double) 3.141, JSON_TOKEN_END
);
737 test_tokenizer_one("0.0", JSON_TOKEN_REAL
, (double) 0.0, JSON_TOKEN_END
);
738 test_tokenizer_one("7e3", JSON_TOKEN_REAL
, (double) 7e3
, JSON_TOKEN_END
);
739 test_tokenizer_one("-7e-3", JSON_TOKEN_REAL
, (double) -7e-3, JSON_TOKEN_END
);
740 test_tokenizer_one("true", JSON_TOKEN_BOOLEAN
, true, JSON_TOKEN_END
);
741 test_tokenizer_one("false", JSON_TOKEN_BOOLEAN
, false, JSON_TOKEN_END
);
742 test_tokenizer_one("null", JSON_TOKEN_NULL
, JSON_TOKEN_END
);
743 test_tokenizer_one("{}", JSON_TOKEN_OBJECT_OPEN
, JSON_TOKEN_OBJECT_CLOSE
, JSON_TOKEN_END
);
744 test_tokenizer_one("\t {\n} \n", JSON_TOKEN_OBJECT_OPEN
, JSON_TOKEN_OBJECT_CLOSE
, JSON_TOKEN_END
);
745 test_tokenizer_one("[]", JSON_TOKEN_ARRAY_OPEN
, JSON_TOKEN_ARRAY_CLOSE
, JSON_TOKEN_END
);
746 test_tokenizer_one("\t [] \n\n", JSON_TOKEN_ARRAY_OPEN
, JSON_TOKEN_ARRAY_CLOSE
, JSON_TOKEN_END
);
747 test_tokenizer_one("\"\"", JSON_TOKEN_STRING
, "", JSON_TOKEN_END
);
748 test_tokenizer_one("\"foo\"", JSON_TOKEN_STRING
, "foo", JSON_TOKEN_END
);
749 test_tokenizer_one("\"foo\\nfoo\"", JSON_TOKEN_STRING
, "foo\nfoo", JSON_TOKEN_END
);
750 test_tokenizer_one("{\"foo\" : \"bar\"}", JSON_TOKEN_OBJECT_OPEN
, JSON_TOKEN_STRING
, "foo", JSON_TOKEN_COLON
, JSON_TOKEN_STRING
, "bar", JSON_TOKEN_OBJECT_CLOSE
, JSON_TOKEN_END
);
751 test_tokenizer_one("{\"foo\" : [true, false]}", JSON_TOKEN_OBJECT_OPEN
, JSON_TOKEN_STRING
, "foo", JSON_TOKEN_COLON
, JSON_TOKEN_ARRAY_OPEN
, JSON_TOKEN_BOOLEAN
, true, JSON_TOKEN_COMMA
, JSON_TOKEN_BOOLEAN
, false, JSON_TOKEN_ARRAY_CLOSE
, JSON_TOKEN_OBJECT_CLOSE
, JSON_TOKEN_END
);
752 test_tokenizer_one("\"\xef\xbf\xbd\"", JSON_TOKEN_STRING
, "\xef\xbf\xbd", JSON_TOKEN_END
);
753 test_tokenizer_one("\"\\ufffd\"", JSON_TOKEN_STRING
, "\xef\xbf\xbd", JSON_TOKEN_END
);
754 test_tokenizer_one("\"\\uf\"", -EINVAL
);
755 test_tokenizer_one("\"\\ud800a\"", -EINVAL
);
756 test_tokenizer_one("\"\\udc00\\udc00\"", -EINVAL
);
757 test_tokenizer_one("\"\\ud801\\udc37\"", JSON_TOKEN_STRING
, "\xf0\x90\x90\xb7", JSON_TOKEN_END
);
759 test_tokenizer_one("[1, 2, -3]", JSON_TOKEN_ARRAY_OPEN
, JSON_TOKEN_UNSIGNED
, (uint64_t) 1, JSON_TOKEN_COMMA
, JSON_TOKEN_UNSIGNED
, (uint64_t) 2, JSON_TOKEN_COMMA
, JSON_TOKEN_INTEGER
, (int64_t) -3, JSON_TOKEN_ARRAY_CLOSE
, JSON_TOKEN_END
);
763 test_variant_one("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1
);
764 test_variant_one("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2
);
765 test_variant_one("{\"foo\" : \"\\u0935\\u093f\\u0935\\u0947\\u0915\\u0916\\u094d\\u092f\\u093e\\u0924\\u093f\\u0930\\u0935\\u093f\\u092a\\u094d\\u0932\\u0935\\u093e\\u0020\\u0939\\u093e\\u0928\\u094b\\u092a\\u093e\\u092f\\u0903\\u0964\"}", NULL
);
767 test_variant_one("[ 0, -0, 0.0, -0.0, 0.000, -0.000, 0e0, -0e0, 0e+0, -0e-0, 0e-0, -0e000, 0e+000 ]", test_zeroes
);
770 TEST(json_variant_merge_objectb
) {
771 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
, *w
= NULL
;
773 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
774 SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("x")),
775 SD_JSON_BUILD_PAIR("c", JSON_BUILD_CONST_STRING("y")),
776 SD_JSON_BUILD_PAIR("a", JSON_BUILD_CONST_STRING("z")))) >= 0);
778 assert_se(sd_json_variant_merge_objectb(&w
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("x")))) >= 0);
779 assert_se(sd_json_variant_merge_objectb(&w
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_STRING("y")))) >= 0);
780 assert_se(sd_json_variant_merge_objectb(&w
, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_STRING("z")))) >= 0);
782 assert_se(sd_json_variant_equal(v
, w
));
785 static void json_array_append_with_source_one(bool source
) {
786 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*a
, *b
;
788 /* Parse two sources, each with a different name and line/column numbers */
790 assert_se(sd_json_parse_with_source(" [41]", source
? "string 1" : NULL
, 0,
791 &a
, NULL
, NULL
) >= 0);
792 assert_se(sd_json_parse_with_source("\n\n [42]", source
? "string 2" : NULL
, 0,
793 &b
, NULL
, NULL
) >= 0);
795 assert_se(sd_json_variant_is_array(a
));
796 assert_se(sd_json_variant_elements(a
) == 1);
797 assert_se(sd_json_variant_is_array(b
));
798 assert_se(sd_json_variant_elements(b
) == 1);
800 /* Verify source information */
803 unsigned line1
, col1
, line2
, col2
;
804 assert_se(sd_json_variant_get_source(a
, &s1
, &line1
, &col1
) >= 0);
805 assert_se(sd_json_variant_get_source(b
, &s2
, &line2
, &col2
) >= 0);
807 ASSERT_STREQ(s1
, source
? "string 1" : NULL
);
808 ASSERT_STREQ(s2
, source
? "string 2" : NULL
);
809 assert_se(line1
== 1);
810 assert_se(col1
== 2);
811 assert_se(line2
== 3);
812 assert_se(col2
== 4);
814 /* Append one elem from the second array (and source) to the first. */
816 sd_json_variant
*elem
;
817 assert_se(elem
= sd_json_variant_by_index(b
, 0));
818 assert_se(sd_json_variant_is_integer(elem
));
819 assert_se(sd_json_variant_elements(elem
) == 0);
821 assert_se(sd_json_variant_append_array(&a
, elem
) >= 0);
823 assert_se(sd_json_variant_is_array(a
));
824 assert_se(sd_json_variant_elements(a
) == 2);
826 /* Verify that source information was propagated correctly */
828 assert_se(sd_json_variant_get_source(elem
, &s1
, &line1
, &col1
) >= 0);
829 assert_se(elem
= sd_json_variant_by_index(a
, 1));
830 assert_se(sd_json_variant_get_source(elem
, &s2
, &line2
, &col2
) >= 0);
832 ASSERT_STREQ(s1
, source
? "string 2" : NULL
);
833 ASSERT_STREQ(s2
, source
? "string 2" : NULL
);
834 assert_se(line1
== 3);
835 assert_se(col1
== 5);
836 assert_se(line2
== 3);
837 assert_se(col2
== 5);
840 TEST(json_array_append_with_source
) {
841 json_array_append_with_source_one(true);
844 TEST(json_array_append_without_source
) {
845 json_array_append_with_source_one(false);
848 TEST(json_array_append_nodup
) {
849 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*l
= NULL
, *s
= NULL
, *wd
= NULL
, *nd
= NULL
;
851 assert_se(sd_json_build(&l
, SD_JSON_BUILD_STRV(STRV_MAKE("foo", "bar", "baz", "bar", "baz", "foo", "qux", "baz"))) >= 0);
852 assert_se(sd_json_build(&s
, SD_JSON_BUILD_STRV(STRV_MAKE("foo", "bar", "baz", "qux"))) >= 0);
854 assert_se(!sd_json_variant_equal(l
, s
));
855 assert_se(sd_json_variant_elements(l
) == 8);
856 assert_se(sd_json_variant_elements(s
) == 4);
859 JSON_VARIANT_ARRAY_FOREACH(i
, l
) {
860 assert_se(sd_json_variant_append_array(&wd
, i
) >= 0);
861 assert_se(sd_json_variant_append_array_nodup(&nd
, i
) >= 0);
864 assert_se(sd_json_variant_elements(wd
) == 8);
865 assert_se(sd_json_variant_equal(l
, wd
));
866 assert_se(!sd_json_variant_equal(s
, wd
));
868 assert_se(sd_json_variant_elements(nd
) == 4);
869 assert_se(!sd_json_variant_equal(l
, nd
));
870 assert_se(sd_json_variant_equal(s
, nd
));
873 TEST(json_dispatch
) {
885 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
887 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
888 SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_UNSIGNED(UINT64_MAX
)),
889 SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("18446744073709551615")),
890 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
891 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
892 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_UNSIGNED(UINT32_MAX
)),
893 SD_JSON_BUILD_PAIR("f", SD_JSON_BUILD_STRING("4294967295")),
894 SD_JSON_BUILD_PAIR("g", SD_JSON_BUILD_INTEGER(INT32_MIN
)),
895 SD_JSON_BUILD_PAIR("h", SD_JSON_BUILD_STRING("-2147483648")),
896 SD_JSON_BUILD_PAIR("i", SD_JSON_BUILD_UNSIGNED(UINT16_MAX
)),
897 SD_JSON_BUILD_PAIR("j", SD_JSON_BUILD_STRING("65535")),
898 SD_JSON_BUILD_PAIR("k", SD_JSON_BUILD_INTEGER(INT16_MIN
)),
899 SD_JSON_BUILD_PAIR("l", SD_JSON_BUILD_STRING("-32768")),
900 SD_JSON_BUILD_PAIR("m", SD_JSON_BUILD_INTEGER(UINT8_MAX
)),
901 SD_JSON_BUILD_PAIR("n", SD_JSON_BUILD_STRING("255")),
902 SD_JSON_BUILD_PAIR("o", SD_JSON_BUILD_INTEGER(INT8_MIN
)),
903 SD_JSON_BUILD_PAIR("p", SD_JSON_BUILD_STRING("-128")))) >= 0);
905 assert_se(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
|SD_JSON_FORMAT_COLOR_AUTO
, stdout
, /* prefix= */ NULL
) >= 0);
907 sd_json_dispatch_field table
[] = {
908 { "a", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint64
, offsetof(struct foobar
, a
) },
909 { "b", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint64
, offsetof(struct foobar
, b
) },
910 { "c", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int64
, offsetof(struct foobar
, c
) },
911 { "d", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int64
, offsetof(struct foobar
, d
) },
912 { "e", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint32
, offsetof(struct foobar
, e
) },
913 { "f", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint32
, offsetof(struct foobar
, f
) },
914 { "g", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int32
, offsetof(struct foobar
, g
) },
915 { "h", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int32
, offsetof(struct foobar
, h
) },
916 { "i", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint16
, offsetof(struct foobar
, i
) },
917 { "j", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint16
, offsetof(struct foobar
, j
) },
918 { "k", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int16
, offsetof(struct foobar
, k
) },
919 { "l", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int16
, offsetof(struct foobar
, l
) },
920 { "m", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint8
, offsetof(struct foobar
, m
) },
921 { "n", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint8
, offsetof(struct foobar
, n
) },
922 { "o", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int8
, offsetof(struct foobar
, o
) },
923 { "p", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_int8
, offsetof(struct foobar
, p
) },
927 assert_se(sd_json_dispatch(v
, table
, SD_JSON_LOG
, &foobar
) >= 0);
929 assert_se(foobar
.a
== UINT64_MAX
);
930 assert_se(foobar
.b
== UINT64_MAX
);
931 assert_se(foobar
.c
== INT64_MIN
);
932 assert_se(foobar
.d
== INT64_MIN
);
934 assert_se(foobar
.e
== UINT32_MAX
);
935 assert_se(foobar
.f
== UINT32_MAX
);
936 assert_se(foobar
.g
== INT32_MIN
);
937 assert_se(foobar
.h
== INT32_MIN
);
939 assert_se(foobar
.i
== UINT16_MAX
);
940 assert_se(foobar
.j
== UINT16_MAX
);
941 assert_se(foobar
.k
== INT16_MIN
);
942 assert_se(foobar
.l
== INT16_MIN
);
944 assert_se(foobar
.m
== UINT8_MAX
);
945 assert_se(foobar
.n
== UINT8_MAX
);
946 assert_se(foobar
.o
== INT8_MIN
);
947 assert_se(foobar
.p
== INT8_MIN
);
950 typedef enum mytestenum
{
951 myfoo
, mybar
, mybaz
, with_some_dashes
, _mymax
, _myinvalid
= -EINVAL
,
954 static const char *mytestenum_table
[_mymax
] = {
958 [with_some_dashes
] = "with-some-dashes",
961 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(mytestenum
, mytestenum
);
963 static JSON_DISPATCH_ENUM_DEFINE(dispatch_mytestenum
, mytestenum
, mytestenum_from_string
);
965 TEST(json_dispatch_enum_define
) {
968 mytestenum a
, b
, c
, d
, e
;
977 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*j
= NULL
;
979 assert_se(sd_json_buildo(&j
,
980 SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_STRING("mybaz")),
981 SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_STRING("mybar")),
982 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_STRING("myfoo")),
983 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_NULL
),
984 SD_JSON_BUILD_PAIR("e", JSON_BUILD_STRING_UNDERSCORIFY(mytestenum_to_string(with_some_dashes
)))) >= 0);
986 assert_se(sd_json_dispatch(j
,
987 (const sd_json_dispatch_field
[]) {
988 { "a", _SD_JSON_VARIANT_TYPE_INVALID
, dispatch_mytestenum
, offsetof(struct data
, a
), 0 },
989 { "b", _SD_JSON_VARIANT_TYPE_INVALID
, dispatch_mytestenum
, offsetof(struct data
, b
), 0 },
990 { "c", _SD_JSON_VARIANT_TYPE_INVALID
, dispatch_mytestenum
, offsetof(struct data
, c
), 0 },
991 { "d", _SD_JSON_VARIANT_TYPE_INVALID
, dispatch_mytestenum
, offsetof(struct data
, d
), 0 },
992 { "e", _SD_JSON_VARIANT_TYPE_INVALID
, dispatch_mytestenum
, offsetof(struct data
, e
), 0 },
998 assert(data
.a
== mybaz
);
999 assert(data
.b
== mybar
);
1000 assert(data
.c
== myfoo
);
1002 assert(data
.e
== with_some_dashes
);
1005 TEST(json_dispatch_double
) {
1007 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*j
= NULL
;
1009 assert_se(sd_json_build(&j
, SD_JSON_BUILD_OBJECT(
1010 SD_JSON_BUILD_PAIR("x1", SD_JSON_BUILD_REAL(0.5)),
1011 SD_JSON_BUILD_PAIR("x2", SD_JSON_BUILD_REAL(-0.5)),
1012 SD_JSON_BUILD_PAIR("x3", JSON_BUILD_CONST_STRING("infinity")),
1013 SD_JSON_BUILD_PAIR("x4", JSON_BUILD_CONST_STRING("-infinity")),
1014 SD_JSON_BUILD_PAIR("x5", JSON_BUILD_CONST_STRING("nan")),
1015 SD_JSON_BUILD_PAIR("x6", JSON_BUILD_CONST_STRING("inf")),
1016 SD_JSON_BUILD_PAIR("x7", JSON_BUILD_CONST_STRING("-inf")))) >= 0);
1019 double x1
, x2
, x3
, x4
, x5
, x6
, x7
;
1022 assert_se(sd_json_dispatch(j
,
1023 (const sd_json_dispatch_field
[]) {
1024 { "x1", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x1
), 0 },
1025 { "x2", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x2
), 0 },
1026 { "x3", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x3
), 0 },
1027 { "x4", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x4
), 0 },
1028 { "x5", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x5
), 0 },
1029 { "x6", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x6
), 0 },
1030 { "x7", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_double
, offsetof(struct data
, x7
), 0 },
1036 assert_se(fabs(data
.x1
- 0.5) < 0.01);
1037 assert_se(fabs(data
.x2
+ 0.5) < 0.01);
1038 assert_se(isinf(data
.x3
));
1039 assert_se(data
.x3
> 0);
1040 assert_se(isinf(data
.x4
));
1041 assert_se(data
.x4
< 0);
1042 assert_se(isnan(data
.x5
));
1043 assert_se(isinf(data
.x6
));
1044 assert_se(data
.x6
> 0);
1045 assert_se(isinf(data
.x7
));
1046 assert_se(data
.x7
< 0);
1049 TEST(json_sensitive
) {
1050 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*a
= NULL
, *b
= NULL
, *v
= NULL
;
1051 _cleanup_free_
char *s
= NULL
;
1054 assert_se(sd_json_build(&a
, SD_JSON_BUILD_STRV(STRV_MAKE("foo", "bar", "baz", "bar", "baz", "foo", "qux", "baz"))) >= 0);
1055 assert_se(sd_json_build(&b
, SD_JSON_BUILD_STRV(STRV_MAKE("foo", "bar", "baz", "qux"))) >= 0);
1057 sd_json_variant_sensitive(a
);
1059 assert_se(sd_json_variant_format(a
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
) >= 0);
1060 ASSERT_STREQ(s
, "\"<sensitive data>\"");
1063 r
= sd_json_variant_format(b
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
);
1066 assert_se((size_t) r
== strlen(s
));
1069 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1070 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1071 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1072 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
))) >= 0);
1073 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1075 r
= sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
);
1078 assert_se((size_t) r
== strlen(s
));
1080 v
= sd_json_variant_unref(v
);
1082 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1083 SD_JSON_BUILD_PAIR_VARIANT("b", b
),
1084 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1085 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1086 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
))) >= 0);
1087 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1089 r
= sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
);
1092 assert_se((size_t) r
== strlen(s
));
1094 v
= sd_json_variant_unref(v
);
1096 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1097 SD_JSON_BUILD_PAIR_VARIANT("b", b
),
1098 SD_JSON_BUILD_PAIR_VARIANT("a", a
),
1099 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1100 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1101 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
))) >= 0);
1102 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1104 assert_se(sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
) >= 0);
1105 ASSERT_STREQ(s
, "{\"b\":[\"foo\",\"bar\",\"baz\",\"qux\"],\"a\":\"<sensitive data>\",\"c\":-9223372036854775808,\"d\":\"-9223372036854775808\",\"e\":{}}");
1107 v
= sd_json_variant_unref(v
);
1109 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1110 SD_JSON_BUILD_PAIR_VARIANT("b", b
),
1111 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1112 SD_JSON_BUILD_PAIR_VARIANT("a", a
),
1113 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1114 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
))) >= 0);
1115 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1117 assert_se(sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
) >= 0);
1118 ASSERT_STREQ(s
, "{\"b\":[\"foo\",\"bar\",\"baz\",\"qux\"],\"c\":-9223372036854775808,\"a\":\"<sensitive data>\",\"d\":\"-9223372036854775808\",\"e\":{}}");
1120 v
= sd_json_variant_unref(v
);
1122 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1123 SD_JSON_BUILD_PAIR_VARIANT("b", b
),
1124 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1125 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1126 SD_JSON_BUILD_PAIR_VARIANT("a", a
),
1127 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
))) >= 0);
1128 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1130 assert_se(sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
) >= 0);
1131 ASSERT_STREQ(s
, "{\"b\":[\"foo\",\"bar\",\"baz\",\"qux\"],\"c\":-9223372036854775808,\"d\":\"-9223372036854775808\",\"a\":\"<sensitive data>\",\"e\":{}}");
1133 v
= sd_json_variant_unref(v
);
1135 assert_se(sd_json_build(&v
, SD_JSON_BUILD_OBJECT(
1136 SD_JSON_BUILD_PAIR_VARIANT("b", b
),
1137 SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(INT64_MIN
)),
1138 SD_JSON_BUILD_PAIR("d", SD_JSON_BUILD_STRING("-9223372036854775808")),
1139 SD_JSON_BUILD_PAIR("e", SD_JSON_BUILD_EMPTY_OBJECT
),
1140 SD_JSON_BUILD_PAIR_VARIANT("a", a
))) >= 0);
1141 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1143 assert_se(sd_json_variant_format(v
, SD_JSON_FORMAT_CENSOR_SENSITIVE
, &s
) >= 0);
1144 ASSERT_STREQ(s
, "{\"b\":[\"foo\",\"bar\",\"baz\",\"qux\"],\"c\":-9223372036854775808,\"d\":\"-9223372036854775808\",\"e\":{},\"a\":\"<sensitive data>\"}");
1148 struct iovec iov1
= CONST_IOVEC_MAKE_STRING("üxknürz"), iov2
= CONST_IOVEC_MAKE_STRING("wuffwuffmiau");
1150 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*j
= NULL
;
1151 assert_se(sd_json_build(&j
, SD_JSON_BUILD_OBJECT(
1152 SD_JSON_BUILD_PAIR("nr1", JSON_BUILD_IOVEC_BASE64(&iov1
)),
1153 SD_JSON_BUILD_PAIR("nr2", JSON_BUILD_IOVEC_HEX(&iov2
)))) >= 0);
1155 sd_json_variant_dump(j
, SD_JSON_FORMAT_PRETTY_AUTO
|SD_JSON_FORMAT_COLOR_AUTO
, /* f= */ NULL
, /* prefix= */ NULL
);
1157 _cleanup_(iovec_done
) struct iovec a
= {}, b
= {};
1158 assert_se(json_variant_unbase64_iovec(sd_json_variant_by_key(j
, "nr1"), &a
) >= 0);
1159 assert_se(json_variant_unhex_iovec(sd_json_variant_by_key(j
, "nr2"), &b
) >= 0);
1161 assert_se(iovec_memcmp(&iov1
, &a
) == 0);
1162 assert_se(iovec_memcmp(&iov2
, &b
) == 0);
1163 assert_se(iovec_memcmp(&iov2
, &a
) < 0);
1164 assert_se(iovec_memcmp(&iov1
, &b
) > 0);
1167 TEST(json_dispatch_nullable
) {
1169 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*j
= NULL
;
1171 assert_se(sd_json_build(&j
, SD_JSON_BUILD_OBJECT(
1172 SD_JSON_BUILD_PAIR("x1", JSON_BUILD_CONST_STRING("foo")),
1173 SD_JSON_BUILD_PAIR("x2", JSON_BUILD_CONST_STRING("bar")),
1174 SD_JSON_BUILD_PAIR("x3", JSON_BUILD_CONST_STRING("waldo")),
1175 SD_JSON_BUILD_PAIR("x4", JSON_BUILD_CONST_STRING("foo2")),
1176 SD_JSON_BUILD_PAIR("x5", JSON_BUILD_CONST_STRING("bar2")),
1177 SD_JSON_BUILD_PAIR("x6", JSON_BUILD_CONST_STRING("waldo2")),
1178 SD_JSON_BUILD_PAIR("x7", SD_JSON_BUILD_NULL
),
1179 SD_JSON_BUILD_PAIR("x8", SD_JSON_BUILD_NULL
),
1180 SD_JSON_BUILD_PAIR("x9", SD_JSON_BUILD_NULL
))) >= 0);
1183 const char *x1
, *x2
, *x3
, *x4
, *x5
, *x6
, *x7
, *x8
, *x9
;
1196 assert_se(sd_json_dispatch(j
,
1197 (const sd_json_dispatch_field
[]) {
1198 { "x1", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x1
), SD_JSON_NULLABLE
},
1199 { "x2", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x2
), SD_JSON_REFUSE_NULL
},
1200 { "x3", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x3
), 0 },
1201 { "x4", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x4
), SD_JSON_NULLABLE
},
1202 { "x5", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x5
), SD_JSON_REFUSE_NULL
},
1203 { "x6", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x6
), 0 },
1204 { "x7", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x7
), SD_JSON_NULLABLE
},
1205 { "x8", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x8
), 0 },
1206 { "x9", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x9
), SD_JSON_NULLABLE
},
1212 assert_se(streq_ptr(data
.x1
, "foo"));
1213 assert_se(streq_ptr(data
.x2
, "bar"));
1214 assert_se(streq_ptr(data
.x3
, "waldo"));
1215 assert_se(streq_ptr(data
.x4
, "foo2"));
1216 assert_se(streq_ptr(data
.x5
, "bar2"));
1217 assert_se(streq_ptr(data
.x6
, "waldo2"));
1218 assert_se(!data
.x7
);
1219 assert_se(!data
.x8
);
1220 assert_se(!data
.x9
);
1222 assert_se(sd_json_dispatch(j
,
1223 (const sd_json_dispatch_field
[]) {
1224 { "x7", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_const_string
, offsetof(struct data
, x7
), SD_JSON_REFUSE_NULL
},
1227 /* flags= */ SD_JSON_ALLOW_EXTENSIONS
,
1230 assert_se(sd_json_dispatch(j
,
1231 (const sd_json_dispatch_field
[]) {
1232 { "x7", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x7
), SD_JSON_REFUSE_NULL
},
1235 /* flags= */ SD_JSON_ALLOW_EXTENSIONS
,
1238 assert_se(sd_json_dispatch(j
,
1239 (const sd_json_dispatch_field
[]) {
1240 { "x7", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct data
, x7
), 0 },
1243 /* flags= */ SD_JSON_ALLOW_EXTENSIONS
,
1247 TEST(parse_continue
) {
1248 unsigned line
= 23, column
= 43;
1250 /* First try to parse with continue logic off, this should fail */
1251 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*x
= NULL
;
1252 assert_se(sd_json_parse_with_source("4711 512", "piff", /* flags= */ 0, &x
, &line
, &column
) == -EINVAL
);
1253 assert_se(line
== 1);
1254 assert_se(column
== 6);
1256 /* Then try to parse with continue logic on, which should yield two numbers */
1257 const char *p
= "4711 512";
1258 assert_se(sd_json_parse_with_source_continue(&p
, "piff", /* flags= */ 0, &x
, &line
, &column
) >= 0);
1259 assert_se(sd_json_variant_is_unsigned(x
));
1260 assert_se(sd_json_variant_unsigned(x
) == 4711);
1261 x
= sd_json_variant_unref(x
);
1263 assert_se(streq_ptr(p
, " 512"));
1264 assert_se(sd_json_parse_with_source_continue(&p
, "piff", /* flags= */ 0, &x
, &line
, &column
) >= 0);
1265 assert_se(sd_json_variant_is_unsigned(x
));
1266 assert_se(sd_json_variant_unsigned(x
) == 512);
1268 assert_se(isempty(p
));
1269 assert_se(sd_json_parse_with_source_continue(&p
, "piff", /* flags= */ 0, &x
, &line
, &column
) == -EINVAL
);
1273 _cleanup_(pidref_done
) PidRef myself
= PIDREF_NULL
, pid1
= PIDREF_NULL
;
1275 assert_se(pidref_set_pid(&myself
, 0) >= 0);
1276 assert_se(pidref_set_pid(&pid1
, 1) >= 0);
1278 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1279 sd_id128_t randomized_boot_id
;
1280 assert_se(sd_id128_randomize(&randomized_boot_id
) >= 0);
1281 assert_se(sd_json_buildo(&v
,
1282 JSON_BUILD_PAIR_PIDREF("myself", &myself
),
1283 JSON_BUILD_PAIR_PIDREF("pid1", &pid1
),
1284 SD_JSON_BUILD_PAIR("remote", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR_UNSIGNED("pid", 1),
1285 SD_JSON_BUILD_PAIR_UNSIGNED("pidfdId", 4711),
1286 SD_JSON_BUILD_PAIR_ID128("bootId", randomized_boot_id
))),
1287 SD_JSON_BUILD_PAIR("automatic", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR_UNSIGNED("pid", 0)))) >= 0);
1289 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1292 PidRef myself
, pid1
, remote
, automatic
;
1294 .myself
= PIDREF_NULL
,
1295 .pid1
= PIDREF_NULL
,
1296 .remote
= PIDREF_NULL
,
1297 .automatic
= PIDREF_NULL
,
1300 assert_se(sd_json_dispatch(
1302 (const sd_json_dispatch_field
[]) {
1303 { "myself", _SD_JSON_VARIANT_TYPE_INVALID
, json_dispatch_pidref
, voffsetof(data
, myself
), SD_JSON_STRICT
},
1304 { "pid1", _SD_JSON_VARIANT_TYPE_INVALID
, json_dispatch_pidref
, voffsetof(data
, pid1
), SD_JSON_STRICT
},
1305 { "remote", _SD_JSON_VARIANT_TYPE_INVALID
, json_dispatch_pidref
, voffsetof(data
, remote
), 0 },
1306 { "automatic", _SD_JSON_VARIANT_TYPE_INVALID
, json_dispatch_pidref
, voffsetof(data
, automatic
), SD_JSON_RELAX
},
1312 assert_se(pidref_equal(&myself
, &data
.myself
));
1313 assert_se(pidref_equal(&pid1
, &data
.pid1
));
1315 assert_se(!pidref_equal(&myself
, &data
.pid1
));
1316 assert_se(!pidref_equal(&pid1
, &data
.myself
));
1317 assert_se(!pidref_equal(&myself
, &data
.remote
));
1318 assert_se(!pidref_equal(&pid1
, &data
.remote
));
1320 assert_se((myself
.fd_id
> 0) == (data
.myself
.fd_id
> 0));
1321 assert_se((pid1
.fd_id
> 0) == (data
.pid1
.fd_id
> 0));
1323 assert_se(!pidref_is_set(&data
.automatic
));
1324 assert_se(pidref_is_automatic(&data
.automatic
));
1325 assert_se(pidref_is_set(&data
.remote
));
1326 assert_se(pidref_is_remote(&data
.remote
));
1328 pidref_done(&data
.myself
);
1329 pidref_done(&data
.pid1
);
1330 pidref_done(&data
.remote
);
1334 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1335 dev_t dev
= makedev(123, 456), parsed
;
1337 ASSERT_OK(json_variant_new_devnum(&v
, dev
));
1338 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1339 ASSERT_OK(json_dispatch_devnum("devnum", v
, /* flags= */ 0, &parsed
));
1340 ASSERT_EQ(major(parsed
), major(dev
));
1341 ASSERT_EQ(minor(parsed
), minor(dev
));
1342 v
= sd_json_variant_unref(v
);
1344 dev
= makedev(1 << 12, 456);
1345 ASSERT_OK(json_variant_new_devnum(&v
, dev
));
1346 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1347 ASSERT_FAIL(json_dispatch_devnum("devnum", v
, /* flags= */ 0, &parsed
));
1348 v
= sd_json_variant_unref(v
);
1350 dev
= makedev(123, 1 << 20);
1351 ASSERT_OK(json_variant_new_devnum(&v
, dev
));
1352 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1353 ASSERT_FAIL(json_dispatch_devnum("devnum", v
, /* flags= */ 0, &parsed
));
1357 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1358 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
1359 _cleanup_close_
int fd
= -EBADF
;
1362 ASSERT_OK(json_variant_new_fd_info(&v
, AT_FDCWD
));
1363 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1364 v
= sd_json_variant_unref(v
);
1366 ASSERT_OK_ERRNO(fd
= openat(AT_FDCWD
, ".", O_CLOEXEC
| O_DIRECTORY
| O_PATH
));
1367 ASSERT_OK(json_variant_new_fd_info(&v
, fd
));
1368 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1369 v
= sd_json_variant_unref(v
);
1370 fd
= safe_close(fd
);
1373 ASSERT_OK(fd
= open_tmpfile_unlinkable(NULL
, O_RDWR
));
1374 ASSERT_OK(json_variant_new_fd_info(&v
, fd
));
1375 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1376 v
= sd_json_variant_unref(v
);
1377 fd
= safe_close(fd
);
1379 fd
= open("/sys/class/net/lo/uevent", O_CLOEXEC
| O_PATH
);
1381 ASSERT_OK(json_variant_new_fd_info(&v
, fd
));
1382 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1383 v
= sd_json_variant_unref(v
);
1384 fd
= safe_close(fd
);
1388 fd
= open("/dev/sda", O_CLOEXEC
| O_PATH
);
1390 ASSERT_OK(json_variant_new_fd_info(&v
, fd
));
1391 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1392 v
= sd_json_variant_unref(v
);
1393 fd
= safe_close(fd
);
1397 ASSERT_OK(json_variant_new_fd_info(&v
, fileno(stdout
)));
1398 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1399 v
= sd_json_variant_unref(v
);
1402 ASSERT_OK_ERRNO(fd
= socket(AF_INET
, SOCK_DGRAM
, 0));
1403 ASSERT_OK(json_variant_new_fd_info(&v
, fd
));
1404 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1405 v
= sd_json_variant_unref(v
);
1406 fd
= safe_close(fd
);
1409 ASSERT_OK(pidref_set_pid(&pidref
, 0));
1410 if (pidref
.fd
>= 0) {
1411 ASSERT_OK(json_variant_new_fd_info(&v
, pidref
.fd
));
1412 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1413 v
= sd_json_variant_unref(v
);
1415 pidref_done(&pidref
);
1417 ASSERT_OK(pidref_set_pid(&pidref
, 1));
1418 if (pidref
.fd
>= 0) {
1419 ASSERT_OK(json_variant_new_fd_info(&v
, pidref
.fd
));
1420 ASSERT_OK(sd_json_variant_dump(v
, SD_JSON_FORMAT_PRETTY_AUTO
| SD_JSON_FORMAT_COLOR_AUTO
, NULL
, NULL
));
1421 v
= sd_json_variant_unref(v
);
1423 pidref_done(&pidref
);
1427 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1428 ASSERT_OK(sd_json_buildo(&v
,
1429 SD_JSON_BUILD_PAIR_STRING("plain", "myservice.service"),
1430 SD_JSON_BUILD_PAIR_STRING("instance", "myservice@instance1.service"),
1431 SD_JSON_BUILD_PAIR_STRING("template", "myservice@.service")));
1433 sd_json_variant_dump(v
, SD_JSON_FORMAT_COLOR
|SD_JSON_FORMAT_PRETTY
, NULL
, NULL
);
1436 const char *plain
, *instance
, *template;
1439 ASSERT_OK(sd_json_dispatch(
1441 (const sd_json_dispatch_field
[]) {
1442 { "plain", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, plain
), SD_JSON_STRICT
},
1443 { "instance", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, instance
), 0 },
1444 { "template", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, template), SD_JSON_RELAX
},
1450 ASSERT_STREQ(data
.plain
, "myservice.service");
1451 ASSERT_STREQ(data
.instance
, "myservice@instance1.service");
1452 ASSERT_STREQ(data
.template, "myservice@.service");
1454 ASSERT_ERROR(sd_json_dispatch(
1456 (const sd_json_dispatch_field
[]) {
1457 { "plain", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, plain
), SD_JSON_RELAX
},
1458 /* instance value is not allowed with SD_JSON_STRICT */
1459 { "instance", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, instance
), SD_JSON_STRICT
},
1460 { "template", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, template), SD_JSON_RELAX
},
1466 ASSERT_ERROR(sd_json_dispatch(
1468 (const sd_json_dispatch_field
[]) {
1469 { "plain", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, plain
), SD_JSON_RELAX
},
1470 { "instance", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, instance
), SD_JSON_RELAX
},
1471 /* template value is not allowed by default */
1472 { "template", SD_JSON_VARIANT_STRING
, json_dispatch_const_unit_name
, voffsetof(data
, template), 0 },
1479 DEFINE_TEST_MAIN(LOG_DEBUG
);