test: add unit test for new sd-json functionality

This commit is contained in:
Lennart Poettering
2026-05-18 10:39:04 +01:00
committed by Luca Boccassi
parent 8c164074be
commit 914c41a774
+63
View File
@@ -13,6 +13,7 @@
#include "fd-util.h"
#include "format-util.h"
#include "fileio.h"
#include "io-util.h"
#include "iovec-util.h"
#include "json-internal.h"
#include "json-util.h"
@@ -518,6 +519,68 @@ TEST(source) {
printf("--- pretty end ---\n");
}
TEST(parse_fd) {
static const char data[] = "{ \"foo\" : \"bar\", \"baz\" : 4711 }";
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
_cleanup_close_ int fd = -EBADF;
ASSERT_OK(fd = open_tmpfile_unlinkable(NULL, O_RDWR));
ASSERT_OK(loop_write(fd, data, strlen(data)));
/* By default the fd is internally duplicated, the caller's fd stays open and the JSON text is
* read starting at the current file offset. */
ASSERT_OK_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK(sd_json_parse_fd("tmpfile", fd, /* flags= */ 0, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
ASSERT_OK(fd_validate(fd)); /* still open, we only got a duplicate */
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(v, "foo")), "bar");
ASSERT_EQ(sd_json_variant_unsigned(sd_json_variant_by_key(v, "baz")), UINT64_C(4711));
v = sd_json_variant_unref(v);
/* Without SD_JSON_PARSE_SEEK0 and with the offset left at EOF there is nothing to read. */
ASSERT_OK_ERRNO(lseek(fd, 0, SEEK_END));
ASSERT_ERROR(sd_json_parse_fd("tmpfile", fd, /* flags= */ 0, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL), ENODATA);
ASSERT_NULL(v);
ASSERT_OK(fd_validate(fd));
/* SD_JSON_PARSE_SEEK0 rewinds to the beginning first, so the stale offset no longer matters. */
ASSERT_OK(sd_json_parse_fd("tmpfile", fd, SD_JSON_PARSE_SEEK0, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
ASSERT_OK(fd_validate(fd));
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(v, "foo")), "bar");
v = sd_json_variant_unref(v);
/* SD_JSON_PARSE_REOPEN_FD reopens the fd internally (starting at offset 0), the caller's fd and
* its offset are left untouched. */
ASSERT_OK_ERRNO(lseek(fd, 0, SEEK_END));
ASSERT_OK(sd_json_parse_fd("tmpfile", fd, SD_JSON_PARSE_REOPEN_FD, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
ASSERT_OK(fd_validate(fd));
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(v, "foo")), "bar");
v = sd_json_variant_unref(v);
/* SD_JSON_PARSE_REOPEN_FD and SD_JSON_PARSE_DONATE_FD are mutually exclusive. */
ASSERT_RETURN_EXPECTED_SE(sd_json_parse_fd("tmpfile", fd, SD_JSON_PARSE_REOPEN_FD|SD_JSON_PARSE_DONATE_FD, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL) == -EINVAL);
ASSERT_OK(fd_validate(fd)); /* not consumed on the -EINVAL path */
/* SD_JSON_PARSE_DONATE_FD passes ownership into the call: the fd is consumed and closed even on
* success. */
ASSERT_OK_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK(sd_json_parse_fd("tmpfile", fd, SD_JSON_PARSE_DONATE_FD, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
ASSERT_ERROR(fd_validate(fd), EBADF);
TAKE_FD(fd); /* already closed by the call, don't double-close */
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(v, "foo")), "bar");
v = sd_json_variant_unref(v);
/* SD_JSON_PARSE_DONATE_FD also consumes the fd when parsing fails. */
_cleanup_close_ int fd2 = -EBADF;
ASSERT_OK(fd2 = open_tmpfile_unlinkable(NULL, O_RDWR));
ASSERT_OK(loop_write(fd2, "kookoo", strlen("kookoo")));
ASSERT_OK_ERRNO(lseek(fd2, 0, SEEK_SET));
ASSERT_ERROR(sd_json_parse_fd("tmpfile", fd2, SD_JSON_PARSE_DONATE_FD, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
ASSERT_ERROR(fd_validate(fd2), EBADF);
TAKE_FD(fd2);
ASSERT_NULL(v);
}
TEST(depth) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
int r;