Files

194 lines
4.8 KiB
C
Raw Permalink Normal View History

2026-04-30 22:15:47 -05:00
// SPDX-License-Identifier: BSD-3-Clause
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <cmocka.h>
#include "pathbuf.h"
static void init_path(struct pathbuf *path, const char *s, bool set_len)
{
size_t len = strlen(s);
assert_true(len < sizeof(path->buf));
memcpy(path->buf, s, len + 1);
path->len = set_len ? len : 0;
}
static void assert_dirname(const char *in, const char *out, bool set_len)
{
struct pathbuf path;
init_path(&path, in, set_len);
qdl_pathbuf_dirname(&path);
assert_string_equal(path.buf, out);
assert_int_equal(path.len, strlen(out));
}
static void test_dirname_posix_root(void **state)
{
(void)state;
assert_dirname("/", "/", true);
assert_dirname("/", "/", false);
}
static void test_dirname_posix_absolute(void **state)
{
(void)state;
assert_dirname("/foo", "/", true);
assert_dirname("/foo/bar", "/foo", true);
assert_dirname("/foo/bar/", "/foo", true);
}
static void test_dirname_relative(void **state)
{
(void)state;
assert_dirname("foo", "foo", true);
assert_dirname("foo/bar", "foo", true);
assert_dirname("foo/bar/", "foo", true);
}
static void test_reset_and_dup(void **state)
{
struct pathbuf src;
struct pathbuf dst;
(void)state;
init_path(&src, "/tmp/example", true);
qdl_pathbuf_dup(&dst, &src);
assert_string_equal(dst.buf, src.buf);
assert_int_equal(dst.len, src.len);
qdl_pathbuf_reset(&dst);
assert_string_equal(dst.buf, "");
assert_int_equal(dst.len, 0);
qdl_pathbuf_reset(NULL);
}
static void test_push_basic_behavior(void **state)
{
struct pathbuf path = {0};
int ret;
(void)state;
ret = qdl_pathbuf_push(&path, "foo");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo");
assert_int_equal(path.len, strlen("foo"));
ret = qdl_pathbuf_push(&path, "bar");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo/bar");
assert_int_equal(path.len, strlen("foo/bar"));
ret = qdl_pathbuf_push(&path, "");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo/bar");
assert_int_equal(path.len, strlen("foo/bar"));
ret = qdl_pathbuf_push(&path, "./baz");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo/bar/baz");
assert_int_equal(path.len, strlen("foo/bar/baz"));
#ifdef _WIN32
2026-05-16 14:32:08 -05:00
ret = qdl_pathbuf_push(&path, ".\\qux");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo/bar/baz/qux");
assert_int_equal(path.len, strlen("foo/bar/baz/qux"));
ret = qdl_pathbuf_push(&path, "nested\\leaf");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "foo/bar/baz/qux/nested/leaf");
assert_int_equal(path.len, strlen("foo/bar/baz/qux/nested/leaf"));
2026-04-30 22:15:47 -05:00
ret = qdl_pathbuf_push(&path, "C:/abs");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "C:/abs");
assert_int_equal(path.len, strlen("C:/abs"));
#else
ret = qdl_pathbuf_push(&path, "/abs");
assert_int_equal(ret, 0);
assert_string_equal(path.buf, "/abs");
assert_int_equal(path.len, strlen("/abs"));
#endif
}
static void test_push_invalid_args(void **state)
{
struct pathbuf path = {0};
(void)state;
assert_int_equal(qdl_pathbuf_push(NULL, "foo"), -EINVAL);
assert_int_equal(qdl_pathbuf_push(&path, NULL), -EINVAL);
}
static void test_push_overflow_keeps_state(void **state)
{
struct pathbuf path = {0};
char before[PATH_MAX];
size_t max_prefix_len;
int ret;
(void)state;
max_prefix_len = sizeof(path.buf) - 1;
memset(path.buf, 'a', max_prefix_len);
path.buf[max_prefix_len] = '\0';
path.len = max_prefix_len;
memcpy(before, path.buf, sizeof(before));
ret = qdl_pathbuf_push(&path, "b");
assert_int_equal(ret, -ENAMETOOLONG);
assert_string_equal(path.buf, before);
assert_int_equal(path.len, max_prefix_len);
}
#ifdef _WIN32
static void test_dirname_windows_drive(void **state)
{
(void)state;
assert_dirname("C:\\", "C:\\", true);
assert_dirname("C:\\foo", "C:\\", true);
assert_dirname("C:\\foo\\bar", "C:\\foo", true);
assert_dirname("C:/foo/bar", "C:/foo", true);
}
static void test_dirname_windows_unc(void **state)
{
(void)state;
assert_dirname("\\\\server\\share", "\\\\server\\share", true);
assert_dirname("\\\\server\\share\\dir", "\\\\server\\share", true);
assert_dirname("\\\\server\\share\\dir\\sub", "\\\\server\\share\\dir", true);
}
#endif
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_dirname_posix_root),
cmocka_unit_test(test_dirname_posix_absolute),
cmocka_unit_test(test_dirname_relative),
cmocka_unit_test(test_reset_and_dup),
cmocka_unit_test(test_push_basic_behavior),
cmocka_unit_test(test_push_invalid_args),
cmocka_unit_test(test_push_overflow_keeps_state),
#ifdef _WIN32
cmocka_unit_test(test_dirname_windows_drive),
cmocka_unit_test(test_dirname_windows_unc),
#endif
};
return cmocka_run_group_tests(tests, NULL, NULL);
}