aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/test/hl_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/test/hl_dir.c')
-rw-r--r--lib/sqfs/test/hl_dir.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/lib/sqfs/test/hl_dir.c b/lib/sqfs/test/hl_dir.c
new file mode 100644
index 0000000..4ff00e8
--- /dev/null
+++ b/lib/sqfs/test/hl_dir.c
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * hl_dir.c
+ *
+ * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "util/test.h"
+#include "sqfs/dir_entry.h"
+#include "sqfs/inode.h"
+#include "sqfs/io.h"
+#include "compat.h"
+
+typedef struct {
+ sqfs_dir_iterator_t obj;
+ size_t idx;
+} dummy_it_t;
+
+static const struct {
+ const char *name;
+ int dev;
+ int inum;
+} entries[] = {
+ { "foo", 1, 1 },
+ { "bar", 1, 2 },
+ { "baz", 1, 3 },
+ { "blub", 1, 2 },
+ { "a", 2, 2 },
+ { "b", 2, 1 },
+ { "c", 2, 2 },
+};
+
+static int dummy_read_link(sqfs_dir_iterator_t *it, char **out)
+{
+ (void)it; (void)out;
+ *out = NULL;
+ return 0;
+}
+
+static void dummy_ignore_subdir(sqfs_dir_iterator_t *it)
+{
+ (void)it;
+ TEST_ASSERT(0);
+}
+
+static int dummy_open_file_ro(sqfs_dir_iterator_t *it, sqfs_istream_t **out)
+{
+ (void)it; (void)out;
+ TEST_ASSERT(0);
+ return 0;
+}
+
+static int dummy_read_xattr(sqfs_dir_iterator_t *it, sqfs_xattr_t **out)
+{
+ (void)it; (void)out;
+ TEST_ASSERT(0);
+ return 0;
+}
+
+static int dummy_open_subdir(sqfs_dir_iterator_t *base,
+ sqfs_dir_iterator_t **out)
+{
+ (void)base; (void)out;
+ TEST_ASSERT(0);
+ return 0;
+}
+
+static int dummy_next(sqfs_dir_iterator_t *base, sqfs_dir_entry_t **out)
+{
+ dummy_it_t *it = (dummy_it_t *)base;
+ const char *name;
+ int inum, dev;
+
+ if (it->idx >= (sizeof(entries) / sizeof(entries[0])))
+ return 1;
+
+ name = entries[it->idx].name;
+ inum = entries[it->idx].inum;
+ dev = entries[it->idx].dev;
+ it->idx += 1;
+
+ *out = sqfs_dir_entry_create(name, SQFS_INODE_MODE_REG | 0644, 0);
+ TEST_NOT_NULL(*out);
+ (*out)->inode = inum;
+ (*out)->dev = dev;
+ return 0;
+}
+
+static void dummy_destroy(sqfs_object_t *obj)
+{
+ free(obj);
+}
+
+static sqfs_dir_iterator_t *mkdummyit(void)
+{
+ dummy_it_t *it = calloc(1, sizeof(*it));
+ TEST_NOT_NULL(it);
+
+ sqfs_object_init(it, dummy_destroy, NULL);
+ ((sqfs_dir_iterator_t *)it)->read_link = dummy_read_link;
+ ((sqfs_dir_iterator_t *)it)->ignore_subdir = dummy_ignore_subdir;
+ ((sqfs_dir_iterator_t *)it)->open_file_ro = dummy_open_file_ro;
+ ((sqfs_dir_iterator_t *)it)->read_xattr = dummy_read_xattr;
+ ((sqfs_dir_iterator_t *)it)->next = dummy_next;
+ ((sqfs_dir_iterator_t *)it)->open_subdir = dummy_open_subdir;
+ return (sqfs_dir_iterator_t *)it;
+}
+
+int main(int argc, char **argv)
+{
+ sqfs_dir_iterator_t *base, *it;
+ sqfs_dir_entry_t *ent;
+ char *target;
+ int ret;
+ (void)argc; (void)argv;
+
+ base = mkdummyit();
+ TEST_NOT_NULL(base);
+
+ ret = sqfs_hard_link_filter_create(&it, base);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(it);
+ TEST_EQUAL_UI(((sqfs_object_t *)base)->refcount, 2);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "foo");
+ TEST_ASSERT(S_ISREG(ent->mode));
+ TEST_EQUAL_UI(ent->flags, 0);
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NULL(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "bar");
+ TEST_ASSERT(S_ISREG(ent->mode));
+ TEST_EQUAL_UI(ent->flags, 0);
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NULL(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "baz");
+ TEST_ASSERT(S_ISREG(ent->mode));
+ TEST_EQUAL_UI(ent->flags, 0);
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NULL(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "blub");
+ TEST_EQUAL_UI(ent->flags, SQFS_DIR_ENTRY_FLAG_HARD_LINK);
+ TEST_ASSERT(S_ISLNK(ent->mode));
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(target);
+ TEST_STR_EQUAL(target, "bar");
+ free(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "a");
+ TEST_ASSERT(S_ISREG(ent->mode));
+ TEST_EQUAL_UI(ent->flags, 0);
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NULL(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "b");
+ TEST_ASSERT(S_ISREG(ent->mode));
+ TEST_EQUAL_UI(ent->flags, 0);
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NULL(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(&ent);
+ TEST_STR_EQUAL(ent->name, "c");
+ TEST_EQUAL_UI(ent->flags, SQFS_DIR_ENTRY_FLAG_HARD_LINK);
+ TEST_ASSERT(S_ISLNK(ent->mode));
+ ret = it->read_link(it, &target);
+ TEST_EQUAL_I(ret, 0);
+ TEST_NOT_NULL(target);
+ TEST_STR_EQUAL(target, "a");
+ free(target);
+ free(ent);
+
+ ret = it->next(it, &ent);
+ TEST_EQUAL_I(ret, 1);
+ TEST_NULL(ent);
+ it = sqfs_drop(it);
+
+ TEST_EQUAL_UI(((sqfs_object_t *)base)->refcount, 1);
+ base = sqfs_drop(base);
+ return EXIT_SUCCESS;
+}