diff options
Diffstat (limited to 'tests/api/test-buffer.c')
| -rw-r--r-- | tests/api/test-buffer.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/tests/api/test-buffer.c b/tests/api/test-buffer.c new file mode 100644 index 000000000000..c17818ba3b4b --- /dev/null +++ b/tests/api/test-buffer.c @@ -0,0 +1,417 @@ +/* + * test-buffer.c + * Tests for libpkgconf buffer API. + * + * SPDX-License-Identifier: pkgconf + * + * Copyright (c) 2025 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" + +static void +test_buffer_empty(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0); + TEST_ASSERT_NULL(pkgconf_buffer_str(&buf)); + TEST_ASSERT_EMPTY_STRING(pkgconf_buffer_str_or_empty(&buf)); + TEST_ASSERT_EQ(pkgconf_buffer_lastc(&buf), '\0'); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_append(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, "hello")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello"); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 5); + + TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, " world")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello world"); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 11); + + TEST_ASSERT_EQ(pkgconf_buffer_lastc(&buf), 'd'); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_append_slice(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_TRUE(pkgconf_buffer_append_slice(&buf, "abcdefgh", 3)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc"); + + TEST_ASSERT_TRUE(pkgconf_buffer_append_slice(&buf, "xyz", 0)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc"); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_append_fmt(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_TRUE(pkgconf_buffer_append_fmt(&buf, "%s=%d", "x", 42)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "x=42"); + + TEST_ASSERT_TRUE(pkgconf_buffer_append_fmt(&buf, " %s", "ok")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "x=42 ok"); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_prepend(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&buf, "world"); + TEST_ASSERT_TRUE(pkgconf_buffer_prepend(&buf, "hello ")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello world"); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_push_byte(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'a')); + TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'b')); + TEST_ASSERT_TRUE(pkgconf_buffer_push_byte(&buf, 'c')); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "abc"); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 3); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_trim_byte(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&buf, "hello\n"); + TEST_ASSERT_TRUE(pkgconf_buffer_trim_byte(&buf)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "hello"); + + pkgconf_buffer_reset(&buf); + pkgconf_buffer_push_byte(&buf, 'x'); + TEST_ASSERT_TRUE(pkgconf_buffer_trim_byte(&buf)); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0); + TEST_ASSERT_FALSE(pkgconf_buffer_trim_byte(&buf)); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_reset(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&buf, "some content"); + TEST_ASSERT_NE(pkgconf_buffer_len(&buf), 0); + + pkgconf_buffer_reset(&buf); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0); + TEST_ASSERT_NULL(pkgconf_buffer_str(&buf)); + + TEST_ASSERT_TRUE(pkgconf_buffer_append(&buf, "fresh")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "fresh"); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_freeze(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&buf, "frozen"); + char *out = pkgconf_buffer_freeze(&buf); + TEST_ASSERT_NONNULL(out); + TEST_ASSERT_STRCMP_EQ(out, "frozen"); + TEST_ASSERT_EQ(pkgconf_buffer_len(&buf), 0); + + TEST_ASSERT_NULL(pkgconf_buffer_freeze(&buf)); + + free(out); + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_copy(void) +{ + pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&src, "original"); + pkgconf_buffer_append(&dst, "to be replaced"); + TEST_ASSERT_TRUE(pkgconf_buffer_copy(&src, &dst)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "original"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&src), "original"); // src is unchanged + + pkgconf_buffer_finalize(&src); + pkgconf_buffer_finalize(&dst); +} + +static void +test_buffer_join(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + + TEST_ASSERT_TRUE(pkgconf_buffer_join(&buf, '/', "usr", "local", "lib", NULL)); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&buf), "usr/local/lib"); + + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_contains(void) +{ + pkgconf_buffer_t hay = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t needle = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&hay, "the quick brown fox"); + + pkgconf_buffer_append(&needle, "quick"); + TEST_ASSERT_TRUE(pkgconf_buffer_contains(&hay, &needle)); + + pkgconf_buffer_reset(&needle); + pkgconf_buffer_append(&needle, "slow"); + TEST_ASSERT_FALSE(pkgconf_buffer_contains(&hay, &needle)); + + TEST_ASSERT_TRUE(pkgconf_buffer_contains_byte(&hay, 'q')); + TEST_ASSERT_FALSE(pkgconf_buffer_contains_byte(&hay, 'z')); + + pkgconf_buffer_finalize(&hay); + pkgconf_buffer_finalize(&needle); +} + +static void +test_buffer_match(void) +{ + pkgconf_buffer_t a = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t b = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&a, "identical"); + pkgconf_buffer_append(&b, "identical"); + TEST_ASSERT_TRUE(pkgconf_buffer_match(&a, &b)); + + // Identical length, but different contents + pkgconf_buffer_reset(&b); + pkgconf_buffer_append(&b, "different"); + TEST_ASSERT_FALSE(pkgconf_buffer_match(&a, &b)); + + // Different length and contents + pkgconf_buffer_reset(&b); + pkgconf_buffer_append(&b, "different!"); + TEST_ASSERT_FALSE(pkgconf_buffer_match(&a, &b)); + + pkgconf_buffer_finalize(&a); + pkgconf_buffer_finalize(&b); +} + +static void +test_buffer_has_prefix(void) +{ + pkgconf_buffer_t hay = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t pre = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&hay, "/usr/local/lib"); + + pkgconf_buffer_append(&pre, "/usr"); + TEST_ASSERT_TRUE(pkgconf_buffer_has_prefix(&hay, &pre)); + + pkgconf_buffer_reset(&pre); + pkgconf_buffer_append(&pre, "/opt"); + TEST_ASSERT_FALSE(pkgconf_buffer_has_prefix(&hay, &pre)); + + pkgconf_buffer_finalize(&hay); + pkgconf_buffer_finalize(&pre); +} + +static void +test_buffer_subst(void) +{ + pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&src, "prefix=${PREFIX}/share"); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst, &src, "${PREFIX}", "/opt/foo")); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "prefix=/opt/foo/share"); + + pkgconf_buffer_finalize(&src); + pkgconf_buffer_finalize(&dst); +} + +static void +test_buffer_subst_empty_pattern(void) +{ + pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst0 = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst1 = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst2 = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst3 = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst4 = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst5 = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_append(&src, "prefix=${PREFIX}/share"); + + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst0, &src, "", "foo")); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst1, &src, "", "")); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst2, &src, "", NULL)); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst3, &src, NULL, "foo")); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst4, &src, NULL, "")); + TEST_ASSERT_TRUE(pkgconf_buffer_subst(&dst5, &src, NULL, NULL)); + + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst0), "prefix=${PREFIX}/share"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst1), "prefix=${PREFIX}/share"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst2), "prefix=${PREFIX}/share"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst3), "prefix=${PREFIX}/share"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst4), "prefix=${PREFIX}/share"); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst5), "prefix=${PREFIX}/share"); + + pkgconf_buffer_finalize(&src); + pkgconf_buffer_finalize(&dst0); + pkgconf_buffer_finalize(&dst1); + pkgconf_buffer_finalize(&dst2); + pkgconf_buffer_finalize(&dst3); + pkgconf_buffer_finalize(&dst4); + pkgconf_buffer_finalize(&dst5); +} + +static void +test_buffer_escape(void) +{ + pkgconf_buffer_t src = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t dst = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_span_t spans[] = { + { ' ', ' ' }, + { '\t', '\t' }, + }; + + pkgconf_buffer_append(&src, "a b\tc"); + TEST_ASSERT_TRUE(pkgconf_buffer_escape(&dst, &src, spans, PKGCONF_ARRAY_SIZE(spans))); + TEST_ASSERT_STRCMP_EQ(pkgconf_buffer_str(&dst), "a\\ b\\\tc"); + + pkgconf_buffer_finalize(&src); + pkgconf_buffer_finalize(&dst); +} + +static void +test_str_eq_slice(void) +{ + TEST_ASSERT_TRUE(pkgconf_str_eq_slice("hello", "hello", 5)); + TEST_ASSERT_FALSE(pkgconf_str_eq_slice("hello!", "hello", 5)); + TEST_ASSERT_FALSE(pkgconf_str_eq_slice("hello", "world", 5)); + TEST_ASSERT_FALSE(pkgconf_str_eq_slice(NULL, "hello", 5)); +} + +static void +test_span_contains(void) +{ + pkgconf_span_t spans[] = { + { '0', '9' }, + { 'a', 'z' }, + }; + + TEST_ASSERT_TRUE(pkgconf_span_contains('5', spans, PKGCONF_ARRAY_SIZE(spans))); + TEST_ASSERT_TRUE(pkgconf_span_contains('m', spans, PKGCONF_ARRAY_SIZE(spans))); + TEST_ASSERT_FALSE(pkgconf_span_contains('A', spans, PKGCONF_ARRAY_SIZE(spans))); + TEST_ASSERT_FALSE(pkgconf_span_contains('!', spans, PKGCONF_ARRAY_SIZE(spans))); +} + +static void +test_buffer_fputs_nonempty(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + FILE *f = tmpfile(); + TEST_ASSERT_NONNULL(f); + + pkgconf_buffer_append(&buf, "hello world"); + TEST_ASSERT_TRUE(pkgconf_buffer_fputs(&buf, f)); + + char out[64]; + rewind(f); + size_t n = fread(out, 1, sizeof(out) - 1, f); + out[n] = '\0'; + + // Buffer contents followed by a newline. + TEST_ASSERT_STRCMP_EQ(out, "hello world\n"); + + fclose(f); + pkgconf_buffer_finalize(&buf); +} + +static void +test_buffer_fputs_empty(void) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + FILE *f = tmpfile(); + TEST_ASSERT_NONNULL(f); + + // An empty buffer writes only a newline. + TEST_ASSERT_TRUE(pkgconf_buffer_fputs(&buf, f)); + + char out[64]; + rewind(f); + size_t n = fread(out, 1, sizeof(out) - 1, f); + out[n] = '\0'; + + TEST_ASSERT_STRCMP_EQ(out, "\n"); + + fclose(f); + pkgconf_buffer_finalize(&buf); +} + +int +main(int argc, const char **argv) +{ + (void) argc; + + const char *basename = pkgconf_path_find_basename(argv[0]); + + TEST_RUN(basename, test_buffer_empty); + TEST_RUN(basename, test_buffer_append); + TEST_RUN(basename, test_buffer_append_slice); + TEST_RUN(basename, test_buffer_append_fmt); + TEST_RUN(basename, test_buffer_prepend); + TEST_RUN(basename, test_buffer_push_byte); + TEST_RUN(basename, test_buffer_trim_byte); + TEST_RUN(basename, test_buffer_reset); + TEST_RUN(basename, test_buffer_freeze); + TEST_RUN(basename, test_buffer_copy); + TEST_RUN(basename, test_buffer_join); + TEST_RUN(basename, test_buffer_contains); + TEST_RUN(basename, test_buffer_match); + TEST_RUN(basename, test_buffer_has_prefix); + TEST_RUN(basename, test_buffer_subst); + TEST_RUN(basename, test_buffer_subst_empty_pattern); + TEST_RUN(basename, test_buffer_escape); + TEST_RUN(basename, test_str_eq_slice); + TEST_RUN(basename, test_span_contains); + TEST_RUN(basename, test_buffer_fputs_nonempty); + TEST_RUN(basename, test_buffer_fputs_empty); + + return EXIT_SUCCESS; +} |
