diff options
Diffstat (limited to 'lib')
75 files changed, 5295 insertions, 0 deletions
diff --git a/lib/fstree/Makemodule.am b/lib/fstree/Makemodule.am index f740527..e2d2ae7 100644 --- a/lib/fstree/Makemodule.am +++ b/lib/fstree/Makemodule.am @@ -4,3 +4,39 @@ libfstree_a_SOURCES = include/fstree.h lib/fstree/src/fstree.c \ lib/fstree/src/add_by_path.c lib/fstree/src/get_by_path.c noinst_LIBRARIES += libfstree.a + +test_mknode_simple_SOURCES = lib/fstree/test/mknode_simple.c +test_mknode_simple_LDADD = libfstree.a libcompat.a + +test_mknode_slink_SOURCES = lib/fstree/test/mknode_slink.c +test_mknode_slink_LDADD = libfstree.a libcompat.a + +test_mknode_reg_SOURCES = lib/fstree/test/mknode_reg.c +test_mknode_reg_LDADD = libfstree.a libcompat.a + +test_mknode_dir_SOURCES = lib/fstree/test/mknode_dir.c +test_mknode_dir_LDADD = libfstree.a libcompat.a + +test_gen_inode_numbers_SOURCES = lib/fstree/test/gen_inode_numbers.c +test_gen_inode_numbers_LDADD = libfstree.a libutil.a libcompat.a + +test_add_by_path_SOURCES = lib/fstree/test/add_by_path.c +test_add_by_path_LDADD = libfstree.a libutil.a libcompat.a + +test_get_path_SOURCES = lib/fstree/test/get_path.c +test_get_path_LDADD = libfstree.a libutil.a libcompat.a + +test_fstree_sort_SOURCES = lib/fstree/test/fstree_sort.c +test_fstree_sort_LDADD = libfstree.a libio.a libutil.a libcompat.a + +test_fstree_init_SOURCES = lib/fstree/test/fstree_init.c +test_fstree_init_LDADD = libfstree.a libio.a libutil.a libcompat.a + +FSTREE_TESTS = \ + test_mknode_simple test_mknode_slink \ + test_mknode_reg test_mknode_dir test_gen_inode_numbers \ + test_add_by_path test_get_path test_fstree_sort \ + test_fstree_init + +check_PROGRAMS += $(FSTREE_TESTS) +TESTS += $(FSTREE_TESTS) diff --git a/lib/fstree/test/add_by_path.c b/lib/fstree/test/add_by_path.c new file mode 100644 index 0000000..97e5a60 --- /dev/null +++ b/lib/fstree/test/add_by_path.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * add_by_path.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *a, *b; + struct stat sb; + fstree_t fs; + char *opts; + (void)argc; (void)argv; + + opts = strdup("mode=0755,uid=21,gid=42"); + TEST_ASSERT(fstree_init(&fs, opts) == 0); + free(opts); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0750; + sb.st_uid = 1000; + sb.st_gid = 100; + + TEST_EQUAL_UI(fs.root->link_count, 2); + + a = fstree_add_generic(&fs, "dir", &sb, NULL); + TEST_NOT_NULL(a); + TEST_STR_EQUAL(a->name, "dir"); + TEST_EQUAL_UI(a->mode, sb.st_mode); + TEST_EQUAL_UI(a->uid, sb.st_uid); + TEST_EQUAL_UI(a->gid, sb.st_gid); + TEST_ASSERT(a->parent == fs.root); + TEST_EQUAL_UI(a->link_count, 2); + TEST_NULL(a->next); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_EQUAL_UI(fs.root->link_count, 3); + TEST_ASSERT(!a->data.dir.created_implicitly); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFBLK | 0640; + sb.st_rdev = 1234; + + b = fstree_add_generic(&fs, "blkdev", &sb, NULL); + TEST_NOT_NULL(b); + TEST_ASSERT(b != a); + TEST_STR_EQUAL(b->name, "blkdev"); + TEST_EQUAL_UI(b->mode, sb.st_mode); + TEST_EQUAL_UI(b->uid, sb.st_uid); + TEST_EQUAL_UI(b->gid, sb.st_gid); + TEST_ASSERT(b->parent == fs.root); + TEST_EQUAL_UI(b->link_count, 1); + TEST_EQUAL_UI(b->data.devno, sb.st_rdev); + TEST_ASSERT(b->next == a); + TEST_EQUAL_UI(fs.root->link_count, 4); + TEST_ASSERT(fs.root->data.dir.children == b); + + TEST_NULL(fstree_add_generic(&fs, "blkdev/foo", &sb, NULL)); + TEST_EQUAL_UI(errno, ENOTDIR); + + TEST_NULL(fstree_add_generic(&fs, "dir", &sb, NULL)); + TEST_EQUAL_UI(errno, EEXIST); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0755; + TEST_NULL(fstree_add_generic(&fs, "dir", &sb, NULL)); + TEST_EQUAL_UI(errno, EEXIST); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFCHR | 0444; + b = fstree_add_generic(&fs, "dir/chrdev", &sb, NULL); + TEST_NOT_NULL(b); + TEST_EQUAL_UI(b->mode, sb.st_mode); + TEST_EQUAL_UI(b->uid, sb.st_uid); + TEST_EQUAL_UI(b->gid, sb.st_gid); + TEST_EQUAL_UI(b->link_count, 1); + TEST_ASSERT(b->parent == a); + TEST_EQUAL_UI(b->data.devno, sb.st_rdev); + TEST_NULL(b->next); + TEST_ASSERT(a->data.dir.children == b); + + TEST_EQUAL_UI(a->link_count, 3); + TEST_EQUAL_UI(fs.root->link_count, 4); + + b = fstree_add_generic(&fs, "dir/foo/chrdev", &sb, NULL); + TEST_NOT_NULL(b); + TEST_NULL(b->next); + TEST_EQUAL_UI(b->mode, sb.st_mode); + TEST_EQUAL_UI(b->uid, sb.st_uid); + TEST_EQUAL_UI(b->gid, sb.st_gid); + TEST_EQUAL_UI(b->link_count, 1); + TEST_ASSERT(b->parent != a); + TEST_ASSERT(b->parent->parent == a); + TEST_EQUAL_UI(b->data.devno, sb.st_rdev); + TEST_NULL(b->next); + + TEST_EQUAL_UI(a->link_count, 4); + TEST_EQUAL_UI(fs.root->link_count, 4); + TEST_ASSERT(a->data.dir.children != b); + + b = b->parent; + TEST_ASSERT(b->data.dir.created_implicitly); + TEST_EQUAL_UI(b->mode, S_IFDIR | 0755); + TEST_EQUAL_UI(b->uid, 21); + TEST_EQUAL_UI(b->gid, 42); + TEST_EQUAL_UI(b->link_count, 3); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0750; + sb.st_uid = 1000; + sb.st_gid = 100; + + a = fstree_add_generic(&fs, "dir/foo", &sb, NULL); + TEST_NOT_NULL(a); + TEST_ASSERT(a == b); + TEST_ASSERT(!a->data.dir.created_implicitly); + TEST_EQUAL_UI(a->mode, sb.st_mode); + TEST_EQUAL_UI(a->uid, sb.st_uid); + TEST_EQUAL_UI(a->gid, sb.st_gid); + TEST_EQUAL_UI(a->link_count, 3); + + TEST_EQUAL_UI(a->parent->link_count, 4); + TEST_EQUAL_UI(fs.root->link_count, 4); + + TEST_NULL(fstree_add_generic(&fs, "dir/foo", &sb, NULL)); + TEST_EQUAL_UI(errno, EEXIST); + + fstree_cleanup(&fs); + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/fstree_init.c b/lib/fstree/test/fstree_init.c new file mode 100644 index 0000000..186f25b --- /dev/null +++ b/lib/fstree/test/fstree_init.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * fstree_init.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" +#include "util/util.h" + +int main(int argc, char **argv) +{ + fstree_t fs; + char *str; + (void)argc; (void)argv; + + str = strdup("mtime=1337,uid=1000,gid=100,mode=0321"); + TEST_NOT_NULL(str); + TEST_ASSERT(fstree_init(&fs, str) == 0); + free(str); + TEST_EQUAL_UI(fs.defaults.st_mtime, 1337); + TEST_EQUAL_UI(fs.defaults.st_uid, 1000); + TEST_EQUAL_UI(fs.defaults.st_gid, 100); + TEST_EQUAL_UI(fs.defaults.st_mode, S_IFDIR | 0321); + fstree_cleanup(&fs); + + TEST_ASSERT(fstree_init(&fs, NULL) == 0); + if (fs.defaults.st_mtime != 0) { + TEST_EQUAL_UI(fs.defaults.st_mtime, get_source_date_epoch()); + } + TEST_EQUAL_UI(fs.defaults.st_uid, 0); + TEST_EQUAL_UI(fs.defaults.st_gid, 0); + TEST_EQUAL_UI(fs.defaults.st_mode, S_IFDIR | 0755); + fstree_cleanup(&fs); + + str = strdup("mode=07777"); + TEST_NOT_NULL(str); + TEST_ASSERT(fstree_init(&fs, str) == 0); + free(str); + fstree_cleanup(&fs); + + str = strdup("mode=017777"); + TEST_NOT_NULL(str); + TEST_ASSERT(fstree_init(&fs, str) != 0); + free(str); + + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/fstree_sort.c b/lib/fstree/test/fstree_sort.c new file mode 100644 index 0000000..7df85f5 --- /dev/null +++ b/lib/fstree/test/fstree_sort.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * fstree_sort.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *a, *b, *c, *d; + struct stat sb; + fstree_t fs; + int ret; + (void)argc; (void)argv; + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFBLK | 0600; + sb.st_rdev = 1337; + + /* in order */ + ret = fstree_init(&fs, NULL); + TEST_EQUAL_I(ret, 0); + + a = fstree_mknode(fs.root, "a", 1, NULL, &sb); + TEST_NOT_NULL(a); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_NULL(a->next); + + b = fstree_mknode(fs.root, "b", 1, NULL, &sb); + TEST_NOT_NULL(a); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_ASSERT(a->next == b); + TEST_NULL(b->next); + + c = fstree_mknode(fs.root, "c", 1, NULL, &sb); + TEST_NOT_NULL(c); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_ASSERT(a->next == b); + TEST_ASSERT(b->next == c); + TEST_NULL(c->next); + + d = fstree_mknode(fs.root, "d", 1, NULL, &sb); + TEST_NOT_NULL(d); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_ASSERT(a->next == b); + TEST_ASSERT(b->next == c); + TEST_ASSERT(c->next == d); + TEST_NULL(d->next); + + fstree_cleanup(&fs); + + /* out-of-order */ + ret = fstree_init(&fs, NULL); + TEST_EQUAL_I(ret, 0); + + d = fstree_mknode(fs.root, "d", 1, NULL, &sb); + TEST_NOT_NULL(d); + TEST_ASSERT(fs.root->data.dir.children == d); + TEST_NULL(d->next); + + c = fstree_mknode(fs.root, "c", 1, NULL, &sb); + TEST_NOT_NULL(c); + TEST_ASSERT(fs.root->data.dir.children == c); + TEST_ASSERT(c->next == d); + TEST_NULL(d->next); + + b = fstree_mknode(fs.root, "b", 1, NULL, &sb); + TEST_NOT_NULL(b); + TEST_ASSERT(fs.root->data.dir.children == b); + TEST_ASSERT(b->next == c); + TEST_ASSERT(c->next == d); + TEST_NULL(d->next); + + a = fstree_mknode(fs.root, "a", 1, NULL, &sb); + TEST_NOT_NULL(a); + TEST_ASSERT(fs.root->data.dir.children == a); + TEST_ASSERT(a->next == b); + TEST_ASSERT(b->next == c); + TEST_ASSERT(c->next == d); + TEST_NULL(d->next); + + fstree_cleanup(&fs); + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/gen_inode_numbers.c b/lib/fstree/test/gen_inode_numbers.c new file mode 100644 index 0000000..5403580 --- /dev/null +++ b/lib/fstree/test/gen_inode_numbers.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * gen_inode_table.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +static tree_node_t *gen_node(tree_node_t *parent, const char *name) +{ + struct stat sb; + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0755; + + return fstree_mknode(parent, name, strlen(name), NULL, &sb); +} + +static void check_children_before_root(tree_node_t *root) +{ + tree_node_t *n; + + for (n = root->data.dir.children; n != NULL; n = n->next) + TEST_LESS_THAN_UI(n->inode_num, root->inode_num); + + for (n = root->data.dir.children; n != NULL; n = n->next) + check_children_before_root(n); +} + +static void check_children_continuous(tree_node_t *root) +{ + tree_node_t *n; + + for (n = root->data.dir.children; n != NULL; n = n->next) { + if (n->next != NULL) { + TEST_EQUAL_UI(n->next->inode_num, (n->inode_num + 1)); + } + } + + for (n = root->data.dir.children; n != NULL; n = n->next) + check_children_continuous(n); +} + +int main(int argc, char **argv) +{ + tree_node_t *a, *b, *c; + fstree_t fs; + (void)argc; (void)argv; + + // inode table for the empty tree + TEST_ASSERT(fstree_init(&fs, NULL) == 0); + fstree_post_process(&fs); + TEST_EQUAL_UI(fs.unique_inode_count, 1); + TEST_EQUAL_UI(fs.root->inode_num, 1); + fstree_cleanup(&fs); + + // tree with 2 levels under root, fan out 3 + TEST_ASSERT(fstree_init(&fs, NULL) == 0); + + a = gen_node(fs.root, "a"); + b = gen_node(fs.root, "b"); + c = gen_node(fs.root, "c"); + TEST_NOT_NULL(a); + TEST_NOT_NULL(b); + TEST_NOT_NULL(c); + + TEST_NOT_NULL(gen_node(a, "a_a")); + TEST_NOT_NULL(gen_node(a, "a_b")); + TEST_NOT_NULL(gen_node(a, "a_c")); + + TEST_NOT_NULL(gen_node(b, "b_a")); + TEST_NOT_NULL(gen_node(b, "b_b")); + TEST_NOT_NULL(gen_node(b, "b_c")); + + TEST_NOT_NULL(gen_node(c, "c_a")); + TEST_NOT_NULL(gen_node(c, "c_b")); + TEST_NOT_NULL(gen_node(c, "c_c")); + + fstree_post_process(&fs); + TEST_EQUAL_UI(fs.unique_inode_count, 13); + + check_children_before_root(fs.root); + check_children_continuous(fs.root); + + fstree_cleanup(&fs); + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/get_path.c b/lib/fstree/test/get_path.c new file mode 100644 index 0000000..61001e9 --- /dev/null +++ b/lib/fstree/test/get_path.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * get_path.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *a, *b, *c, *d; + struct stat sb; + fstree_t fs; + char *str; + (void)argc; (void)argv; + + TEST_ASSERT(fstree_init(&fs, NULL) == 0); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0750; + sb.st_uid = 1000; + sb.st_gid = 100; + + a = fstree_add_generic(&fs, "foo", &sb, NULL); + b = fstree_add_generic(&fs, "foo/bar", &sb, NULL); + c = fstree_add_generic(&fs, "foo/bar/baz", &sb, NULL); + d = fstree_add_generic(&fs, "foo/bar/baz/dir", &sb, NULL); + + str = fstree_get_path(fs.root); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/"); + free(str); + + str = fstree_get_path(a); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/foo"); + free(str); + + str = fstree_get_path(b); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/foo/bar"); + free(str); + + str = fstree_get_path(c); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/foo/bar/baz"); + free(str); + + str = fstree_get_path(d); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/foo/bar/baz/dir"); + free(str); + + fstree_cleanup(&fs); + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/mknode_dir.c b/lib/fstree/test/mknode_dir.c new file mode 100644 index 0000000..dd7eba7 --- /dev/null +++ b/lib/fstree/test/mknode_dir.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * mknode_dir.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *root, *a, *b; + struct stat sb; + fstree_t fs; + (void)argc; (void)argv; + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFDIR | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 4096; + + root = fstree_mknode(NULL, "rootdir", 7, NULL, &sb); + TEST_EQUAL_UI(root->uid, sb.st_uid); + TEST_EQUAL_UI(root->gid, sb.st_gid); + TEST_EQUAL_UI(root->mode, sb.st_mode); + TEST_EQUAL_UI(root->link_count, 2); + TEST_ASSERT(root->name >= (char *)root->payload); + TEST_STR_EQUAL(root->name, "rootdir"); + TEST_NULL(root->data.dir.children); + TEST_NULL(root->parent); + TEST_NULL(root->next); + + a = fstree_mknode(root, "adir", 4, NULL, &sb); + TEST_ASSERT(a->parent == root); + TEST_NULL(a->next); + TEST_EQUAL_UI(a->link_count, 2); + TEST_EQUAL_UI(root->link_count, 3); + TEST_ASSERT(root->data.dir.children == a); + TEST_NULL(root->parent); + TEST_NULL(root->next); + + b = fstree_mknode(root, "bdir", 4, NULL, &sb); + TEST_ASSERT(a->parent == root); + TEST_ASSERT(b->parent == root); + TEST_EQUAL_UI(b->link_count, 2); + TEST_ASSERT(root->data.dir.children == a); + TEST_ASSERT(a->next == b); + TEST_EQUAL_UI(root->link_count, 4); + TEST_NULL(b->next); + TEST_NULL(root->parent); + TEST_NULL(root->next); + + free(root); + free(a); + free(b); + + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/mknode_reg.c b/lib/fstree/test/mknode_reg.c new file mode 100644 index 0000000..368720f --- /dev/null +++ b/lib/fstree/test/mknode_reg.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * mknode_reg.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *node; + struct stat sb; + fstree_t fs; + (void)argc; (void)argv; + + memset(&fs, 0, sizeof(fs)); + + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFREG | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 4096; + + node = fstree_mknode(NULL, "filename", 8, "input", &sb); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, sb.st_mode); + TEST_NULL(node->parent); + TEST_EQUAL_UI(node->link_count, 1); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_ASSERT(node->data.file.input_file >= (char *)node->payload); + TEST_ASSERT(node->data.file.input_file >= node->name + 8); + TEST_STR_EQUAL(node->name, "filename"); + TEST_STR_EQUAL(node->data.file.input_file, "input"); + free(node); + + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/mknode_simple.c b/lib/fstree/test/mknode_simple.c new file mode 100644 index 0000000..c7efb49 --- /dev/null +++ b/lib/fstree/test/mknode_simple.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * mknode_simple.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *node; + struct stat sb; + fstree_t fs; + (void)argc; (void)argv; + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFSOCK | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 1337; + + node = fstree_mknode(NULL, "sockfile", 8, NULL, &sb); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_STR_EQUAL(node->name, "sockfile"); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, sb.st_mode); + TEST_EQUAL_UI(node->link_count, 1); + TEST_NULL(node->parent); + TEST_NULL(node->data.target); + TEST_EQUAL_UI(node->data.devno, 0); + free(node); + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFIFO | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 1337; + + node = fstree_mknode(NULL, "fifo", 4, NULL, &sb); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_STR_EQUAL(node->name, "fifo"); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, sb.st_mode); + TEST_EQUAL_UI(node->link_count, 1); + TEST_NULL(node->parent); + TEST_NULL(node->data.target); + TEST_EQUAL_UI(node->data.devno, 0); + free(node); + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFBLK | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 1337; + + node = fstree_mknode(NULL, "blkdev", 6, NULL, &sb); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_STR_EQUAL(node->name, "blkdev"); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, sb.st_mode); + TEST_EQUAL_UI(node->link_count, 1); + TEST_EQUAL_UI(node->data.devno, sb.st_rdev); + TEST_NULL(node->parent); + free(node); + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFCHR | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 1337; + + node = fstree_mknode(NULL, "chardev", 7, NULL, &sb); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_STR_EQUAL(node->name, "chardev"); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, sb.st_mode); + TEST_EQUAL_UI(node->link_count, 1); + TEST_EQUAL_UI(node->data.devno, sb.st_rdev); + TEST_NULL(node->parent); + free(node); + + return EXIT_SUCCESS; +} diff --git a/lib/fstree/test/mknode_slink.c b/lib/fstree/test/mknode_slink.c new file mode 100644 index 0000000..c50a0ba --- /dev/null +++ b/lib/fstree/test/mknode_slink.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * mknode_slink.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "fstree.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tree_node_t *node; + struct stat sb; + fstree_t fs; + (void)argc; (void)argv; + + memset(&fs, 0, sizeof(fs)); + memset(&sb, 0, sizeof(sb)); + sb.st_mode = S_IFLNK | 0654; + sb.st_uid = 123; + sb.st_gid = 456; + sb.st_rdev = 789; + sb.st_size = 1337; + + node = fstree_mknode(NULL, "symlink", 7, "target", &sb); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, S_IFLNK | 0777); + TEST_EQUAL_UI(node->link_count, 1); + TEST_NULL(node->parent); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_ASSERT(node->data.target >= (char *)node->payload); + TEST_ASSERT(node->data.target >= node->name + 8); + TEST_STR_EQUAL(node->name, "symlink"); + TEST_STR_EQUAL(node->data.target, "target"); + free(node); + + node = fstree_mknode(NULL, "symlink", 7, "", &sb); + TEST_EQUAL_UI(node->uid, sb.st_uid); + TEST_EQUAL_UI(node->gid, sb.st_gid); + TEST_EQUAL_UI(node->mode, S_IFLNK | 0777); + TEST_EQUAL_UI(node->link_count, 1); + TEST_NULL(node->parent); + TEST_ASSERT((char *)node->name >= (char *)node->payload); + TEST_ASSERT(node->data.target >= (char *)node->payload); + TEST_ASSERT(node->data.target >= node->name + 8); + TEST_STR_EQUAL(node->name, "symlink"); + TEST_STR_EQUAL(node->data.target, ""); + free(node); + + return EXIT_SUCCESS; +} diff --git a/lib/io/Makemodule.am b/lib/io/Makemodule.am index c331124..17952f4 100644 --- a/lib/io/Makemodule.am +++ b/lib/io/Makemodule.am @@ -14,3 +14,16 @@ libio_a_SOURCES += lib/io/src/unix/ostream.c lib/io/src/unix/istream.c endif noinst_LIBRARIES += libio.a + +test_get_line_SOURCES = lib/io/test/get_line.c +test_get_line_LDADD = libio.a libcompat.a +test_get_line_CPPFLAGS = $(AM_CPPFLAGS) +test_get_line_CPPFLAGS += -DTESTFILE=$(top_srcdir)/lib/io/test/get_line.txt + +test_sparse_fb_SOURCES = lib/io/test/sparse_fb.c +test_sparse_fb_LDADD = libio.a libutil.a libcompat.a + +check_PROGRAMS += test_get_line test_sparse_fb +TESTS += test_get_line test_sparse_fb + +EXTRA_DIST += $(top_srcdir)/lib/io/test/get_line.txt diff --git a/lib/io/test/get_line.c b/lib/io/test/get_line.c new file mode 100644 index 0000000..2d0f9b7 --- /dev/null +++ b/lib/io/test/get_line.c @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * get_line.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "io/file.h" +#include "util/test.h" + +typedef struct { + size_t line_num; + const char *str; +} line_t; + +static void run_test_case(const line_t *lines, size_t count, + int flags) +{ + size_t i, line_num, old_line_num; + istream_t *fp; + char *line; + int ret; + + fp = istream_open_file(STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + + line_num = 1; + line = NULL; + + for (i = 0; i < count; ++i) { + old_line_num = line_num; + ret = istream_get_line(fp, &line, &line_num, flags); + + TEST_ASSERT(line_num >= old_line_num); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(line); + + TEST_EQUAL_UI(line_num, lines[i].line_num); + TEST_STR_EQUAL(line, lines[i].str); + + free(line); + line = NULL; + line_num += 1; + } + + ret = istream_get_line(fp, &line, &line_num, flags); + TEST_ASSERT(ret > 0); + + sqfs_drop(fp); +} + +static const line_t lines_raw[] = { + { 1, "" }, + { 2, "The quick" }, + { 3, " " }, + { 4, " brown fox " }, + { 5, "" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 9, "" }, + { 10, "dog" }, + { 11, "" }, +}; + +static const line_t lines_ltrim[] = { + { 1, "" }, + { 2, "The quick" }, + { 3, "" }, + { 4, "brown fox " }, + { 5, "" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 9, "" }, + { 10, "dog" }, + { 11, "" }, +}; + +static const line_t lines_rtrim[] = { + { 1, "" }, + { 2, "The quick" }, + { 3, "" }, + { 4, " brown fox" }, + { 5, "" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 9, "" }, + { 10, "dog" }, + { 11, "" }, +}; + +static const line_t lines_trim[] = { + { 1, "" }, + { 2, "The quick" }, + { 3, "" }, + { 4, "brown fox" }, + { 5, "" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 9, "" }, + { 10, "dog" }, + { 11, "" }, +}; + +static const line_t lines_no_empty[] = { + { 2, "The quick" }, + { 3, " " }, + { 4, " brown fox " }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 10, "dog" }, +}; + +static const line_t lines_no_empty_ltrim[] = { + { 2, "The quick" }, + { 4, "brown fox " }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 10, "dog" }, +}; + +static const line_t lines_no_empty_rtrim[] = { + { 2, "The quick" }, + { 4, " brown fox" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 10, "dog" }, +}; + +static const line_t lines_no_empty_trim[] = { + { 2, "The quick" }, + { 4, "brown fox" }, + { 6, "jumps over" }, + { 7, "the" }, + { 8, "lazy" }, + { 10, "dog" }, +}; + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + + run_test_case(lines_raw, 11, 0); + run_test_case(lines_ltrim, 11, ISTREAM_LINE_LTRIM); + run_test_case(lines_rtrim, 11, ISTREAM_LINE_RTRIM); + run_test_case(lines_trim, 11, + ISTREAM_LINE_LTRIM | ISTREAM_LINE_RTRIM); + + run_test_case(lines_no_empty, 7, ISTREAM_LINE_SKIP_EMPTY); + run_test_case(lines_no_empty_ltrim, 6, + ISTREAM_LINE_SKIP_EMPTY | ISTREAM_LINE_LTRIM); + run_test_case(lines_no_empty_rtrim, 6, + ISTREAM_LINE_SKIP_EMPTY | ISTREAM_LINE_RTRIM); + run_test_case(lines_no_empty_trim, 6, + ISTREAM_LINE_SKIP_EMPTY | ISTREAM_LINE_LTRIM | + ISTREAM_LINE_RTRIM); + + return EXIT_SUCCESS; +} diff --git a/lib/io/test/get_line.txt b/lib/io/test/get_line.txt new file mode 100644 index 0000000..a1994f0 --- /dev/null +++ b/lib/io/test/get_line.txt @@ -0,0 +1,11 @@ +
+The quick
+
+ brown fox
+
+jumps over
+the
+lazy
+
+dog
+
diff --git a/lib/io/test/sparse_fb.c b/lib/io/test/sparse_fb.c new file mode 100644 index 0000000..fa4b840 --- /dev/null +++ b/lib/io/test/sparse_fb.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * get_line.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "io/ostream.h" +#include "util/test.h" +#include "util/util.h" + +static ostream_t dummy; +static size_t total = 0; + +static int dummy_append(ostream_t *strm, const void *data, size_t size) +{ + bool bret; + + TEST_ASSERT(strm == &dummy); + TEST_NOT_NULL(data); + TEST_ASSERT(size > 0); + + bret = is_memory_zero(data, size); + TEST_ASSERT(bret); + + bret = SZ_ADD_OV(total, size, &total); + TEST_ASSERT(!bret); + return 0; +} + +static int dummy_flush(ostream_t *strm) +{ + TEST_ASSERT(strm == &dummy); + return 0; +} + +static ostream_t dummy = { + { + 1, + NULL, + NULL, + }, + dummy_append, + NULL, + dummy_flush, + NULL, +}; + +int main(int argc, char **argv) +{ + size_t ref; + int ret; + (void)argc; (void)argv; + + ref = 131072 + 1337; + + ret = ostream_append_sparse(&dummy, ref); + TEST_EQUAL_I(ret, 0); + + ret = ostream_flush(&dummy); + TEST_EQUAL_I(ret, 0); + + TEST_EQUAL_UI(ref, total); + return EXIT_SUCCESS; +} diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index dfd88c9..3500aad 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -103,3 +103,26 @@ sqfsinclude_HEADERS = $(LIBSQFS_HEARDS) lib_LTLIBRARIES += libsquashfs.la pkgconfig_DATA += lib/sqfs/libsquashfs1.pc + +test_abi_SOURCES = lib/sqfs/test/abi.c +test_abi_LDADD = libsquashfs.la libcompat.a + +test_table_SOURCES = lib/sqfs/test/table.c +test_table_LDADD = libsquashfs.la libcompat.a + +test_xattr_writer_SOURCES = lib/sqfs/test/xattr_writer.c +test_xattr_writer_LDADD = libsquashfs.la libcompat.a + +xattr_benchmark_SOURCES = lib/sqfs/test/xattr_benchmark.c +xattr_benchmark_LDADD = libcommon.a libsquashfs.la libcompat.a + +test_get_node_path_SOURCES = lib/sqfs/test/get_node_path.c +test_get_node_path_LDADD = libcommon.a libsquashfs.la libcompat.a + +LIBSQFS_TESTS = \ + test_abi test_table test_xattr_writer test_get_node_path + +noinst_PROGRAMS += xattr_benchmark + +check_PROGRAMS += $(LIBSQFS_TESTS) +TESTS += $(LIBSQFS_TESTS) diff --git a/lib/sqfs/test/abi.c b/lib/sqfs/test/abi.c new file mode 100644 index 0000000..0eaf5df --- /dev/null +++ b/lib/sqfs/test/abi.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * abi.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "sqfs/block_processor.h" +#include "sqfs/compressor.h" +#include "sqfs/block.h" +#include "util/test.h" + +#include <stddef.h> + +static void test_compressor_opt_struct(void) +{ + sqfs_compressor_config_t cfg; + + TEST_EQUAL_UI(sizeof(cfg.id), sizeof(sqfs_u16)); + TEST_EQUAL_UI(sizeof(cfg.flags), sizeof(sqfs_u16)); + TEST_EQUAL_UI(sizeof(cfg.block_size), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(cfg.level), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(cfg.opt), (2 * sizeof(sqfs_u64))); + + TEST_EQUAL_UI(sizeof(cfg.opt.gzip), sizeof(cfg.opt)); + TEST_EQUAL_UI(sizeof(cfg.opt.lzo), sizeof(cfg.opt)); + TEST_EQUAL_UI(sizeof(cfg.opt.xz), sizeof(cfg.opt)); + TEST_EQUAL_UI(sizeof(cfg.opt.padd0), sizeof(cfg.opt)); + + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, id), 0); + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, flags), + sizeof(sqfs_u16)); + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, block_size), + sizeof(sqfs_u32)); + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, level), + (2 * sizeof(sqfs_u32))); + + if (__alignof__(sqfs_compressor_config_t) == __alignof__(sqfs_u32)) { + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, opt), + (3 * sizeof(sqfs_u32))); + } else if (__alignof__(sqfs_compressor_config_t) == __alignof__(sqfs_u64)) { + TEST_EQUAL_UI(offsetof(sqfs_compressor_config_t, opt), + (4 * sizeof(sqfs_u32))); + } +} + +static const char *names[] = { + [SQFS_COMP_GZIP] = "gzip", + [SQFS_COMP_LZMA] = "lzma", + [SQFS_COMP_LZO] = "lzo", + [SQFS_COMP_XZ] = "xz", + [SQFS_COMP_LZ4] = "lz4", + [SQFS_COMP_ZSTD] = "zstd", +}; + +static void test_compressor_names(void) +{ + const char *str; + int i, id; + + for (i = SQFS_COMP_MIN; i <= SQFS_COMP_MAX; ++i) { + str = sqfs_compressor_name_from_id(i); + TEST_STR_EQUAL(str, names[i]); + + id = sqfs_compressor_id_from_name(str); + TEST_EQUAL_I(id, i); + } +} + +static void test_blockproc_stats(void) +{ + sqfs_block_processor_stats_t stats; + size_t off; + + TEST_EQUAL_UI(sizeof(stats.size), sizeof(size_t)); + TEST_EQUAL_UI(sizeof(stats.input_bytes_read), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.output_bytes_generated), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.data_block_count), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.frag_block_count), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.sparse_block_count), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.total_frag_count), sizeof(sqfs_u64)); + TEST_EQUAL_UI(sizeof(stats.actual_frag_count), sizeof(sqfs_u64)); + + if (__alignof__(stats) == __alignof__(sqfs_u32)) { + TEST_ASSERT(sizeof(stats) >= + (sizeof(sqfs_u32) + 7 * sizeof(sqfs_u64))); + } else if (__alignof__(stats) == __alignof__(sqfs_u64)) { + TEST_ASSERT(sizeof(stats) >= (8 * sizeof(sqfs_u64))); + } + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, size), 0); + + if (sizeof(size_t) < sizeof(sqfs_u64) && + (__alignof__(sqfs_block_processor_stats_t) == + __alignof__(sqfs_u64))) { + off = sizeof(sqfs_u64); + } else { + off = sizeof(stats.size); + } + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + input_bytes_read), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + output_bytes_generated), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + data_block_count), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + frag_block_count), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + sparse_block_count), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + total_frag_count), off); + off += sizeof(sqfs_u64); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_stats_t, + actual_frag_count), off); +} + +static void test_blockproc_desc(void) +{ + sqfs_block_processor_desc_t desc; + + TEST_ASSERT(sizeof(desc) >= (4 * sizeof(sqfs_u32) + + 5 * sizeof(void *))); + + TEST_EQUAL_UI(sizeof(desc.size), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(desc.max_block_size), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(desc.num_workers), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(desc.max_backlog), sizeof(sqfs_u32)); + TEST_EQUAL_UI(sizeof(desc.cmp), sizeof(void *)); + TEST_EQUAL_UI(sizeof(desc.wr), sizeof(void *)); + TEST_EQUAL_UI(sizeof(desc.tbl), sizeof(void *)); + TEST_EQUAL_UI(sizeof(desc.file), sizeof(void *)); + TEST_EQUAL_UI(sizeof(desc.uncmp), sizeof(void *)); + + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, size), 0); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, max_block_size), + sizeof(sqfs_u32)); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, num_workers), + (2 * sizeof(sqfs_u32))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, max_backlog), + (3 * sizeof(sqfs_u32))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, cmp), + (4 * sizeof(sqfs_u32))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, wr), + (4 * sizeof(sqfs_u32) + sizeof(void *))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, tbl), + (4 * sizeof(sqfs_u32) + 2 * sizeof(void *))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, file), + (4 * sizeof(sqfs_u32) + 3 * sizeof(void *))); + TEST_EQUAL_UI(offsetof(sqfs_block_processor_desc_t, uncmp), + (4 * sizeof(sqfs_u32) + 4 * sizeof(void *))); +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + test_compressor_opt_struct(); + test_compressor_names(); + test_blockproc_stats(); + test_blockproc_desc(); + return EXIT_SUCCESS; +} diff --git a/lib/sqfs/test/get_node_path.c b/lib/sqfs/test/get_node_path.c new file mode 100644 index 0000000..c76cc1c --- /dev/null +++ b/lib/sqfs/test/get_node_path.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * get_node_path.c + * + * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "util/test.h" + +#include "sqfs/dir_reader.h" +#include "sqfs/error.h" + +int main(int argc, char **argv) +{ + sqfs_tree_node_t *n0, *n1, *n2; + char *str; + int ret; + (void)argc; + (void)argv; + + n0 = calloc(1, sizeof(*n0) + 16); + TEST_NOT_NULL(n0); + + n1 = calloc(1, sizeof(*n1) + 16); + TEST_NOT_NULL(n1); + + n2 = calloc(1, sizeof(*n2) + 16); + TEST_NOT_NULL(n2); + + /* no parent -> must return "/" */ + ret = sqfs_tree_node_get_path(n0, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/"); + sqfs_free(str); + + /* hiearchy levels */ + n1->parent = n0; + n0->children = n1; + strcpy((char *)n1->name, "bar"); + + n2->parent = n1; + n1->children = n2; + strcpy((char *)n2->name, "baz"); + + ret = sqfs_tree_node_get_path(n1, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar"); + sqfs_free(str); + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar/baz"); + sqfs_free(str); + + /* root node must not have a name */ + strcpy((char *)n0->name, "foo"); + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_ARG_INVALID); + TEST_NULL(str); + n0->name[0] = '\0'; + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar/baz"); + sqfs_free(str); + + /* non-root nodes must have names */ + n1->name[0] = '\0'; + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_CORRUPTED); + TEST_NULL(str); + n1->name[0] = 'b'; + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar/baz"); + sqfs_free(str); + + /* some names are illegal */ + strcpy((char *)n1->name, ".."); + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_CORRUPTED); + TEST_NULL(str); + + strcpy((char *)n1->name, "."); + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_CORRUPTED); + TEST_NULL(str); + + strcpy((char *)n1->name, "a/b"); + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_CORRUPTED); + TEST_NULL(str); + + strcpy((char *)n1->name, "bar"); + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar/baz"); + sqfs_free(str); + + /* link loops must be detected */ + n0->parent = n2; + strcpy((char *)n0->name, "foo"); + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, SQFS_ERROR_LINK_LOOP); + TEST_NULL(str); + + n0->parent = NULL; + n0->name[0] = '\0'; + + ret = sqfs_tree_node_get_path(n2, &str); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(str); + TEST_STR_EQUAL(str, "/bar/baz"); + sqfs_free(str); + + /* cleanup */ + free(n0); + free(n1); + free(n2); + return EXIT_SUCCESS; +} diff --git a/lib/sqfs/test/table.c b/lib/sqfs/test/table.c new file mode 100644 index 0000000..3e44fa3 --- /dev/null +++ b/lib/sqfs/test/table.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * table.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "util/test.h" + +#include "sqfs/compressor.h" +#include "sqfs/error.h" +#include "sqfs/table.h" +#include "sqfs/io.h" + +static sqfs_u8 file_data[32768]; +static size_t file_used = 0; + +static int dummy_read_at(sqfs_file_t *file, sqfs_u64 offset, + void *buffer, size_t size) +{ + (void)file; + + if (offset >= sizeof(file_data)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + if (size > (sizeof(file_data) - offset)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + memset(buffer, 0, size); + + if (offset < file_used) { + if (size > (file_used - offset)) + size = file_used - offset; + + memcpy(buffer, file_data + offset, size); + } + return 0; +} + +static int dummy_write_at(sqfs_file_t *file, sqfs_u64 offset, + const void *buffer, size_t size) +{ + (void)file; + + if (offset >= sizeof(file_data)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + if (size > (sizeof(file_data) - offset)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + if (offset > file_used) + memset(file_data + file_used, 0, offset - file_used); + + if ((offset + size) > file_used) + file_used = offset + size; + + memcpy(file_data + offset, buffer, size); + return 0; +} + +static sqfs_u64 dummy_get_size(const sqfs_file_t *file) +{ + (void)file; + return file_used; +} + +static sqfs_s32 dummy_compress(sqfs_compressor_t *cmp, const sqfs_u8 *in, + sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) +{ + (void)cmp; + memcpy(out, in, outsize < size ? outsize : size); + return 0; +} + +static sqfs_s32 dummy_uncompress(sqfs_compressor_t *cmp, const sqfs_u8 *in, + sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) +{ + (void)cmp; + if (outsize < size) + return 0; + memcpy(out, in, size); + return size; +} + +static sqfs_file_t dummy_file = { + { 1, NULL, NULL }, + dummy_read_at, + dummy_write_at, + dummy_get_size, + NULL, +}; + +static sqfs_compressor_t dummy_compressor = { + { 1, NULL, NULL }, + NULL, + NULL, + NULL, + dummy_compress, +}; + +static sqfs_compressor_t dummy_uncompressor = { + { 1, NULL, NULL }, + NULL, + NULL, + NULL, + dummy_uncompress, +}; + +/*****************************************************************************/ + +static sqfs_u64 table[4000]; + +int main(int argc, char **argv) +{ + sqfs_u64 start, value, locations[4], *copy; + sqfs_u16 hdr; + size_t i; + int ret; + (void)argc; (void)argv; + + /* fill the table with data */ + for (i = 0; i < sizeof(table) / sizeof(table[0]); ++i) + table[i] = i; + + /* serialize the table */ + ret = sqfs_write_table(&dummy_file, &dummy_compressor, + table, sizeof(table), &start); + TEST_EQUAL_I(ret, 0); + + TEST_EQUAL_UI(file_used, (3 * (8192 + 2) + (7424 + 2) + 4 * sizeof(sqfs_u64))); + TEST_EQUAL_UI(start, (3 * (8192 + 2) + (7424 + 2))); + + /* check the location list */ + memcpy(locations, file_data + start, sizeof(locations)); + for (i = 0; i < 4; ++i) + locations[i] = le64toh(locations[i]); + + TEST_EQUAL_UI(locations[0], 0); + TEST_EQUAL_UI(locations[1], (1 * (8192 + 2))); + TEST_EQUAL_UI(locations[2], (2 * (8192 + 2))); + TEST_EQUAL_UI(locations[3], (3 * (8192 + 2))); + + /* check the individual blocks */ + memcpy(&hdr, file_data + locations[0], sizeof(hdr)); + hdr = le16toh(hdr); + TEST_EQUAL_UI(hdr, (0x8000 | 8192)); + + for (i = 0; i < 8192; i += sizeof(sqfs_u64)) { + memcpy(&value, (file_data + locations[0] + 2) + i, + sizeof(value)); + + TEST_EQUAL_UI(value, i / sizeof(sqfs_u64)); + } + + memcpy(&hdr, file_data + locations[1], sizeof(hdr)); + hdr = le16toh(hdr); + TEST_EQUAL_UI(hdr, (0x8000 | 8192)); + + for (i = 0; i < 8192; i += sizeof(sqfs_u64)) { + memcpy(&value, (file_data + locations[1] + 2) + i, + sizeof(value)); + + TEST_EQUAL_UI(value, (1024 + i / sizeof(sqfs_u64))); + } + + memcpy(&hdr, file_data + locations[2], sizeof(hdr)); + hdr = le16toh(hdr); + TEST_EQUAL_UI(hdr, (0x8000 | 8192)); + + for (i = 0; i < 8192; i += sizeof(sqfs_u64)) { + memcpy(&value, (file_data + locations[2] + 2) + i, + sizeof(value)); + + TEST_EQUAL_UI(value, (2048 + i / sizeof(sqfs_u64))); + } + + memcpy(&hdr, file_data + locations[3], sizeof(hdr)); + hdr = le16toh(hdr); + TEST_EQUAL_UI(hdr, (0x8000 | 7424)); + + for (i = 0; i < 7424; i += sizeof(sqfs_u64)) { + memcpy(&value, (file_data + locations[3] + 2) + i, + sizeof(value)); + + TEST_EQUAL_UI(value, (3072 + i / sizeof(sqfs_u64))); + } + + /* read the table back */ + ret = sqfs_read_table(&dummy_file, &dummy_uncompressor, + sizeof(table), start, 0, start, (void **)©); + TEST_EQUAL_I(ret, 0); + + ret = memcmp(copy, table, sizeof(table)); + TEST_EQUAL_I(ret, 0); + + free(copy); + return EXIT_SUCCESS; +} diff --git a/lib/sqfs/test/xattr_benchmark.c b/lib/sqfs/test/xattr_benchmark.c new file mode 100644 index 0000000..072dd06 --- /dev/null +++ b/lib/sqfs/test/xattr_benchmark.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * xattr_benchmark.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "common.h" + +#include "sqfs/xattr_writer.h" +#include "sqfs/xattr.h" + +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <stdio.h> + +static struct option long_opts[] = { + { "block-count", required_argument, NULL, 'b' }, + { "groups-size", required_argument, NULL, 'g' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 }, +}; + +static const char *short_opts = "g:b:hV"; + +static const char *help_string = +"Usage: xattr_benchmark [OPTIONS...]\n" +"\n" +"Possible options:\n" +"\n" +" --block-count, -b <count> How many unique xattr blocks to generate.\n" +" --group-size, -g <count> Number of key-value pairs to generate for each\n" +" xattr block.\n" +"\n"; + +int main(int argc, char **argv) +{ + long blkidx, grpidx, block_count = 0, group_size = 0; + sqfs_xattr_writer_t *xwr; + sqfs_u32 id; + int ret; + + for (;;) { + int i = getopt_long(argc, argv, short_opts, long_opts, NULL); + if (i == -1) + break; + + switch (i) { + case 'b': + block_count = strtol(optarg, NULL, 0); + break; + case 'g': + group_size = strtol(optarg, NULL, 0); + break; + case 'h': + fputs(help_string, stdout); + return EXIT_SUCCESS; + case 'V': + print_version("xattr_benchmark"); + return EXIT_SUCCESS; + default: + goto fail_arg; + } + } + + if (block_count <= 0) { + fputs("A block count > 0 must be specified.\n", stderr); + goto fail_arg; + } + + if (group_size <= 0) { + fputs("A group size > 0 must be specified.\n", stderr); + goto fail_arg; + } + + /* setup writer */ + xwr = sqfs_xattr_writer_create(0); + + /* generate blocks */ + for (blkidx = 0; blkidx < block_count; ++blkidx) { + ret = sqfs_xattr_writer_begin(xwr, 0); + if (ret < 0) { + sqfs_perror(NULL, "begin xattr block", ret); + goto fail; + } + + for (grpidx = 0; grpidx < group_size; ++grpidx) { + char key[64], value[64]; + + snprintf(key, sizeof(key), "user.group%ld.key%ld", + blkidx, grpidx); + + snprintf(value, sizeof(value), "group%ld/value%ld", + blkidx, grpidx); + + ret = sqfs_xattr_writer_add(xwr, key, value, + strlen(value)); + + if (ret < 0) { + sqfs_perror(NULL, "add to xattr block", ret); + goto fail; + } + } + + ret = sqfs_xattr_writer_end(xwr, &id); + if (ret < 0) { + sqfs_perror(NULL, "end xattr block", ret); + goto fail; + } + } + + /* cleanup */ + sqfs_drop(xwr); + return EXIT_SUCCESS; +fail: + sqfs_drop(xwr); + return EXIT_FAILURE; +fail_arg: + fputs("Try `xattr_benchmark --help' for more information.\n", stderr); + return EXIT_FAILURE; +} diff --git a/lib/sqfs/test/xattr_writer.c b/lib/sqfs/test/xattr_writer.c new file mode 100644 index 0000000..f7d0734 --- /dev/null +++ b/lib/sqfs/test/xattr_writer.c @@ -0,0 +1,323 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * xattr_writer.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "util/test.h" + +#include "sqfs/xattr_writer.h" +#include "sqfs/compressor.h" +#include "sqfs/xattr.h" +#include "sqfs/error.h" +#include "sqfs/super.h" +#include "sqfs/io.h" + +static sqfs_u8 file_data[1024]; +static size_t file_used = 0; + +static int dummy_write_at(sqfs_file_t *file, sqfs_u64 offset, + const void *buffer, size_t size) +{ + (void)file; + + if (offset >= sizeof(file_data)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + if (size > (sizeof(file_data) - offset)) + return SQFS_ERROR_OUT_OF_BOUNDS; + + if (offset > file_used) + memset(file_data + file_used, 0, offset - file_used); + + if ((offset + size) > file_used) + file_used = offset + size; + + memcpy(file_data + offset, buffer, size); + return 0; +} + +static sqfs_u64 dummy_get_size(const sqfs_file_t *file) +{ + (void)file; + return file_used; +} + +static sqfs_s32 dummy_compress(sqfs_compressor_t *cmp, const sqfs_u8 *in, + sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) +{ + (void)cmp; + memcpy(out, in, outsize < size ? outsize : size); + return 0; +} + +static sqfs_file_t dummy_file = { + { 1, NULL, NULL }, + NULL, + dummy_write_at, + dummy_get_size, + NULL, +}; + +static sqfs_compressor_t dummy_compressor = { + { 1, NULL, NULL }, + NULL, + NULL, + NULL, + dummy_compress, +}; + +/*****************************************************************************/ + +int main(int argc, char **argv) +{ + size_t offset, ool_value_offset, id_offset; + sqfs_xattr_id_table_t idtbl; + sqfs_xattr_writer_t *xwr; + sqfs_xattr_value_t value; + sqfs_xattr_entry_t key; + sqfs_xattr_id_t desc; + sqfs_super_t super; + char strbuf[32]; + sqfs_u16 hdr; + sqfs_u64 ref; + sqfs_u32 id; + int ret; + (void)argc; (void)argv; + + /* setup */ + xwr = sqfs_xattr_writer_create(0); + TEST_NOT_NULL(xwr); + + /* record a block of key/value pairs */ + ret = sqfs_xattr_writer_begin(xwr, 0); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "user.foobar", "test", 4); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "security.selinux", "Xwhatever", 9); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_end(xwr, &id); + TEST_EQUAL_I(ret, 0); + TEST_EQUAL_UI(id, 0); + + /* record a second, different block */ + ret = sqfs_xattr_writer_begin(xwr, 0); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "user.foobar", "bla", 3); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "security.selinux", "blub", 4); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_end(xwr, &id); + TEST_EQUAL_I(ret, 0); + TEST_EQUAL_UI(id, 1); + + /* same as first block after sorting and gets the same ID */ + ret = sqfs_xattr_writer_begin(xwr, 0); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "security.selinux", "Xwhatever", 9); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "user.foobar", "test", 4); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_end(xwr, &id); + TEST_EQUAL_I(ret, 0); + TEST_EQUAL_UI(id, 0); + + /* the third assignment overwrites the first, making + the block identical to the second one */ + ret = sqfs_xattr_writer_begin(xwr, 0); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "user.foobar", "mimimi", 6); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "security.selinux", "blub", 4); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "user.foobar", "bla", 3); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_end(xwr, &id); + TEST_EQUAL_I(ret, 0); + TEST_EQUAL_UI(id, 1); + + /* add another block with the same value, so it gets stored OOL */ + ret = sqfs_xattr_writer_begin(xwr, 0); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_add(xwr, "security.selinux", "Xwhatever", 9); + TEST_EQUAL_I(ret, 0); + + ret = sqfs_xattr_writer_end(xwr, &id); + TEST_EQUAL_I(ret, 0); + TEST_EQUAL_UI(id, 2); + + /* serialize */ + sqfs_super_init(&super, 131072, 0, SQFS_COMP_GZIP); + ret = sqfs_xattr_writer_flush(xwr, &dummy_file, &super, + &dummy_compressor); + TEST_EQUAL_I(ret, 0); + + TEST_EQUAL_UI(file_used, 177); + + /* meta data block holding the key-value-pairs */ + memcpy(&hdr, file_data, sizeof(hdr)); + hdr = le16toh(hdr); + TEST_EQUAL_UI(hdr, (0x8000 | 101)); + offset = 2; + + memcpy(&key, file_data + offset, sizeof(key)); + key.type = le16toh(key.type); + key.size = le16toh(key.size); + offset += sizeof(key); + TEST_EQUAL_UI(key.type, SQFS_XATTR_USER); + TEST_EQUAL_UI(key.size, 6); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, key.size); + TEST_STR_EQUAL(strbuf, "foobar"); + offset += key.size; + + memcpy(&value, file_data + offset, sizeof(value)); + value.size = le32toh(value.size); + offset += sizeof(value); + TEST_EQUAL_UI(value.size, 4); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, value.size); + TEST_STR_EQUAL(strbuf, "test"); + offset += value.size; + + memcpy(&key, file_data + offset, sizeof(key)); + key.type = le16toh(key.type); + key.size = le16toh(key.size); + offset += sizeof(key); + TEST_EQUAL_UI(key.type, SQFS_XATTR_SECURITY); + TEST_EQUAL_UI(key.size, 7); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, key.size); + TEST_STR_EQUAL(strbuf, "selinux"); + offset += key.size; + + ool_value_offset = offset; + + memcpy(&value, file_data + offset, sizeof(value)); + value.size = le32toh(value.size); + offset += sizeof(value); + TEST_EQUAL_UI(value.size, 9); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, value.size); + TEST_STR_EQUAL(strbuf, "Xwhatever"); + offset += value.size; + + memcpy(&key, file_data + offset, sizeof(key)); + key.type = le16toh(key.type); + key.size = le16toh(key.size); + offset += sizeof(key); + TEST_EQUAL_UI(key.type, SQFS_XATTR_USER); + TEST_EQUAL_UI(key.size, 6); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, key.size); + TEST_STR_EQUAL(strbuf, "foobar"); + offset += key.size; + + memcpy(&value, file_data + offset, sizeof(value)); + value.size = le32toh(value.size); + offset += sizeof(value); + TEST_EQUAL_UI(value.size, 3); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, value.size); + TEST_STR_EQUAL(strbuf, "bla"); + offset += value.size; + + memcpy(&key, file_data + offset, sizeof(key)); + key.type = le16toh(key.type); + key.size = le16toh(key.size); + offset += sizeof(key); + TEST_EQUAL_UI(key.type, SQFS_XATTR_SECURITY); + TEST_EQUAL_UI(key.size, 7); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, key.size); + TEST_STR_EQUAL(strbuf, "selinux"); + offset += key.size; + + memcpy(&value, file_data + offset, sizeof(value)); + value.size = le32toh(value.size); + offset += sizeof(value); + TEST_EQUAL_UI(value.size, 4); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, value.size); + TEST_STR_EQUAL(strbuf, "blub"); + offset += value.size; + + memcpy(&key, file_data + offset, sizeof(key)); + key.type = le16toh(key.type); + key.size = le16toh(key.size); + offset += sizeof(key); + TEST_EQUAL_UI(key.type, (SQFS_XATTR_SECURITY | SQFS_XATTR_FLAG_OOL)); + TEST_EQUAL_UI(key.size, 7); + memset(strbuf, '\0', sizeof(strbuf)); + memcpy(strbuf, file_data + offset, key.size); + TEST_STR_EQUAL(strbuf, "selinux"); + offset += key.size; + + memcpy(&value, file_data + offset, sizeof(value)); + value.size = le32toh(value.size); + offset += sizeof(value); + TEST_EQUAL_UI(value.size, 8); + memcpy(&ref, file_data + offset, sizeof(ref)); + ref = le64toh(ref); + TEST_EQUAL_UI(ref, (ool_value_offset - 2)); + offset += value.size; + + /* meta data block holding the ID descriptions */ + id_offset = offset; + + memcpy(&hdr, file_data + offset, sizeof(hdr)); + TEST_EQUAL_UI(le16toh(hdr), (0x8000 | (16 * 3))); + offset += sizeof(hdr); + + memcpy(&desc, file_data + offset, sizeof(desc)); + TEST_EQUAL_UI(le64toh(desc.xattr), 0); + TEST_EQUAL_UI(le32toh(desc.count), 2); + TEST_EQUAL_UI(le32toh(desc.size), 42); + offset += sizeof(desc); + + memcpy(&desc, file_data + offset, sizeof(desc)); + TEST_EQUAL_UI(le64toh(desc.xattr), 42); + TEST_EQUAL_UI(le32toh(desc.count), 2); + TEST_EQUAL_UI(le32toh(desc.size), 36); + offset += sizeof(desc); + + memcpy(&desc, file_data + offset, sizeof(desc)); + TEST_EQUAL_UI(le64toh(desc.xattr), 78); + TEST_EQUAL_UI(le32toh(desc.count), 1); + TEST_EQUAL_UI(le32toh(desc.size), 23); + offset += sizeof(desc); + + /* the xattr table itself */ + TEST_EQUAL_UI(super.xattr_id_table_start, offset); + + memcpy(&idtbl, file_data + offset, sizeof(idtbl)); + TEST_EQUAL_UI(le64toh(idtbl.xattr_table_start), 0); + TEST_EQUAL_UI(le32toh(idtbl.xattr_ids), 3); + offset += sizeof(idtbl); + + memcpy(&ref, file_data + offset, sizeof(ref)); + TEST_EQUAL_UI(le64toh(ref), id_offset); + offset += sizeof(ref); + + TEST_EQUAL_UI(offset, file_used); + + /* cleanup */ + sqfs_drop(xwr); + return EXIT_SUCCESS; +} diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am index 1db02f1..896ce0f 100644 --- a/lib/tar/Makemodule.am +++ b/lib/tar/Makemodule.am @@ -6,3 +6,180 @@ libtar_a_SOURCES = lib/tar/src/read_header.c lib/tar/src/write_header.c \ include/tar/tar.h include/tar/format.h noinst_LIBRARIES += libtar.a + +TARDATADIR=$(top_srcdir)/lib/tar/test/data + +test_tar_gnu0_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu0_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu0_CPPFLAGS += -DTESTFILE=format-acceptance/gnu.tar + +test_tar_gnu1_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu1_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu1_CPPFLAGS += -DTESTFILE=format-acceptance/gnu-g.tar + +test_tar_gnu2_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu2_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu2_CPPFLAGS += -DTESTFILE=user-group-largenum/gnu.tar +test_tar_gnu2_CPPFLAGS += -DTESTUID=0x80000000 -DTESTGID=0x80000000 +test_tar_gnu2_CPPFLAGS += -DTESTTS=1542995392 + +test_tar_gnu3_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu3_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu3_CPPFLAGS += -DTESTFILE=negative-mtime/gnu.tar -DTESTTS=-315622800 + +test_tar_gnu4_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu4_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu4_CPPFLAGS += -DTESTFILE=long-paths/gnu.tar -DLONG_NAME_TEST +test_tar_gnu4_CPPFLAGS += -DTESTTS=1542909670 + +test_tar_gnu5_SOURCES = lib/tar/test/tar_simple.c +test_tar_gnu5_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu5_CPPFLAGS += -DTESTFILE=large-mtime/gnu.tar -DTESTTS=8589934592L + +test_tar_gnu6_SOURCES = lib/tar/test/tar_big_file.c +test_tar_gnu6_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_gnu6_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_gnu6_CPPFLAGS += -DTESTFILE=file-size/gnu.tar + +test_tar_pax0_SOURCES = lib/tar/test/tar_simple.c +test_tar_pax0_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax0_CPPFLAGS += -DTESTFILE=format-acceptance/pax.tar + +test_tar_pax1_SOURCES = lib/tar/test/tar_simple.c +test_tar_pax1_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax1_CPPFLAGS += -DTESTFILE=user-group-largenum/pax.tar +test_tar_pax1_CPPFLAGS += -DTESTUID=2147483648UL -DTESTGID=2147483648UL +test_tar_pax1_CPPFLAGS += -DTESTTS=1542995392 + +test_tar_pax2_SOURCES = lib/tar/test/tar_simple.c +test_tar_pax2_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax2_CPPFLAGS += -DTESTFILE=large-mtime/pax.tar -DTESTTS=8589934592L + +test_tar_pax3_SOURCES = lib/tar/test/tar_simple.c +test_tar_pax3_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax3_CPPFLAGS += -DTESTFILE=negative-mtime/pax.tar -DTESTTS=-315622800 + +test_tar_pax4_SOURCES = lib/tar/test/tar_simple.c +test_tar_pax4_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax4_CPPFLAGS += -DTESTFILE=long-paths/pax.tar +test_tar_pax4_CPPFLAGS += -DLONG_NAME_TEST -DTESTTS=1542909670 + +test_tar_pax5_SOURCES = lib/tar/test/tar_big_file.c +test_tar_pax5_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_pax5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_pax5_CPPFLAGS += -DTESTFILE=file-size/pax.tar + +test_tar_ustar0_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar0_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar0_CPPFLAGS += -DTESTFILE=format-acceptance/ustar.tar + +test_tar_ustar1_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar1_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar1_CPPFLAGS += -DTESTFILE=format-acceptance/ustar-pre-posix.tar + +test_tar_ustar2_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar2_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar2_CPPFLAGS += -DTESTFILE=format-acceptance/v7.tar + +test_tar_ustar3_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar3_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar3_CPPFLAGS += -DTESTFILE=user-group-largenum/8-digit.tar +test_tar_ustar3_CPPFLAGS += -DTESTUID=8388608 -DTESTGID=8388608 +test_tar_ustar3_CPPFLAGS += -DTESTTS=1542995392 + +test_tar_ustar4_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar4_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar4_CPPFLAGS += -DTESTFILE=large-mtime/12-digit.tar +test_tar_ustar4_CPPFLAGS += -DTESTTS=8589934592L + +test_tar_ustar5_SOURCES = lib/tar/test/tar_simple.c +test_tar_ustar5_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar5_CPPFLAGS += -DTESTFILE=long-paths/ustar.tar +test_tar_ustar5_CPPFLAGS += -DLONG_NAME_TEST -DTESTTS=1542909670 + +test_tar_ustar6_SOURCES = lib/tar/test/tar_big_file.c +test_tar_ustar6_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_ustar6_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_ustar6_CPPFLAGS += -DTESTFILE=file-size/12-digit.tar + +test_tar_target_filled_SOURCES = lib/tar/test/tar_target_filled.c +test_tar_target_filled_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_target_filled_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) + +test_tar_sparse_gnu_SOURCES = lib/tar/test/tar_sparse_gnu.c +test_tar_sparse_gnu_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_sparse_gnu_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) + +test_tar_sparse_gnu0_SOURCES = lib/tar/test/tar_sparse.c +test_tar_sparse_gnu0_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_sparse_gnu0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_sparse_gnu0_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu0-0.tar + +test_tar_sparse_gnu1_SOURCES = lib/tar/test/tar_sparse.c +test_tar_sparse_gnu1_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_sparse_gnu1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_sparse_gnu1_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu0-1.tar + +test_tar_sparse_gnu2_SOURCES = lib/tar/test/tar_sparse.c +test_tar_sparse_gnu2_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_sparse_gnu2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_sparse_gnu2_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu1-0.tar + +test_tar_sparse_gnu3_SOURCES = lib/tar/test/tar_sparse.c +test_tar_sparse_gnu3_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_sparse_gnu3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_sparse_gnu3_CPPFLAGS += -DTESTFILE=sparse-files/gnu.tar + +test_tar_xattr_bsd_SOURCES = lib/tar/test/tar_xattr.c +test_tar_xattr_bsd_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_xattr_bsd_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_xattr_bsd_CPPFLAGS += -DTESTFILE=xattr/xattr-libarchive.tar + +test_tar_xattr_schily_SOURCES = lib/tar/test/tar_xattr.c +test_tar_xattr_schily_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_xattr_schily_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_xattr_schily_CPPFLAGS += -DTESTFILE=xattr/xattr-schily.tar + +test_tar_xattr_schily_bin_SOURCES = lib/tar/test/tar_xattr_bin.c +test_tar_xattr_schily_bin_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_xattr_schily_bin_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_xattr_schily_bin_CPPFLAGS += -DTESTFILE=xattr/xattr-schily-binary.tar + +tar_fuzz_SOURCES = lib/tar/test/tar_fuzz.c +tar_fuzz_LDADD = libtar.a libio.a libutil.a libcompat.a + +LIBTAR_TESTS = \ + test_tar_ustar0 test_tar_ustar1 test_tar_ustar2 test_tar_ustar3 \ + test_tar_ustar4 test_tar_ustar5 test_tar_ustar6 \ + test_tar_pax0 test_tar_pax1 test_tar_pax2 test_tar_pax3 test_tar_pax4 \ + test_tar_pax5 \ + test_tar_gnu0 test_tar_gnu1 test_tar_gnu2 test_tar_gnu3 test_tar_gnu4 \ + test_tar_gnu5 test_tar_gnu6 \ + test_tar_sparse_gnu test_tar_sparse_gnu0 test_tar_sparse_gnu1 \ + test_tar_sparse_gnu2 test_tar_sparse_gnu3 \ + test_tar_xattr_bsd test_tar_xattr_schily test_tar_xattr_schily_bin \ + test_tar_target_filled + +check_PROGRAMS += $(LIBTAR_TESTS) +TESTS += $(LIBTAR_TESTS) + +noinst_PROGRAMS += tar_fuzz + +EXTRA_DIST += $(TARDATADIR) diff --git a/lib/tar/test/data/CREDITS b/lib/tar/test/data/CREDITS new file mode 100644 index 0000000..7a2738f --- /dev/null +++ b/lib/tar/test/data/CREDITS @@ -0,0 +1,35 @@ +The tar archives in this directory have been obtained from here: + + https://github.com/mgorny/tar-test-inputs + + git commit hash a2110a6 + +This repository was linked in the following article on interoperability of +various different tar programs: + + https://dev.gentoo.org/~mgorny/articles/portability-of-tar-features.html + +The original intention of the example archives was to test various tar programs +for interoperability with each others extensions and format quirks. + +The following have been removed since there is no intention in adding support +for those features: + + - volume-label tests + - multi-volume tests + - longe user + group names + - sun tar samples + - star samples + - file flags tests + +In addition to that, the files in "file-size" are truncated, since we are only +interested in parsing the header. + +The following addtional files have been added: + - xattr/xattr-shily-binary.tar + Created from xattr/xattr-shily.tar by manually patching in a capability + xattr key/value pair. + - tar/format-acceptance/link_filled.tar + Contributed in GitHub issue #64. A tar ball that contains a hard link + where the 100 byte target field is completely filled without containing + a null-terminator. diff --git a/lib/tar/test/data/file-size/12-digit.tar b/lib/tar/test/data/file-size/12-digit.tar Binary files differnew file mode 100644 index 0000000..a6b3553 --- /dev/null +++ b/lib/tar/test/data/file-size/12-digit.tar diff --git a/lib/tar/test/data/file-size/gnu.tar b/lib/tar/test/data/file-size/gnu.tar Binary files differnew file mode 100644 index 0000000..aad726f --- /dev/null +++ b/lib/tar/test/data/file-size/gnu.tar diff --git a/lib/tar/test/data/file-size/pax.tar b/lib/tar/test/data/file-size/pax.tar Binary files differnew file mode 100644 index 0000000..e391fee --- /dev/null +++ b/lib/tar/test/data/file-size/pax.tar diff --git a/lib/tar/test/data/format-acceptance/gnu-g.tar b/lib/tar/test/data/format-acceptance/gnu-g.tar Binary files differnew file mode 100644 index 0000000..a72f60d --- /dev/null +++ b/lib/tar/test/data/format-acceptance/gnu-g.tar diff --git a/lib/tar/test/data/format-acceptance/gnu.tar b/lib/tar/test/data/format-acceptance/gnu.tar Binary files differnew file mode 100644 index 0000000..98e8157 --- /dev/null +++ b/lib/tar/test/data/format-acceptance/gnu.tar diff --git a/lib/tar/test/data/format-acceptance/link_filled.tar b/lib/tar/test/data/format-acceptance/link_filled.tar Binary files differnew file mode 100644 index 0000000..9b80f89 --- /dev/null +++ b/lib/tar/test/data/format-acceptance/link_filled.tar diff --git a/lib/tar/test/data/format-acceptance/pax.tar b/lib/tar/test/data/format-acceptance/pax.tar Binary files differnew file mode 100644 index 0000000..69a029f --- /dev/null +++ b/lib/tar/test/data/format-acceptance/pax.tar diff --git a/lib/tar/test/data/format-acceptance/ustar-pre-posix.tar b/lib/tar/test/data/format-acceptance/ustar-pre-posix.tar Binary files differnew file mode 100644 index 0000000..4230f5f --- /dev/null +++ b/lib/tar/test/data/format-acceptance/ustar-pre-posix.tar diff --git a/lib/tar/test/data/format-acceptance/ustar.tar b/lib/tar/test/data/format-acceptance/ustar.tar Binary files differnew file mode 100644 index 0000000..9a6d9b3 --- /dev/null +++ b/lib/tar/test/data/format-acceptance/ustar.tar diff --git a/lib/tar/test/data/format-acceptance/v7.tar b/lib/tar/test/data/format-acceptance/v7.tar Binary files differnew file mode 100644 index 0000000..5483b4b --- /dev/null +++ b/lib/tar/test/data/format-acceptance/v7.tar diff --git a/lib/tar/test/data/large-mtime/12-digit.tar b/lib/tar/test/data/large-mtime/12-digit.tar Binary files differnew file mode 100644 index 0000000..8202b28 --- /dev/null +++ b/lib/tar/test/data/large-mtime/12-digit.tar diff --git a/lib/tar/test/data/large-mtime/gnu.tar b/lib/tar/test/data/large-mtime/gnu.tar Binary files differnew file mode 100644 index 0000000..4e3dda2 --- /dev/null +++ b/lib/tar/test/data/large-mtime/gnu.tar diff --git a/lib/tar/test/data/large-mtime/pax.tar b/lib/tar/test/data/large-mtime/pax.tar Binary files differnew file mode 100644 index 0000000..8d32530 --- /dev/null +++ b/lib/tar/test/data/large-mtime/pax.tar diff --git a/lib/tar/test/data/long-paths/gnu.tar b/lib/tar/test/data/long-paths/gnu.tar Binary files differnew file mode 100644 index 0000000..4eee731 --- /dev/null +++ b/lib/tar/test/data/long-paths/gnu.tar diff --git a/lib/tar/test/data/long-paths/pax.tar b/lib/tar/test/data/long-paths/pax.tar Binary files differnew file mode 100644 index 0000000..1e63e9c --- /dev/null +++ b/lib/tar/test/data/long-paths/pax.tar diff --git a/lib/tar/test/data/long-paths/ustar.tar b/lib/tar/test/data/long-paths/ustar.tar Binary files differnew file mode 100644 index 0000000..812255c --- /dev/null +++ b/lib/tar/test/data/long-paths/ustar.tar diff --git a/lib/tar/test/data/negative-mtime/gnu.tar b/lib/tar/test/data/negative-mtime/gnu.tar Binary files differnew file mode 100644 index 0000000..a9b1272 --- /dev/null +++ b/lib/tar/test/data/negative-mtime/gnu.tar diff --git a/lib/tar/test/data/negative-mtime/pax.tar b/lib/tar/test/data/negative-mtime/pax.tar Binary files differnew file mode 100644 index 0000000..d0b3e6c --- /dev/null +++ b/lib/tar/test/data/negative-mtime/pax.tar diff --git a/lib/tar/test/data/sparse-files/gnu-small.tar b/lib/tar/test/data/sparse-files/gnu-small.tar Binary files differnew file mode 100644 index 0000000..7a1b222 --- /dev/null +++ b/lib/tar/test/data/sparse-files/gnu-small.tar diff --git a/lib/tar/test/data/sparse-files/gnu.tar b/lib/tar/test/data/sparse-files/gnu.tar Binary files differnew file mode 100644 index 0000000..3d641a2 --- /dev/null +++ b/lib/tar/test/data/sparse-files/gnu.tar diff --git a/lib/tar/test/data/sparse-files/pax-gnu0-0.tar b/lib/tar/test/data/sparse-files/pax-gnu0-0.tar Binary files differnew file mode 100644 index 0000000..628f09e --- /dev/null +++ b/lib/tar/test/data/sparse-files/pax-gnu0-0.tar diff --git a/lib/tar/test/data/sparse-files/pax-gnu0-1.tar b/lib/tar/test/data/sparse-files/pax-gnu0-1.tar Binary files differnew file mode 100644 index 0000000..87e362e --- /dev/null +++ b/lib/tar/test/data/sparse-files/pax-gnu0-1.tar diff --git a/lib/tar/test/data/sparse-files/pax-gnu1-0.tar b/lib/tar/test/data/sparse-files/pax-gnu1-0.tar Binary files differnew file mode 100644 index 0000000..edb0ccf --- /dev/null +++ b/lib/tar/test/data/sparse-files/pax-gnu1-0.tar diff --git a/lib/tar/test/data/user-group-largenum/8-digit.tar b/lib/tar/test/data/user-group-largenum/8-digit.tar Binary files differnew file mode 100644 index 0000000..a48ea5d --- /dev/null +++ b/lib/tar/test/data/user-group-largenum/8-digit.tar diff --git a/lib/tar/test/data/user-group-largenum/gnu.tar b/lib/tar/test/data/user-group-largenum/gnu.tar Binary files differnew file mode 100644 index 0000000..4c30f57 --- /dev/null +++ b/lib/tar/test/data/user-group-largenum/gnu.tar diff --git a/lib/tar/test/data/user-group-largenum/pax.tar b/lib/tar/test/data/user-group-largenum/pax.tar Binary files differnew file mode 100644 index 0000000..a9fe54c --- /dev/null +++ b/lib/tar/test/data/user-group-largenum/pax.tar diff --git a/lib/tar/test/data/xattr/acl.tar b/lib/tar/test/data/xattr/acl.tar Binary files differnew file mode 100644 index 0000000..a65c0af --- /dev/null +++ b/lib/tar/test/data/xattr/acl.tar diff --git a/lib/tar/test/data/xattr/xattr-libarchive.tar b/lib/tar/test/data/xattr/xattr-libarchive.tar Binary files differnew file mode 100644 index 0000000..3bd6125 --- /dev/null +++ b/lib/tar/test/data/xattr/xattr-libarchive.tar diff --git a/lib/tar/test/data/xattr/xattr-schily-binary.tar b/lib/tar/test/data/xattr/xattr-schily-binary.tar Binary files differnew file mode 100644 index 0000000..0312807 --- /dev/null +++ b/lib/tar/test/data/xattr/xattr-schily-binary.tar diff --git a/lib/tar/test/data/xattr/xattr-schily.tar b/lib/tar/test/data/xattr/xattr-schily.tar Binary files differnew file mode 100644 index 0000000..1cf525c --- /dev/null +++ b/lib/tar/test/data/xattr/xattr-schily.tar diff --git a/lib/tar/test/tar_big_file.c b/lib/tar/test/tar_big_file.c new file mode 100644 index 0000000..deb41f4 --- /dev/null +++ b/lib/tar/test/tar_big_file.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_big_file.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "tar/tar.h" +#include "io/file.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + istream_t *fp; + (void)argc; (void)argv; + + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, 01750); + TEST_EQUAL_UI(hdr.gid, 01750); + TEST_EQUAL_UI(hdr.actual_size, 8589934592); + TEST_EQUAL_UI(hdr.mtime, 1542959190); + TEST_STR_EQUAL(hdr.name, "big-file.bin"); + TEST_ASSERT(!hdr.unknown_record); + clear_header(&hdr); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_fuzz.c b/lib/tar/test/tar_fuzz.c new file mode 100644 index 0000000..21e6978 --- /dev/null +++ b/lib/tar/test/tar_fuzz.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_fuzz.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "io/file.h" +#include "tar/tar.h" + +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + istream_t *fp; + int ret; + + if (argc != 2) { + fputs("usage: tar_fuzz <tarball>\n", stderr); + return EXIT_FAILURE; + } + + fp = istream_open_file(argv[1]); + if (fp == NULL) + return EXIT_FAILURE; + + for (;;) { + ret = read_header(fp, &hdr); + if (ret > 0) + break; + if (ret < 0) + goto fail; + + ret = istream_skip(fp, hdr.record_size); + + clear_header(&hdr); + if (ret < 0) + goto fail; + } + + sqfs_drop(fp); + return EXIT_SUCCESS; +fail: + sqfs_drop(fp); + return EXIT_FAILURE; +} diff --git a/lib/tar/test/tar_simple.c b/lib/tar/test/tar_simple.c new file mode 100644 index 0000000..cb38abb --- /dev/null +++ b/lib/tar/test/tar_simple.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_simple.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +#ifndef TESTUID +#define TESTUID 1000 +#endif + +#ifndef TESTGID +#define TESTGID TESTUID +#endif + +#ifndef TESTFNAME +#define TESTFNAME input.txt +#endif + +#ifndef TESTTS +#define TESTTS 1542905892 +#endif + +#ifdef LONG_NAME_TEST +static const char *fname = +"012345678901234567890123456789/012345678901234567890123456789/" +"012345678901234567890123456789/012345678901234567890123456789/" +"012345678901234567890123456789/input.txt"; +#else +static const char *fname = STRVALUE(TESTFNAME); +#endif + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + char buffer[6]; + sqfs_s64 ts; + istream_t *fp; + (void)argc; (void)argv; + + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, TESTUID); + TEST_EQUAL_UI(hdr.gid, TESTGID); + TEST_EQUAL_UI(hdr.actual_size, 5); + + ts = TESTTS; + TEST_EQUAL_UI(hdr.mtime, ts); + TEST_STR_EQUAL(hdr.name, fname); + TEST_ASSERT(!hdr.unknown_record); + + TEST_ASSERT(istream_read(fp, buffer, 5) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + clear_header(&hdr); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_sparse.c b/lib/tar/test/tar_sparse.c new file mode 100644 index 0000000..27ce053 --- /dev/null +++ b/lib/tar/test/tar_sparse.c @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_sparse.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +static void test_case_sparse(const char *path) +{ + tar_header_decoded_t hdr; + sparse_map_t *sparse; + istream_t *fp; + + fp = istream_open_file(path); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, 01750); + TEST_EQUAL_UI(hdr.gid, 01750); + TEST_EQUAL_UI(hdr.actual_size, 2097152); + TEST_EQUAL_UI(hdr.record_size, 32768); + TEST_STR_EQUAL(hdr.name, "input.bin"); + TEST_ASSERT(!hdr.unknown_record); + + sparse = hdr.sparse; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 0); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 262144); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 524288); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 786432); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 1048576); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 1310720); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 1572864); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 1835008); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 2097152); + TEST_EQUAL_UI(sparse->count, 0); + + sparse = sparse->next; + TEST_NULL(sparse); + + clear_header(&hdr); + sqfs_drop(fp); +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + test_case_sparse( STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE) ); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_sparse_gnu.c b/lib/tar/test/tar_sparse_gnu.c new file mode 100644 index 0000000..19ddd0a --- /dev/null +++ b/lib/tar/test/tar_sparse_gnu.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_sparse_gnu.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + sparse_map_t *sparse; + istream_t *fp; + (void)argc; (void)argv; + + TEST_ASSERT(chdir(TEST_PATH) == 0); + + fp = istream_open_file("sparse-files/gnu-small.tar"); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, 01750); + TEST_EQUAL_UI(hdr.gid, 01750); + TEST_EQUAL_UI(hdr.actual_size, 524288); + TEST_EQUAL_UI(hdr.record_size, 8192); + TEST_STR_EQUAL(hdr.name, "input.bin"); + TEST_ASSERT(!hdr.unknown_record); + + sparse = hdr.sparse; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 0); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 262144); + TEST_EQUAL_UI(sparse->count, 4096); + + sparse = sparse->next; + TEST_NOT_NULL(sparse); + TEST_EQUAL_UI(sparse->offset, 524288); + TEST_EQUAL_UI(sparse->count, 0); + + TEST_NULL(sparse->next); + + clear_header(&hdr); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_target_filled.c b/lib/tar/test/tar_target_filled.c new file mode 100644 index 0000000..abc6a47 --- /dev/null +++ b/lib/tar/test/tar_target_filled.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_target_filled.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + char buffer[16]; + istream_t *fp; + (void)argc; (void)argv; + + TEST_ASSERT(chdir(TEST_PATH) == 0); + + fp = istream_open_file("format-acceptance/link_filled.tar"); + TEST_NOT_NULL(fp); + + /* "deep" directory hierarchy containg 2 files */ + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04/" + "errored_file_tst"); + TEST_EQUAL_UI(hdr.actual_size, 5); + TEST_ASSERT(istream_read(fp, buffer, 5) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + TEST_ASSERT(skip_padding(fp, 5) == 0); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0777); + TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04/" + "some_test_file"); + TEST_EQUAL_UI(hdr.actual_size, 5); + TEST_ASSERT(istream_read(fp, buffer, 5) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + TEST_ASSERT(skip_padding(fp, 5) == 0); + clear_header(&hdr); + + /* "deep" directory hierarchy containg a hard link */ + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); + TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003/20CharsForLnkTest004/"); + clear_header(&hdr); + + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003/20CharsForLnkTest004/" + "01234567890123456789"); + TEST_ASSERT(hdr.is_hard_link); + + TEST_STR_EQUAL(hdr.link_target, "20_characters_here01/" + "20_characters_here02/20_characters_here03/" + "20_characters_here04/errored_file_tst"); + clear_header(&hdr); + + /* end of file */ + TEST_ASSERT(read_header(fp, &hdr) > 0); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_xattr.c b/lib/tar/test/tar_xattr.c new file mode 100644 index 0000000..122d1db --- /dev/null +++ b/lib/tar/test/tar_xattr.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_xattr.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + char buffer[6]; + istream_t *fp; + (void)argc; (void)argv; + + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, 01750); + TEST_EQUAL_UI(hdr.gid, 01750); + TEST_EQUAL_UI(hdr.actual_size, 5); + TEST_EQUAL_UI(hdr.mtime, 1543094477); + TEST_STR_EQUAL(hdr.name, "input.txt"); + TEST_ASSERT(!hdr.unknown_record); + TEST_ASSERT(istream_read(fp, buffer, 5) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + + TEST_NOT_NULL(hdr.xattr); + TEST_STR_EQUAL(hdr.xattr->key, "user.mime_type"); + TEST_STR_EQUAL((const char *)hdr.xattr->value, "text/plain"); + TEST_EQUAL_UI(hdr.xattr->value_len, 10); + TEST_NULL(hdr.xattr->next); + + clear_header(&hdr); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_xattr_bin.c b/lib/tar/test/tar_xattr_bin.c new file mode 100644 index 0000000..90443a1 --- /dev/null +++ b/lib/tar/test/tar_xattr_bin.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_xattr_bin.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" + +static const uint8_t value[] = { + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +int main(int argc, char **argv) +{ + tar_header_decoded_t hdr; + char buffer[6]; + istream_t *fp; + (void)argc; (void)argv; + + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + TEST_ASSERT(read_header(fp, &hdr) == 0); + TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); + TEST_EQUAL_UI(hdr.uid, 01750); + TEST_EQUAL_UI(hdr.gid, 01750); + TEST_EQUAL_UI(hdr.actual_size, 5); + TEST_EQUAL_UI(hdr.mtime, 1543094477); + TEST_STR_EQUAL(hdr.name, "input.txt"); + TEST_ASSERT(!hdr.unknown_record); + TEST_ASSERT(istream_read(fp, buffer, 5) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + + TEST_NOT_NULL(hdr.xattr); + TEST_STR_EQUAL(hdr.xattr->key, "security.capability"); + TEST_EQUAL_UI(hdr.xattr->value_len, sizeof(value)); + TEST_ASSERT(memcmp(hdr.xattr->value, value, sizeof(value)) == 0); + TEST_NULL(hdr.xattr->next); + + clear_header(&hdr); + sqfs_drop(fp); + return EXIT_SUCCESS; +} diff --git a/lib/util/Makemodule.am b/lib/util/Makemodule.am index 35e8078..0a0e50e 100644 --- a/lib/util/Makemodule.am +++ b/lib/util/Makemodule.am @@ -32,3 +32,55 @@ libutil_a_SOURCES += lib/util/src/mempool.c endif noinst_LIBRARIES += libutil.a + +test_str_table_SOURCES = lib/util/test/str_table.c +test_str_table_LDADD = libutil.a libio.a libcompat.a +test_str_table_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/lib/util/test + +test_rbtree_SOURCES = lib/util/test/rbtree.c +test_rbtree_LDADD = libutil.a libcompat.a + +test_xxhash_SOURCES = lib/util/test/xxhash.c +test_xxhash_LDADD = libutil.a libcompat.a + +test_threadpool_SOURCES = lib/util/test/threadpool.c +test_threadpool_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) +test_threadpool_CPPFLAGS = $(AM_CPPFLAGS) +test_threadpool_LDADD = libutil.a libcompat.a $(PTHREAD_LIBS) + +if HAVE_PTHREAD +test_threadpool_CPPFLAGS += -DHAVE_PTHREAD +endif + +test_ismemzero_SOURCES = lib/util/test/is_memory_zero.c +test_ismemzero_LDADD = libutil.a libcompat.a + +test_canonicalize_name_SOURCES = lib/util/test/canonicalize_name.c +test_canonicalize_name_LDADD = libutil.a libcompat.a + +test_filename_sane_SOURCES = lib/util/test/filename_sane.c +test_filename_sane_SOURCES += lib/util/src/filename_sane.c +test_filename_sane_LDADD = libcompat.a libutil.a + +test_filename_sane_w32_SOURCES = lib/util/test/filename_sane.c +test_filename_sane_w32_SOURCES += lib/util/src/filename_sane.c +test_filename_sane_w32_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_WIN32=1 +test_filename_sane_w32_LDADD = libcompat.a + +test_sdate_epoch_SOURCES = lib/util/test/epoch.c +test_sdate_epoch_LDADD = libutil.a libcompat.a + +test_hex_decode_SOURCES = lib/util/test/hex_decode.c +test_hex_decode_LDADD = libutil.a libcompat.a + +test_base64_decode_SOURCES = lib/util/test/base64_decode.c +test_base64_decode_LDADD = libutil.a libcompat.a + +LIBUTIL_TESTS = \ + test_str_table test_rbtree test_xxhash test_threadpool test_ismemzero \ + test_canonicalize_name test_filename_sane test_filename_sane_w32 \ + test_sdate_epoch test_hex_decode test_base64_decode + +check_PROGRAMS += $(LIBUTIL_TESTS) +TESTS += $(LIBUTIL_TESTS) +EXTRA_DIST += $(top_srcdir)/lib/util/test/words.txt diff --git a/lib/util/test/base64_decode.c b/lib/util/test/base64_decode.c new file mode 100644 index 0000000..8f22a86 --- /dev/null +++ b/lib/util/test/base64_decode.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * base64_decode.c + * + * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" + +static const struct { + int result; + const char *in; + const char *out; +} test_vec[] = { + { 0, "", "" }, + { 0, "Zg", "f" }, + { 0, "Zg==", "f" }, + { 0, "Zm8=", "fo" }, + { 0, "Zm9v", "foo" }, + { 0, "Zm9vYg==", "foob" }, + { 0, "Zm9vYmE=", "fooba" }, + { 0, "Zm9vYmFy", "foobar" }, + { 0, "TGV0J3MgYWxsIGxvdmUgTGFpbiEK", "Let's all love Lain!\n" }, + { -1, "Zg==X", "XX" }, +}; + +int main(int argc, char **argv) +{ + sqfs_u8 buffer[256]; + size_t i, j; + (void)argc; (void)argv; + + for (i = 0; i < sizeof(test_vec) / sizeof(test_vec[0]); ++i) { + const size_t in_len = strlen(test_vec[i].in); + const size_t out_len = strlen(test_vec[i].out); + size_t real_out; + int ret; + + /* initialize the buffer */ + for (j = 0; j < sizeof(buffer); ++j) { + buffer[j] = (j % 2) ? 0xAA : 0x55; + } + + /* convert */ + real_out = sizeof(buffer); + ret = base64_decode(test_vec[i].in, in_len, buffer, &real_out); + + /* make sure pattern is un-touched after expected offset */ + j = (in_len / 4) * 3; + if (in_len % 4) + j += 3; + + for (; j < sizeof(buffer); ++j) { + TEST_ASSERT(buffer[j] == ((j % 2) ? 0xAA : 0x55)); + } + + /* check result */ + if (test_vec[i].result == 0) { + TEST_ASSERT(ret == 0); + TEST_EQUAL_UI(real_out, out_len); + ret = memcmp(buffer, test_vec[i].out, out_len); + TEST_ASSERT(ret == 0); + } else { + TEST_ASSERT(ret != 0); + TEST_EQUAL_UI(real_out, 0); + } + + fprintf(stderr, "CASE %lu OK\n", (unsigned long)i); + } + + return EXIT_SUCCESS; +} + diff --git a/lib/util/test/canonicalize_name.c b/lib/util/test/canonicalize_name.c new file mode 100644 index 0000000..9f81b04 --- /dev/null +++ b/lib/util/test/canonicalize_name.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * canonicalize_name.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" + +static const struct { + const char *in; + const char *out; +} must_work[] = { + { "", "" }, + { "/", "" }, + { "\\", "\\" }, + { "///", "" }, + { "\\\\\\", "\\\\\\" }, + { "/\\//\\\\/", "\\/\\\\" }, + { "foo/bar/test", "foo/bar/test" }, + { "foo\\bar\\test", "foo\\bar\\test" }, + { "/foo/bar/test/", "foo/bar/test" }, + { "\\foo\\bar\\test\\", "\\foo\\bar\\test\\" }, + { "///foo//bar//test///", "foo/bar/test" }, + { "./foo/././bar/test/./.", "foo/bar/test" }, + { "./foo/././", "foo" }, + { ".", "" }, + { "./", "" }, + { "./.", "" }, + { "foo/.../bar", "foo/.../bar" }, + { "foo/.test/bar", "foo/.test/bar" }, +}; + +static const char *must_not_work[] = { + "..", + "foo/../bar", + "../foo/bar", + "foo/bar/..", + "foo/bar/../", +}; + +int main(int argc, char **argv) +{ + char buffer[512]; + size_t i; + (void)argc; (void)argv; + + for (i = 0; i < sizeof(must_work) / sizeof(must_work[0]); ++i) { + strcpy(buffer, must_work[i].in); + + if (canonicalize_name(buffer)) { + fprintf(stderr, "Test case rejected: '%s'\n", + must_work[i].in); + return EXIT_FAILURE; + } + + if (strcmp(buffer, must_work[i].out) != 0) { + fprintf(stderr, "Expected result: %s\n", + must_work[i].out); + fprintf(stderr, "Actual result: %s\n", buffer); + return EXIT_FAILURE; + } + } + + for (i = 0; i < sizeof(must_not_work) / sizeof(must_not_work[0]); ++i) { + strcpy(buffer, must_not_work[i]); + + if (canonicalize_name(buffer) == 0) { + fprintf(stderr, "Test case accepted: '%s'\n", + must_not_work[i]); + fprintf(stderr, "Transformed into: '%s'\n", buffer); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/lib/util/test/epoch.c b/lib/util/test/epoch.c new file mode 100644 index 0000000..a04942e --- /dev/null +++ b/lib/util/test/epoch.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * epoch.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" + +#if defined(_WIN32) || defined(__WINDOWS__) +static void setenv(const char *key, const char *value, int overwrite) +{ + char buffer[128]; + (void)overwrite; + + snprintf(buffer, sizeof(buffer) - 1, "%s=%s", key, value); + buffer[sizeof(buffer) - 1] = '\0'; + + _putenv(buffer); +} + +static void unsetenv(const char *key) +{ + setenv(key, "", 0); +} +#endif + +int main(int argc, char **argv) +{ + sqfs_u32 ts; + (void)argc; (void)argv; + + unsetenv("SOURCE_DATE_EPOCH"); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0); + + setenv("SOURCE_DATE_EPOCH", "1337", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 1337); + + setenv("SOURCE_DATE_EPOCH", "0xCAFE", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0); + + setenv("SOURCE_DATE_EPOCH", "foobar", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0); + + setenv("SOURCE_DATE_EPOCH", "-12", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0); + + setenv("SOURCE_DATE_EPOCH", "12", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 12); + + setenv("SOURCE_DATE_EPOCH", "4294967295", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0xFFFFFFFF); + + setenv("SOURCE_DATE_EPOCH", "4294967296", 1); + ts = get_source_date_epoch(); + TEST_EQUAL_UI(ts, 0); + + return EXIT_SUCCESS; +} diff --git a/lib/util/test/filename_sane.c b/lib/util/test/filename_sane.c new file mode 100644 index 0000000..9c9930d --- /dev/null +++ b/lib/util/test/filename_sane.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * filename_sane.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" + +static const char *must_work[] = { + "foobar", + "test.txt", +#if !defined(_WIN32) && !defined(__WINDOWS__) && !defined(TEST_WIN32) + "\\foo", "foo\\", "foo\\bar", +#endif + NULL, +}; + +static const char *must_not_work[] = { + ".", + "..", + "/foo", + "foo/", + "foo/bar", + NULL, +}; + +static const char *must_not_work_here[] = { +#if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) + "\\foo", "foo\\", "foo\\bar", + "fo<o", "fo>o", "fo:o", "fo\"o", + "fo|o", "fo?o", "fo*o", "fo\ro", + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "LPT1", "LPT2", + "con", "prn", "aux", "nul", + "com1", "com2", "lpt1", "lpt2", + "AUX.txt", "aux.txt", "NUL.txt", "nul.txt", +#endif + NULL, +}; + +int main(int argc, char **argv) +{ + size_t i; + (void)argc; (void)argv; + + for (i = 0; must_work[i] != NULL; ++i) { + if (!is_filename_sane(must_work[i], false)) { + fprintf(stderr, "%s was rejected!\n", must_work[i]); + return EXIT_FAILURE; + } + + if (!is_filename_sane(must_work[i], true)) { + fprintf(stderr, + "%s was rejected when testing for " + "OS specific stuff!\n", must_work[i]); + return EXIT_FAILURE; + } + } + + for (i = 0; must_not_work[i] != NULL; ++i) { + if (is_filename_sane(must_not_work[i], false)) { + fprintf(stderr, "%s was accepted!\n", + must_not_work[i]); + return EXIT_FAILURE; + } + + if (is_filename_sane(must_not_work[i], true)) { + fprintf(stderr, + "%s was accepted when testing for " + "OS specific stuff!\n", must_not_work[i]); + return EXIT_FAILURE; + } + } + + for (i = 0; must_not_work_here[i] != NULL; ++i) { + if (!is_filename_sane(must_not_work_here[i], false)) { + fprintf(stderr, + "%s was rejected in the generic test!\n", + must_not_work_here[i]); + return EXIT_FAILURE; + } + + if (is_filename_sane(must_not_work_here[i], true)) { + fprintf(stderr, + "%s was accepted when testing for " + "OS specific stuff!\n", must_not_work_here[i]); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/lib/util/test/hex_decode.c b/lib/util/test/hex_decode.c new file mode 100644 index 0000000..21ac4e7 --- /dev/null +++ b/lib/util/test/hex_decode.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * hex_decode.c + * + * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" + +static const struct { + int result; + const char *in; + const char *out; +} test_vec[] = { + { 0, "", NULL }, + { -1, "A", NULL }, + { 0, "AA", "\xAA" }, + { 0, "0A", "\x0A" }, + { 0, "A0", "\xA0" }, + { -1, "A0B", NULL }, + { 0, "A0BC", "\xA0\xBC" }, + { 0, "0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF" }, + { 0, "0123456789abcdef", "\x01\x23\x45\x67\x89\xAB\xCD\xEF" }, + { -1, "0123456789ABCDEFGH", NULL }, + { -1, "0123456789abcdefgh", NULL }, +}; + +int main(int argc, char **argv) +{ + sqfs_u8 buffer[256]; + size_t i, j; + (void)argc; (void)argv; + + for (i = 0; i < sizeof(test_vec) / sizeof(test_vec[0]); ++i) { + size_t in_len = strlen(test_vec[i].in); + size_t out_len = in_len / 2; + int ret; + + /* initialize the buffer */ + for (j = 0; j < sizeof(buffer); ++j) { + buffer[j] = (j % 2) ? 0xAA : 0x55; + } + + /* convert */ + ret = hex_decode(test_vec[i].in, in_len, + buffer, sizeof(buffer)); + + /* make sure pattern is un-touched after expected offset */ + for (j = out_len; j < sizeof(buffer); ++j) { + TEST_ASSERT(buffer[j] == ((j % 2) ? 0xAA : 0x55)); + } + + /* check result */ + if (test_vec[i].result == 0) { + TEST_ASSERT(ret == 0); + ret = memcmp(buffer, test_vec[i].out, out_len); + TEST_ASSERT(ret == 0); + } else { + TEST_ASSERT(ret != 0); + } + } + + return EXIT_SUCCESS; +} + diff --git a/lib/util/test/is_memory_zero.c b/lib/util/test/is_memory_zero.c new file mode 100644 index 0000000..f62b0bb --- /dev/null +++ b/lib/util/test/is_memory_zero.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * is_memory_zero.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "util/test.h" +#include "util/util.h" + +int main(int argc, char **argv) +{ + unsigned char temp[1024]; + size_t i, j; + (void)argc; (void)argv; + + memset(temp, 0, sizeof(temp)); + + for (i = 0; i < sizeof(temp); ++i) { + TEST_ASSERT(is_memory_zero(temp, i)); + + for (j = 0; j < i; ++j) { + TEST_ASSERT(is_memory_zero(temp, i)); + temp[j] = 42; + TEST_ASSERT(!is_memory_zero(temp, i)); + temp[j] = 0; + TEST_ASSERT(is_memory_zero(temp, i)); + } + } + + return EXIT_SUCCESS; +} diff --git a/lib/util/test/rbtree.c b/lib/util/test/rbtree.c new file mode 100644 index 0000000..ca01c0d --- /dev/null +++ b/lib/util/test/rbtree.c @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * rbtree.c + * + * Copyright (C) 2020 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "util/rbtree.h" +#include "util/test.h" + +static int key_compare(const void *ctx, const void *a, const void *b) +{ + (void)ctx; + return *((const sqfs_s32 *)a) - *((const sqfs_s32 *)b); +} + +static size_t count_nodes_dfs(rbtree_node_t *n) +{ + return 1 + (n->left == NULL ? 0 : count_nodes_dfs(n->left)) + + (n->right == NULL ? 0 : count_nodes_dfs(n->right)); +} + +static size_t min_depth(rbtree_node_t *n) +{ + size_t lhs, rhs; + + if (n == NULL) + return 0; + + lhs = min_depth(n->left) + 1; + rhs = min_depth(n->right) + 1; + + return lhs < rhs ? lhs : rhs; +} + +static size_t max_depth(rbtree_node_t *n) +{ + size_t lhs, rhs; + + if (n == NULL) + return 0; + + lhs = min_depth(n->left) + 1; + rhs = min_depth(n->right) + 1; + + return lhs > rhs ? lhs : rhs; +} + +static size_t get_ref_black_depth(rbtree_t *rb) +{ + rbtree_node_t *n; + size_t count = 0; + + for (n = rb->root; n != NULL; n = n->left) { + if (!n->is_red) + count += 1; + } + + return count; +} + +static void check_binary_tree_dfs(rbtree_node_t *n) +{ + const void *key = rbtree_node_key(n); + const void *cmp; + + if (n->left != NULL) { + cmp = rbtree_node_key(n->left); + TEST_ASSERT(key_compare(NULL, cmp, key) < 0); + + check_binary_tree_dfs(n->left); + } + + if (n->right != NULL) { + cmp = rbtree_node_key(n->right); + TEST_ASSERT(key_compare(NULL, cmp, key) > 0); + + check_binary_tree_dfs(n->right); + } +} + +static void check_colors_dfs(rbtree_node_t *n) +{ + if (n->is_red) { + TEST_ASSERT(n->left == NULL || !n->left->is_red); + TEST_ASSERT(n->right == NULL || !n->right->is_red); + } + + if (n->left != NULL) + check_colors_dfs(n->left); + + if (n->right != NULL) + check_colors_dfs(n->right); +} + +static void check_black_depth_dfs(rbtree_node_t *n, size_t ref, + size_t counter) +{ + if (!n->is_red) + counter += 1; + + if (n->left == NULL || n->right == NULL) + TEST_EQUAL_UI(counter, ref); + + if (n->left != NULL) + check_black_depth_dfs(n->left, ref, counter); + + if (n->right != NULL) + check_black_depth_dfs(n->right, ref, counter); +} + +static int check_subtrees_equal(const rbtree_node_t *lhs, + const rbtree_node_t *rhs, + size_t datasize) +{ + if (lhs == rhs) + return -1; + + if (lhs->value_offset != rhs->value_offset) + return -1; + + if ((lhs->is_red && !rhs->is_red) || (!lhs->is_red && rhs->is_red)) + return -1; + + if (memcmp(lhs->data, rhs->data, datasize) != 0) + return -1; + + if (lhs->left == NULL) { + if (rhs->left != NULL) + return -1; + } else { + if (rhs->left == NULL) + return -1; + + if (check_subtrees_equal(lhs->left, rhs->left, datasize)) + return -1; + } + + if (lhs->right == NULL) { + if (rhs->right != NULL) + return -1; + } else { + if (rhs->right == NULL) + return -1; + + if (check_subtrees_equal(lhs->right, rhs->right, datasize)) + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + size_t count, blkdepth, mind, maxd; + sqfs_s32 key, key2; + rbtree_t rb, copy; + rbtree_node_t *n; + sqfs_u64 value; + int ret; + (void)argc; (void)argv; + + TEST_ASSERT(rbtree_init(&rb, sizeof(sqfs_s32), + sizeof(sqfs_u64), key_compare) == 0); + + count = 0; + + for (key = -1000; key < 1000; ++key) { + /* lookup of current key must fail prior to insert */ + TEST_NULL(rbtree_lookup(&rb, &key)); + + /* previous key/value pairs must still be there */ + for (key2 = -1000; key2 < key; ++key2) { + n = rbtree_lookup(&rb, &key2); + TEST_NOT_NULL(n); + value = *((sqfs_u64 *)rbtree_node_value(n)); + TEST_EQUAL_UI((sqfs_u64)(key2 + 10000), value); + } + + /* insert key value pair */ + value = key + 10000; + TEST_ASSERT(rbtree_insert(&rb, &key, &value) == 0); + count += 1; + + /* check if the tree has the right number of nodes */ + TEST_EQUAL_UI(count_nodes_dfs(rb.root), count); + + /* check if it is still a binary tree */ + check_binary_tree_dfs(rb.root); + + /* root node must be black. Every red node + must have black children. */ + TEST_ASSERT(!rb.root->is_red); + check_colors_dfs(rb.root); + + /* every path from the root to a leave must have + the same number of black nodes. */ + blkdepth = get_ref_black_depth(&rb); + check_black_depth_dfs(rb.root, blkdepth, 0); + + /* longest root to leaf path must be at most + twice as long as the shortest. */ + mind = min_depth(rb.root); + maxd = max_depth(rb.root); + TEST_ASSERT(maxd <= mind * 2); + + /* lookup of current key must work after insert */ + n = rbtree_lookup(&rb, &key); + TEST_NOT_NULL(n); + value = *((sqfs_u64 *)rbtree_node_value(n)); + TEST_EQUAL_UI((sqfs_u64)(key + 10000), value); + } + + /* test if copy works */ + ret = rbtree_copy(&rb, ©); + TEST_EQUAL_I(ret, 0); + + TEST_EQUAL_UI(rb.key_size, copy.key_size); + TEST_EQUAL_UI(rb.key_size_padded, copy.key_size_padded); + TEST_EQUAL_UI(rb.value_size, copy.value_size); + TEST_ASSERT(rb.key_compare == copy.key_compare); + TEST_ASSERT(rb.root != copy.root); + + ret = check_subtrees_equal(rb.root, copy.root, + rb.key_size_padded + rb.value_size); + TEST_EQUAL_I(ret, 0); + + /* cleanup */ + rbtree_cleanup(&rb); + rbtree_cleanup(©); + return EXIT_SUCCESS; +} diff --git a/lib/util/test/str_table.c b/lib/util/test/str_table.c new file mode 100644 index 0000000..d4160eb --- /dev/null +++ b/lib/util/test/str_table.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * str_table.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "util/str_table.h" +#include "io/file.h" +#include "compat.h" +#include "util/test.h" + +static char *strings[1000]; + +static int read_strings(void) +{ + istream_t *fp; + ssize_t ret; + char *line; + int i; + + fp = istream_open_file("words.txt"); + TEST_NOT_NULL(fp); + + for (i = 0; i < 1000; ++i) { + ret = istream_get_line(fp, &line, NULL, 0); + TEST_EQUAL_I(ret, 0); + + strings[i] = line; + } + + sqfs_drop(fp); + return 0; +} + +int main(int argc, char **argv) +{ + str_table_t table; + size_t i, j, idx; + const char *str; + (void)argc; (void)argv; + + TEST_ASSERT(chdir(TEST_PATH) == 0); + + if (read_strings()) + return EXIT_FAILURE; + + TEST_ASSERT(str_table_init(&table) == 0); + + for (i = 0; i < 1000; ++i) { + TEST_ASSERT(str_table_get_index(&table, strings[i], &idx) == 0); + + TEST_EQUAL_UI(idx, i); + + for (j = 0; j <= i; ++j) { + str = str_table_get_string(&table, j); + + TEST_NOT_NULL(str); + TEST_ASSERT(str != strings[i]); + TEST_STR_EQUAL(str, strings[j]); + } + + for (; j < 1000; ++j) + TEST_NULL(str_table_get_string(&table, j)); + } + + for (i = 0; i < 1000; ++i) { + TEST_ASSERT(str_table_get_index(&table, strings[i], &idx) == 0); + TEST_EQUAL_UI(idx, i); + + str = str_table_get_string(&table, i); + + TEST_NOT_NULL(str); + TEST_ASSERT(str != strings[i]); + TEST_STR_EQUAL(str, strings[i]); + } + + str_table_cleanup(&table); + + for (i = 0; i < 1000; ++i) + free(strings[i]); + + return EXIT_SUCCESS; +} diff --git a/lib/util/test/threadpool.c b/lib/util/test/threadpool.c new file mode 100644 index 0000000..cf54484 --- /dev/null +++ b/lib/util/test/threadpool.c @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * threadpool.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "util/threadpool.h" +#include "util/test.h" + +#if defined(_WIN32) || defined(__WINDOWS__) +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRALEAN +#include <windows.h> + +static CRITICAL_SECTION mutex; +static unsigned int ticket; + +static void ticket_init(void) +{ + InitializeCriticalSection(&mutex); + ticket = 0; +} + +static void ticket_cleanup(void) +{ + DeleteCriticalSection(&mutex); + ticket = 0; +} + +static void ticket_wait(unsigned int value) +{ + for (;;) { + EnterCriticalSection(&mutex); + + if (value == ticket) { + ticket += 1; + LeaveCriticalSection(&mutex); + break; + } + + LeaveCriticalSection(&mutex); + SwitchToThread(); + } +} +#elif defined(HAVE_PTHREAD) +#include <pthread.h> + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned int ticket; + +static void ticket_init(void) +{ + ticket = 0; +} + +static void ticket_cleanup(void) +{ +} + +static void ticket_wait(unsigned int value) +{ + for (;;) { + pthread_mutex_lock(&mutex); + + if (value == ticket) { + ticket += 1; + pthread_mutex_unlock(&mutex); + break; + } + + pthread_mutex_unlock(&mutex); + sched_yield(); + } +} +#else +static void ticket_init(void) +{ +} + +static void ticket_cleanup(void) +{ +} + +static void ticket_wait(unsigned int value) +{ + (void)value; +} +#endif + +static int worker(void *user, void *work_item) +{ + unsigned int value = *((unsigned int *)work_item); + (void)user; + + ticket_wait(value); + + *((unsigned int *)work_item) = 42; + return 0; +} + +static int worker_serial(void *user, void *work_item) +{ + (void)user; + *((unsigned int *)work_item) = 42; + return 0; +} + +static void test_case(thread_pool_t *pool) +{ + unsigned int values[10]; + unsigned int *ptr; + size_t i, count; + int ret; + + /* must return a sane value */ + count = pool->get_worker_count(pool); + TEST_ASSERT(count >= 1); + + /* dequeue on empty pool MUST NOT lock up */ + ptr = pool->dequeue(pool); + TEST_NULL(ptr); + + /* submit work items in reverse order */ + ticket_init(); + + for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) { + values[i] = (sizeof(values) / sizeof(values[0]) - 1) - i; + + ret = pool->submit(pool, values + i); + TEST_EQUAL_I(ret, 0); + } + + /* items must dequeue in the same order */ + for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) { + ptr = pool->dequeue(pool); + + TEST_NOT_NULL(ptr); + TEST_ASSERT(ptr == (values + i)); + TEST_EQUAL_UI(*ptr, 42); + } + + ticket_cleanup(); + + /* queue now empty */ + ptr = pool->dequeue(pool); + TEST_NULL(ptr); +} + +int main(int argc, char **argv) +{ + thread_pool_t *pool; + (void)argc; (void)argv; + + /* test the actual parallel implementation */ + pool = thread_pool_create(10, worker); + TEST_NOT_NULL(pool); + test_case(pool); + pool->destroy(pool); + + /* repeate the test with the serial reference implementation */ + pool = thread_pool_create_serial(worker_serial); + TEST_NOT_NULL(pool); + test_case(pool); + pool->destroy(pool); + return EXIT_SUCCESS; +} diff --git a/lib/util/test/words.txt b/lib/util/test/words.txt new file mode 100644 index 0000000..9496e14 --- /dev/null +++ b/lib/util/test/words.txt @@ -0,0 +1,1000 @@ +a +ability +able +about +above +accept +according +account +across +act +action +activity +actually +add +address +administration +admit +adult +affect +after +again +against +age +agency +agent +ago +agree +agreement +ahead +air +all +allow +almost +alone +along +already +also +although +always +American +among +amount +analysis +and +animal +another +answer +any +anyone +anything +appear +apply +approach +area +argue +arm +around +arrive +art +article +artist +as +ask +assume +at +attack +attention +attorney +audience +author +authority +available +avoid +away +baby +back +bad +bag +ball +bank +bar +base +be +beat +beautiful +because +become +bed +before +begin +behavior +behind +believe +benefit +best +better +between +beyond +big +bill +billion +bit +black +blood +blue +board +body +book +born +both +box +boy +break +bring +brother +budget +build +building +business +but +buy +by +call +camera +campaign +can +cancer +candidate +capital +car +card +care +career +carry +case +catch +cause +cell +center +central +century +certain +certainly +chair +challenge +chance +change +character +charge +check +child +choice +choose +church +citizen +city +civil +claim +class +clear +clearly +close +coach +cold +collection +college +color +come +commercial +common +community +company +compare +computer +concern +condition +conference +Congress +consider +consumer +contain +continue +control +cost +could +country +couple +course +court +cover +create +crime +cultural +culture +cup +current +customer +cut +dark +data +daughter +day +dead +deal +death +debate +decade +decide +decision +deep +defense +degree +Democrat +democratic +describe +design +despite +detail +determine +develop +development +die +difference +different +difficult +dinner +direction +director +discover +discuss +discussion +disease +do +doctor +dog +door +down +draw +dream +drive +drop +drug +during +each +early +east +easy +eat +economic +economy +edge +education +effect +effort +eight +either +election +else +employee +end +energy +enjoy +enough +enter +entire +environment +environmental +especially +establish +even +evening +event +ever +every +everybody +everyone +everything +evidence +exactly +example +executive +exist +expect +experience +expert +explain +eye +face +fact +factor +fail +fall +family +far +fast +father +fear +federal +feel +feeling +few +field +fight +figure +fill +film +final +finally +financial +find +fine +finger +finish +fire +firm +first +fish +five +floor +fly +focus +follow +food +foot +for +force +foreign +forget +form +former +forward +four +free +friend +from +front +full +fund +future +game +garden +gas +general +generation +get +girl +give +glass +go +goal +good +government +great +green +ground +group +grow +growth +guess +gun +guy +hair +half +hand +hang +happen +happy +hard +have +he +head +health +hear +heart +heat +heavy +help +her +here +herself +high +him +himself +his +history +hit +hold +home +hope +hospital +hot +hotel +hour +house +how +however +huge +human +hundred +husband +I +idea +identify +if +image +imagine +impact +important +improve +in +include +including +increase +indeed +indicate +individual +industry +information +inside +instead +institution +interest +interesting +international +interview +into +investment +involve +issue +it +item +its +itself +job +join +just +keep +key +kid +kill +kind +kitchen +know +knowledge +land +language +large +last +late +later +laugh +law +lawyer +lay +lead +leader +learn +least +leave +left +leg +legal +less +let +letter +level +lie +life +light +like +likely +line +list +listen +little +live +local +long +look +lose +loss +lot +love +low +machine +magazine +main +maintain +major +majority +make +man +manage +management +manager +many +market +marriage +material +matter +may +maybe +me +mean +measure +media +medical +meet +meeting +member +memory +mention +message +method +middle +might +military +million +mind +minute +miss +mission +model +modern +moment +money +month +more +morning +most +mother +mouth +move +movement +movie +Mr +Mrs +much +music +must +my +myself +name +nation +national +natural +nature +near +nearly +necessary +need +network +never +new +news +newspaper +next +nice +night +no +none +nor +north +not +note +nothing +notice +now +n't +number +occur +of +off +offer +office +officer +official +often +oh +oil +ok +old +on +once +one +only +onto +open +operation +opportunity +option +or +order +organization +other +others +our +out +outside +over +own +owner +page +pain +painting +paper +parent +part +participant +particular +particularly +partner +party +pass +past +patient +pattern +pay +peace +people +per +perform +performance +perhaps +period +person +personal +phone +physical +pick +picture +piece +place +plan +plant +play +player +PM +point +police +policy +political +politics +poor +popular +population +position +positive +possible +power +practice +prepare +present +president +pressure +pretty +prevent +price +private +probably +problem +process +produce +product +production +professional +professor +program +project +property +protect +prove +provide +public +pull +purpose +push +put +quality +question +quickly +quite +race +radio +raise +range +rate +rather +reach +read +ready +real +reality +realize +really +reason +receive +recent +recently +recognize +record +red +reduce +reflect +region +relate +relationship +religious +remain +remember +remove +report +represent +Republican +require +research +resource +respond +response +responsibility +rest +result +return +reveal +rich +right +rise +risk +road +rock +role +room +rule +run +safe +same +save +say +scene +school +science +scientist +score +sea +season +seat +second +section +security +see +seek +seem +sell +send +senior +sense +series +serious +serve +service +set +seven +several +sex +sexual +shake +share +she +shoot +short +shot +should +shoulder +show +side +sign +significant +similar +simple +simply +since +sing +single +sister +sit +site +situation +six +size +skill +skin +small +smile +so +social +society +soldier +some +somebody +someone +something +sometimes +son +song +soon +sort +sound +source +south +southern +space +speak +special +specific +speech +spend +sport +spring +staff +stage +stand +standard +star +start +state +statement +station +stay +step +still +stock +stop +store +story +strategy +street +strong +structure +student +study +stuff +style +subject +success +successful +such +suddenly +suffer +suggest +summer +support +sure +surface +system +table +take +talk +task +tax +teach +teacher +team +technology +television +tell +ten +tend +term +test +than +thank +that +the +their +them +themselves +then +theory +there +these +they +thing +think +third +this +those +though +thought +thousand +threat +three +through +throughout +throw +thus +time +to +today +together +tonight +too +top +total +tough +toward +town +trade +traditional +training +travel +treat +treatment +tree +trial +trip +trouble +true +truth +try +turn +TV +two +type +under +understand +unit +until +up +upon +us +use +usually +value +various +very +victim +view +violence +visit +voice +vote +wait +walk +wall +want +war +watch +water +way +we +weapon +wear +week +weight +well +west +western +what +whatever +when +where +whether +which +while +white +who +whole +whom +whose +why +wide +wife +will +win +wind +window +wish +with +within +without +woman +wonder +word +work +worker +world +worry +would +write +writer +wrong +yard +yeah +year +yes +yet +you +young +your +yourself diff --git a/lib/util/test/xxhash.c b/lib/util/test/xxhash.c new file mode 100644 index 0000000..17374fd --- /dev/null +++ b/lib/util/test/xxhash.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * xxhash.c + * + * Copyright (C) 2020 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "util/util.h" +#include "util/test.h" + +static const struct { + const char *plaintext; + size_t psize; + sqfs_u32 digest; +} test_vectors[] = { + { + .plaintext = "\x9e", + .psize = 1, + .digest = 0xB85CBEE5, + }, + { + .plaintext = "\x9e\xff\x1f\x4b\x5e\x53\x2f\xdd" + "\xb5\x54\x4d\x2a\x95\x2b", + .psize = 14, + .digest = 0xE5AA0AB4, + }, + { + .plaintext = "\x9e\xff\x1f\x4b\x5e\x53\x2f\xdd" + "\xb5\x54\x4d\x2a\x95\x2b\x57\xae" + "\x5d\xba\x74\xe9\xd3\xa6\x4c\x98" + "\x30\x60\xc0\x80\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00", + .psize = 101, + .digest = 0x018F52BC, + }, +}; + +int main(int argc, char **argv) +{ + sqfs_u32 hash; + size_t i; + (void)argc; (void)argv; + + for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); ++i) { + hash = xxh32(test_vectors[i].plaintext, test_vectors[i].psize); + + if (hash != test_vectors[i].digest) { + fprintf(stderr, "Test case " PRI_SZ " failed!\n", i); + fprintf(stderr, "Expected result: 0x%08X\n", + test_vectors[i].digest); + fprintf(stderr, "Actual result: 0x%08X\n", hash); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/lib/xfrm/Makemodule.am b/lib/xfrm/Makemodule.am index ad446f6..a517df7 100644 --- a/lib/xfrm/Makemodule.am +++ b/lib/xfrm/Makemodule.am @@ -1,3 +1,6 @@ +LIBXFRM_LIBS = $(ZLIB_LIBS) $(XZ_LIBS) $(BZIP2_LIBS) $(ZSTD_LIBS) +LIBXFRM_TESTS = + libxfrm_a_SOURCES = include/xfrm/stream.h include/xfrm/compress.h \ lib/xfrm/src/compress.c libxfrm_a_CFLAGS = $(AM_CFLAGS) @@ -5,23 +8,66 @@ libxfrm_a_CFLAGS = $(AM_CFLAGS) if WITH_XZ libxfrm_a_SOURCES += lib/xfrm/src/xz.c libxfrm_a_CFLAGS += $(XZ_CFLAGS) -DWITH_XZ + +test_unpack_xz_SOURCES = lib/xfrm/test/unpack.c +test_unpack_xz_LDADD = libxfrm.a $(XZ_LIBS) +test_unpack_xz_CPPFLAGS = $(AM_CPPFLAGS) -DDO_XZ=1 + +test_pack_xz_SOURCES = lib/xfrm/test/pack.c +test_pack_xz_LDADD = libxfrm.a $(LIBXFRM_LIBS) +test_pack_xz_CPPFLAGS = $(AM_CPPFLAGS) -DDO_XZ=1 + +LIBXFRM_TESTS += test_pack_xz test_unpack_xz endif if WITH_BZIP2 libxfrm_a_SOURCES += lib/xfrm/src/bzip2.c libxfrm_a_CFLAGS += $(BZIP2_CFLAGS) -DWITH_BZIP2 + +test_unpack_bzip2_SOURCES = lib/xfrm/test/unpack.c +test_unpack_bzip2_LDADD = libxfrm.a $(BZIP2_LIBS) +test_unpack_bzip2_CPPFLAGS = $(AM_CPPFLAGS) -DDO_BZIP2=1 + +test_pack_bzip2_SOURCES = lib/xfrm/test/pack.c +test_pack_bzip2_LDADD = libxfrm.a $(LIBXFRM_LIBS) +test_pack_bzip2_CPPFLAGS = $(AM_CPPFLAGS) -DDO_BZIP2=1 + +LIBXFRM_TESTS += test_unpack_bzip2 test_pack_bzip2 endif if WITH_GZIP libxfrm_a_SOURCES += lib/xfrm/src/gzip.c libxfrm_a_CFLAGS += $(ZLIB_CFLAGS) -DWITH_GZIP + +test_unpack_gzip_SOURCES = lib/xfrm/test/unpack.c +test_unpack_gzip_LDADD = libxfrm.a $(ZLIB_LIBS) +test_unpack_gzip_CPPFLAGS = $(AM_CPPFLAGS) -DDO_GZIP=1 + +test_pack_gzip_SOURCES = lib/xfrm/test/pack.c +test_pack_gzip_LDADD = libxfrm.a $(LIBXFRM_LIBS) +test_pack_gzip_CPPFLAGS = $(AM_CPPFLAGS) -DDO_GZIP=1 + +LIBXFRM_TESTS += test_pack_gzip test_unpack_gzip endif if WITH_ZSTD if HAVE_ZSTD_STREAM libxfrm_a_SOURCES += lib/xfrm/src/zstd.c libxfrm_a_CFLAGS += $(ZSTD_CFLAGS) -DWITH_ZSTD + +test_pack_zstd_SOURCES = lib/xfrm/test/unpack.c +test_pack_zstd_LDADD = libxfrm.a $(ZSTD_LIBS) +test_pack_zstd_CPPFLAGS = $(AM_CPPFLAGS) -DDO_ZSTD=1 + +test_unpack_zstd_SOURCES = lib/xfrm/test/pack.c +test_unpack_zstd_LDADD = libxfrm.a $(LIBXFRM_LIBS) +test_unpack_zstd_CPPFLAGS = $(AM_CPPFLAGS) -DDO_ZSTD=1 + +LIBXFRM_TESTS += test_pack_zstd test_unpack_zstd endif endif noinst_LIBRARIES += libxfrm.a + +check_PROGRAMS += $(LIBXFRM_TESTS) +TESTS += $(LIBXFRM_TESTS) diff --git a/lib/xfrm/test/pack.c b/lib/xfrm/test/pack.c new file mode 100644 index 0000000..c297005 --- /dev/null +++ b/lib/xfrm/test/pack.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * compress.c + * + * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at> + */ +#include "xfrm/compress.h" +#include "xfrm/stream.h" +#include "util/test.h" + +static const char text[] = +"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n" +"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n" +"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n" +"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n" +"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n" +"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"; + +static sqfs_u8 buffer_cmp[1024]; +static sqfs_u8 buffer_plain[1024]; +static sqfs_u8 ref_cmp[1024]; +static size_t ref_size; + +#if defined(DO_BZIP2) +#define mkdecompressor decompressor_stream_bzip2_create +#define mkcompressor compressor_stream_bzip2_create + +static sqfs_u8 magic[3] = "BZh"; +static int comp_id = XFRM_COMPRESSOR_BZIP2; +static const char *comp_name = "bzip2"; +#elif defined(DO_XZ) +#define mkdecompressor decompressor_stream_xz_create +#define mkcompressor compressor_stream_xz_create + +static sqfs_u8 magic[6] = "\xFD" "7zXZ"; +static int comp_id = XFRM_COMPRESSOR_XZ; +static const char *comp_name = "xz"; +#elif defined(DO_GZIP) +#define mkdecompressor decompressor_stream_gzip_create +#define mkcompressor compressor_stream_gzip_create + +static sqfs_u8 magic[3] = "\x1F\x8B\x08"; +static int comp_id = XFRM_COMPRESSOR_GZIP; +static const char *comp_name = "gzip"; +#elif defined(DO_ZSTD) +#define mkdecompressor decompressor_stream_zstd_create +#define mkcompressor compressor_stream_zstd_create + +static sqfs_u8 magic[4] = "\x28\xB5\x2F\xFD"; +static int comp_id = XFRM_COMPRESSOR_ZSTD; +static const char *comp_name = "zstd"; +#else +#error build configuration broken +#endif + +int main(int argc, char **argv) +{ + sqfs_u32 in_diff = 0, out_diff = 0; + xfrm_stream_t *xfrm; + const char *str; + size_t size; + int ret; + (void)argc; (void)argv; + + /* generic name/ID API */ + ret = xfrm_compressor_id_from_name(comp_name); + TEST_EQUAL_I(ret, comp_id); + + str = xfrm_compressor_name_from_id(ret); + TEST_STR_EQUAL(str, comp_name); + + /* compress the original text */ + xfrm = mkcompressor(NULL); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + ret = xfrm->process_data(xfrm, text, sizeof(text), + buffer_cmp, sizeof(buffer_cmp), + &in_diff, &out_diff, XFRM_STREAM_FLUSH_FULL); + TEST_EQUAL_I(ret, XFRM_STREAM_END); + + TEST_EQUAL_UI(in_diff, sizeof(text)); + TEST_ASSERT(out_diff > 0); + TEST_ASSERT(out_diff < sizeof(text)); + + sqfs_drop(xfrm); + + size = out_diff; + in_diff = out_diff = 0; + + memcpy(ref_cmp, buffer_cmp, size); + ref_size = size; + + /* check if it has the expected magic number */ + TEST_ASSERT(size >= sizeof(magic)); + ret = memcmp(buffer_cmp, magic, sizeof(magic)); + TEST_EQUAL_I(ret, 0); + + /* check if the auto detection correctly identifies it */ + ret = xfrm_compressor_id_from_magic(buffer_cmp, size); + TEST_EQUAL_I(ret, comp_id); + + ret = xfrm_compressor_id_from_magic(text, sizeof(text)); + TEST_EQUAL_I(ret, -1); + + /* unpack the compressed text and compare to the original */ + xfrm = mkdecompressor(); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + ret = xfrm->process_data(xfrm, buffer_cmp, size, + buffer_plain, sizeof(buffer_plain), + &in_diff, &out_diff, 0); + TEST_ASSERT(ret == XFRM_STREAM_END || ret == XFRM_STREAM_OK); + + TEST_EQUAL_UI(in_diff, size); + TEST_EQUAL_UI(out_diff, sizeof(text)); + ret = memcmp(buffer_plain, text, out_diff); + TEST_EQUAL_I(ret, 0); + + sqfs_drop(xfrm); + in_diff = out_diff = 0; + + /* retry packing but create the compressor using the ID */ + memset(buffer_cmp, 0, sizeof(buffer_cmp)); + memset(buffer_plain, 0, sizeof(buffer_plain)); + + xfrm = compressor_stream_create(comp_id, NULL); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + ret = xfrm->process_data(xfrm, text, sizeof(text), + buffer_cmp, sizeof(buffer_cmp), + &in_diff, &out_diff, XFRM_STREAM_FLUSH_FULL); + TEST_EQUAL_I(ret, XFRM_STREAM_END); + + TEST_EQUAL_UI(in_diff, sizeof(text)); + TEST_EQUAL_UI(out_diff, ref_size); + + sqfs_drop(xfrm); + size = out_diff; + in_diff = out_diff = 0; + + /* make sure we got an identical result */ + ret = memcmp(ref_cmp, buffer_cmp, size); + TEST_EQUAL_I(ret, 0); + + /* decompress it using ID */ + xfrm = decompressor_stream_create(comp_id); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + ret = xfrm->process_data(xfrm, buffer_cmp, size, + buffer_plain, sizeof(buffer_plain), + &in_diff, &out_diff, 0); + TEST_ASSERT(ret == XFRM_STREAM_END || ret == XFRM_STREAM_OK); + + TEST_EQUAL_UI(in_diff, size); + TEST_EQUAL_UI(out_diff, sizeof(text)); + ret = memcmp(buffer_plain, text, out_diff); + TEST_EQUAL_I(ret, 0); + + sqfs_drop(xfrm); + return EXIT_SUCCESS; +} diff --git a/lib/xfrm/test/unpack.c b/lib/xfrm/test/unpack.c new file mode 100644 index 0000000..ca51f10 --- /dev/null +++ b/lib/xfrm/test/unpack.c @@ -0,0 +1,428 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * unpack.c + * + * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at> + */ +#include "xfrm/compress.h" +#include "xfrm/stream.h" +#include "util/test.h" + +static const sqfs_u8 blob_in[] = { +#if defined(DO_XZ) + 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, + 0xff, 0x12, 0xd9, 0x41, 0x02, 0x00, 0x21, 0x01, + 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc, + 0xe0, 0x01, 0xbd, 0x01, 0x43, 0x5d, 0x00, 0x26, + 0x1b, 0xca, 0x46, 0x67, 0x5a, 0xf2, 0x77, 0xb8, + 0x7d, 0x86, 0xd8, 0x41, 0xdb, 0x05, 0x35, 0xcd, + 0x83, 0xa5, 0x7c, 0x12, 0xa5, 0x05, 0xdb, 0x90, + 0xbd, 0x2f, 0x14, 0xd3, 0x71, 0x72, 0x96, 0xa8, + 0x8a, 0x7d, 0x84, 0x56, 0x71, 0x8d, 0x6a, 0x22, + 0x98, 0xab, 0x9e, 0x3d, 0xc3, 0x55, 0xef, 0xcc, + 0xa5, 0xc3, 0xdd, 0x5b, 0x8e, 0xbf, 0x03, 0x81, + 0x21, 0x40, 0xd6, 0x26, 0x91, 0x02, 0x45, 0x4e, + 0x20, 0x91, 0xcf, 0x8c, 0x51, 0x22, 0x02, 0x70, + 0xba, 0x05, 0x6b, 0x83, 0xef, 0x3f, 0x8e, 0x09, + 0xef, 0x88, 0xf5, 0x37, 0x1b, 0x89, 0x8d, 0xff, + 0x1e, 0xee, 0xe8, 0xb0, 0xac, 0xf2, 0x6e, 0xd4, + 0x3e, 0x25, 0xaf, 0xa0, 0x6d, 0x2e, 0xc0, 0x7f, + 0xb5, 0xa0, 0xcb, 0x90, 0x1f, 0x08, 0x1a, 0xe2, + 0x90, 0x20, 0x19, 0x71, 0x0c, 0xe8, 0x3f, 0xe5, + 0x39, 0xeb, 0x9a, 0x62, 0x4f, 0x06, 0xda, 0x3c, + 0x32, 0x59, 0xcc, 0x83, 0xe3, 0x83, 0x0f, 0x38, + 0x7d, 0x43, 0x37, 0x6c, 0x0b, 0x05, 0x65, 0x98, + 0x25, 0xdb, 0xf2, 0xc0, 0x2d, 0x39, 0x36, 0x5d, + 0xd4, 0xb6, 0xc2, 0x79, 0x73, 0x3e, 0xc2, 0x6e, + 0x54, 0xec, 0x78, 0x2b, 0x5d, 0xf1, 0xd1, 0xb4, + 0xb3, 0xcd, 0xf3, 0x89, 0xf5, 0x81, 0x3e, 0x2c, + 0x65, 0xd6, 0x73, 0xd3, 0x1b, 0x20, 0x68, 0x0c, + 0x93, 0xd4, 0xfc, 0x9f, 0xf8, 0xa7, 0xd4, 0xfa, + 0x3a, 0xb1, 0x13, 0x93, 0x4b, 0xec, 0x78, 0x7d, + 0x5c, 0x81, 0x80, 0xe5, 0x14, 0x78, 0xfe, 0x7e, + 0xde, 0xf7, 0xad, 0x9e, 0x84, 0xba, 0xf1, 0x00, + 0xe9, 0xbd, 0x2c, 0xf4, 0x70, 0x7d, 0xbe, 0x29, + 0xb9, 0xf0, 0x10, 0xb9, 0x01, 0xf1, 0x76, 0x8a, + 0x5a, 0xad, 0x02, 0xa1, 0x32, 0xc8, 0x53, 0x59, + 0x11, 0x4c, 0xe2, 0x98, 0x34, 0xd9, 0x23, 0x51, + 0x4a, 0x40, 0x2b, 0x87, 0x41, 0xdd, 0x50, 0xcd, + 0x98, 0x1e, 0x29, 0x86, 0x23, 0x93, 0x3e, 0x9b, + 0x6b, 0x16, 0xa1, 0x40, 0xac, 0xe7, 0x40, 0xfe, + 0xa9, 0x87, 0x48, 0x25, 0x52, 0x02, 0x8b, 0xc4, + 0x68, 0x08, 0x5a, 0x62, 0xc1, 0xb2, 0x07, 0x3b, + 0x26, 0x1e, 0x59, 0x5c, 0x47, 0x24, 0xae, 0x8e, + 0xe5, 0xf7, 0xe6, 0x4b, 0x13, 0xb4, 0x6d, 0x46, + 0x65, 0x4f, 0xd0, 0x48, 0xcc, 0x51, 0x4b, 0x80, + 0xcb, 0xf1, 0xd4, 0x6c, 0x45, 0x98, 0x92, 0x47, + 0xeb, 0x60, 0x00, 0x00, 0x00, 0x01, 0xd7, 0x02, + 0xbe, 0x03, 0x00, 0x00, 0xda, 0x2c, 0x45, 0x49, + 0xa8, 0x00, 0x0a, 0xfc, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x59, 0x5a +#elif defined(DO_BZIP2) + 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, + 0x53, 0x59, 0x05, 0x24, 0x28, 0x04, 0x00, 0x00, + 0x27, 0xd7, 0x80, 0x00, 0x10, 0x40, 0x05, 0x06, + 0x04, 0x02, 0x00, 0x3f, 0xe7, 0xff, 0x40, 0x30, + 0x01, 0x2d, 0x23, 0x62, 0x26, 0x05, 0x3d, 0x03, + 0x54, 0xfd, 0x53, 0x4c, 0x86, 0x9e, 0x90, 0x6a, + 0x9e, 0x9e, 0x85, 0x3c, 0xa0, 0x00, 0x00, 0x1a, + 0x9e, 0x41, 0x13, 0x13, 0x28, 0x69, 0x03, 0xd4, + 0x0f, 0x1c, 0x70, 0xd0, 0xb4, 0xe3, 0xe4, 0x75, + 0x4e, 0x8b, 0x67, 0x43, 0x7b, 0x38, 0x27, 0x77, + 0xe4, 0xc1, 0x98, 0x3a, 0x2d, 0x3a, 0xe4, 0x44, + 0x98, 0xdc, 0x49, 0x8b, 0x22, 0x48, 0xfc, 0xc8, + 0xe7, 0x57, 0x05, 0x3c, 0x5a, 0xee, 0x5a, 0x84, + 0xcd, 0x7c, 0x8f, 0x26, 0x6b, 0x6e, 0xf7, 0xb5, + 0x49, 0x1f, 0x79, 0x42, 0x5d, 0x09, 0x8c, 0xc6, + 0xde, 0x0c, 0x0d, 0xb1, 0x46, 0xb4, 0xee, 0xd9, + 0x8f, 0x33, 0x37, 0x04, 0xa9, 0x05, 0x49, 0xe3, + 0x04, 0x16, 0x62, 0x36, 0x3a, 0x01, 0xda, 0xd4, + 0xc8, 0x8a, 0x32, 0x02, 0x1f, 0x62, 0x4b, 0xa4, + 0x49, 0x59, 0xda, 0x50, 0x85, 0x69, 0x35, 0x21, + 0x10, 0xc6, 0x8a, 0x3c, 0x44, 0x95, 0xb0, 0xbc, + 0xc5, 0x6b, 0xea, 0xfb, 0x40, 0xbd, 0x14, 0x01, + 0x6a, 0xfa, 0xcd, 0x67, 0xd8, 0x2d, 0x93, 0x8b, + 0xda, 0x44, 0x1b, 0xe9, 0x5a, 0x87, 0x60, 0xb0, + 0xe0, 0x73, 0xd1, 0x01, 0x3a, 0x66, 0x05, 0xcc, + 0x34, 0xa0, 0x63, 0x8d, 0x35, 0x5e, 0xa0, 0x9f, + 0x05, 0x89, 0x15, 0x51, 0x48, 0x16, 0x0c, 0x61, + 0xf4, 0x30, 0xb8, 0x07, 0x29, 0xc0, 0xf5, 0x1a, + 0xe1, 0x0d, 0x6c, 0xfe, 0x91, 0xda, 0x13, 0x2f, + 0x8e, 0x5b, 0x1c, 0xfc, 0xb3, 0xb2, 0x30, 0x9d, + 0xf6, 0x09, 0x30, 0x55, 0x30, 0x67, 0xc2, 0x87, + 0xe9, 0x9a, 0xd4, 0x1d, 0x66, 0x11, 0x54, 0x89, + 0x21, 0xe1, 0x55, 0x84, 0xbf, 0xa6, 0x11, 0xa4, + 0xb8, 0x40, 0xed, 0x42, 0x20, 0xb9, 0xb7, 0x26, + 0x31, 0x14, 0x4f, 0x86, 0xdc, 0x50, 0x34, 0x38, + 0x8b, 0x57, 0x77, 0x21, 0xf6, 0x89, 0xbd, 0xc5, + 0x65, 0xc3, 0x23, 0x45, 0xec, 0x7f, 0x8b, 0xb9, + 0x22, 0x9c, 0x28, 0x48, 0x02, 0x92, 0x14, 0x02, + 0x00, +#elif defined(DO_GZIP) + 0x1f, 0x8b, 0x08, 0x08, 0xdb, 0xa1, 0x97, 0x63, + 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, + 0x78, 0x74, 0x00, 0x35, 0x90, 0xc1, 0x71, 0x43, + 0x31, 0x08, 0x44, 0xef, 0xbf, 0x8a, 0x2d, 0x20, + 0xf3, 0xab, 0x48, 0x6e, 0xb9, 0xa6, 0x00, 0x82, + 0xb0, 0xc3, 0x8c, 0x24, 0x64, 0x09, 0x3c, 0x2e, + 0x3f, 0xc8, 0x4e, 0x6e, 0x42, 0xc0, 0xb2, 0xfb, + 0x3e, 0x6d, 0x4a, 0x83, 0x8e, 0x15, 0x0d, 0xc5, + 0xaa, 0x4d, 0x2c, 0x75, 0x50, 0x13, 0x7f, 0x03, + 0x5b, 0x5f, 0xc2, 0x2e, 0x1e, 0x13, 0x54, 0x74, + 0xe8, 0x62, 0xed, 0x57, 0x48, 0xd5, 0x6c, 0x2e, + 0x29, 0xb9, 0x00, 0xd1, 0x58, 0xcd, 0xca, 0xe1, + 0xd2, 0x46, 0x2e, 0x6b, 0x67, 0x2d, 0x5a, 0xa2, + 0x3b, 0xc2, 0x51, 0xe9, 0x3b, 0xe5, 0x21, 0xfe, + 0x92, 0x16, 0x34, 0xba, 0x76, 0x02, 0x55, 0xbd, + 0x05, 0x9d, 0xf8, 0x72, 0x48, 0xd7, 0x96, 0xda, + 0x68, 0xba, 0x1f, 0xf7, 0x2c, 0xa9, 0xbd, 0x1d, + 0xb7, 0xd0, 0x85, 0x6e, 0xcb, 0x67, 0x14, 0xc8, + 0x43, 0x26, 0xab, 0x93, 0xab, 0x75, 0x44, 0xad, + 0xd4, 0xd8, 0x5e, 0xca, 0x7b, 0x48, 0x97, 0xee, + 0x4b, 0x4f, 0x49, 0x1d, 0x39, 0x0c, 0xa1, 0x34, + 0xde, 0xd2, 0x93, 0x1d, 0xcf, 0x00, 0x79, 0xca, + 0x4f, 0xbc, 0x6f, 0x49, 0x0a, 0x17, 0xe8, 0x8c, + 0x74, 0xf2, 0xca, 0xaa, 0x1d, 0x53, 0xc6, 0x94, + 0x1f, 0xe9, 0x45, 0x66, 0x06, 0xcf, 0x8f, 0xbb, + 0xd5, 0x18, 0x79, 0x4e, 0xd2, 0x4e, 0x26, 0x85, + 0xac, 0x25, 0x07, 0x6b, 0xad, 0xff, 0x84, 0x32, + 0x50, 0xe0, 0x12, 0x57, 0x25, 0x47, 0xdf, 0x86, + 0x30, 0x68, 0x66, 0x11, 0xf3, 0xc4, 0xc7, 0x83, + 0x65, 0xb8, 0xc4, 0xc6, 0x98, 0x0c, 0x8c, 0x99, + 0x84, 0x73, 0x8e, 0x63, 0x68, 0x21, 0xdf, 0x1b, + 0xd6, 0x8f, 0x31, 0x4d, 0x8b, 0xf4, 0x4d, 0x71, + 0x93, 0xca, 0xa3, 0x1c, 0x75, 0x10, 0x32, 0x02, + 0xec, 0x72, 0x51, 0x56, 0x42, 0x91, 0x25, 0x73, + 0x77, 0x9b, 0xd5, 0x6d, 0x83, 0x36, 0x20, 0x4d, + 0x1c, 0xeb, 0x8f, 0x6b, 0xb4, 0xf3, 0xf8, 0x05, + 0x6b, 0x8b, 0x8b, 0x20, 0xbe, 0x01, 0x00, 0x00, +#elif defined(DO_ZSTD) + 0x28, 0xb5, 0x2f, 0xfd, 0x04, 0x88, 0xa5, 0x08, + 0x00, 0x46, 0x97, 0x3a, 0x1a, 0x80, 0x37, 0xcd, + 0x01, 0xc0, 0x8a, 0xec, 0xfe, 0x2d, 0xf2, 0xb9, + 0x44, 0x6b, 0xb9, 0x24, 0x77, 0x56, 0x5a, 0x33, + 0x17, 0x0b, 0x67, 0x83, 0x2e, 0x47, 0x07, 0x31, + 0x00, 0x32, 0x00, 0x33, 0x00, 0xc5, 0x2c, 0x5a, + 0x92, 0x93, 0x0f, 0x7b, 0xd1, 0x1d, 0x63, 0x2c, + 0xc8, 0x99, 0x94, 0x77, 0x8f, 0x94, 0x38, 0x75, + 0x80, 0x2f, 0xae, 0xc1, 0x3e, 0xd2, 0xcf, 0x49, + 0x15, 0x25, 0x1a, 0x87, 0x93, 0xdd, 0xe8, 0x00, + 0x6d, 0xaa, 0xf8, 0x54, 0x74, 0xe5, 0x48, 0x4d, + 0xa6, 0xf3, 0x1a, 0xa3, 0x13, 0x08, 0xe5, 0x26, + 0xdc, 0x73, 0xcc, 0x3e, 0xfd, 0x86, 0xa9, 0x52, + 0xb2, 0x76, 0xc7, 0xc2, 0x0f, 0xe4, 0x84, 0x4b, + 0x12, 0x61, 0x3a, 0x6b, 0x7a, 0x1e, 0x8a, 0x81, + 0xa9, 0x9b, 0x11, 0x37, 0x25, 0x55, 0x73, 0x73, + 0x71, 0xa0, 0x84, 0xca, 0xc3, 0x4b, 0xb5, 0xcc, + 0x50, 0xa6, 0x46, 0xd7, 0xe8, 0x08, 0xaa, 0x04, + 0x28, 0xb1, 0x8e, 0xea, 0xb4, 0x4a, 0x49, 0x2b, + 0xd6, 0x0d, 0x59, 0x68, 0xda, 0x64, 0x29, 0x1f, + 0x85, 0x53, 0x72, 0xf1, 0xc5, 0x88, 0x1a, 0x0b, + 0x4f, 0x96, 0x43, 0xe0, 0x91, 0x89, 0xb9, 0xc0, + 0xe8, 0x18, 0xd5, 0x6e, 0x94, 0xe8, 0x35, 0x66, + 0x01, 0x94, 0x80, 0x95, 0x87, 0xe2, 0xc8, 0x19, + 0x73, 0xa3, 0x01, 0x05, 0xc1, 0x64, 0x72, 0xc9, + 0x6b, 0x6e, 0x55, 0x7c, 0x29, 0x67, 0x90, 0x93, + 0x49, 0xeb, 0xe3, 0x85, 0xc2, 0xf5, 0x79, 0x68, + 0x9d, 0x92, 0xc3, 0x32, 0x75, 0x80, 0x66, 0xf2, + 0x43, 0xa7, 0xb0, 0xc3, 0x22, 0x3f, 0x39, 0x8a, + 0x35, 0x5c, 0x63, 0x5c, 0xd1, 0x9e, 0x8a, 0xd2, + 0x78, 0x3c, 0x12, 0x01, 0x25, 0x04, 0x0e, 0x08, + 0x10, 0x88, 0xb6, 0x1b, 0xb7, 0x96, 0x35, 0xa8, + 0x0d, 0x1e, 0xae, 0xac, 0x4a, 0x70, 0xa5, 0x31, + 0xd0, 0x0c, 0x78, 0xbf, 0xdd, 0xc5, 0x24, 0x3e, + 0xcb, 0x0a, 0x0a, 0x69, 0x40, 0xba, 0xb0, 0xc4, + 0x2a, 0x9b, 0x1e, 0x0a, 0x51, 0xa6, 0x16, 0x98, + 0x76, +#endif +}; + +static const sqfs_u8 blob_in_concat[] = { +#if defined(DO_XZ) + 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, + 0xe6, 0xd6, 0xb4, 0x46, 0x02, 0x00, 0x21, 0x01, + 0x16, 0x00, 0x00, 0x00, 0x74, 0x2f, 0xe5, 0xa3, + 0xe0, 0x00, 0xdc, 0x00, 0xb3, 0x5d, 0x00, 0x26, + 0x1b, 0xca, 0x46, 0x67, 0x5a, 0xf2, 0x77, 0xb8, + 0x7d, 0x86, 0xd8, 0x41, 0xdb, 0x05, 0x35, 0xcd, + 0x83, 0xa5, 0x7c, 0x12, 0xa5, 0x05, 0xdb, 0x90, + 0xbd, 0x2f, 0x14, 0xd3, 0x71, 0x72, 0x96, 0xa8, + 0x8a, 0x7d, 0x84, 0x56, 0x71, 0x8d, 0x6a, 0x22, + 0x98, 0xab, 0x9e, 0x3d, 0xc3, 0x55, 0xef, 0xcc, + 0xa5, 0xc3, 0xdd, 0x5b, 0x8e, 0xbf, 0x03, 0x81, + 0x21, 0x40, 0xd6, 0x26, 0x91, 0x02, 0x45, 0x4e, + 0x20, 0x91, 0xcf, 0x8c, 0x51, 0x22, 0x02, 0x70, + 0xba, 0x05, 0x6b, 0x83, 0xef, 0x3f, 0x8e, 0x09, + 0xef, 0x88, 0xf5, 0x37, 0x1b, 0x89, 0x8d, 0xff, + 0x1e, 0xee, 0xe8, 0xb0, 0xac, 0xf2, 0x6e, 0xd4, + 0x3e, 0x25, 0xaf, 0xa0, 0x6d, 0x2e, 0xc0, 0x7f, + 0xb5, 0xa0, 0xcb, 0x90, 0x1f, 0x08, 0x1a, 0xe2, + 0x90, 0x20, 0x19, 0x71, 0x0c, 0xe8, 0x3f, 0xe5, + 0x39, 0xeb, 0x9a, 0x62, 0x4f, 0x06, 0xda, 0x3c, + 0x32, 0x59, 0xcc, 0x83, 0xe3, 0x83, 0x0f, 0x38, + 0x7d, 0x43, 0x37, 0x6c, 0x0b, 0x05, 0x65, 0x98, + 0x25, 0xdb, 0xf2, 0xc0, 0x2d, 0x39, 0x36, 0x5d, + 0xd4, 0xb6, 0xc2, 0x79, 0x73, 0x3e, 0xc2, 0x6e, + 0x54, 0xec, 0x78, 0x2b, 0x5d, 0xf1, 0xd1, 0xb4, + 0xb3, 0xcd, 0xf3, 0x89, 0xf5, 0x80, 0x79, 0x46, + 0xc0, 0x00, 0x00, 0x00, 0xc4, 0xf5, 0x1d, 0x08, + 0xf0, 0x34, 0x3a, 0x59, 0x00, 0x01, 0xcf, 0x01, + 0xdd, 0x01, 0x00, 0x00, 0x7f, 0x5a, 0x77, 0xcb, + 0xb1, 0xc4, 0x67, 0xfb, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x59, 0x5a, + 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, + 0xe6, 0xd6, 0xb4, 0x46, 0x02, 0x00, 0x21, 0x01, + 0x16, 0x00, 0x00, 0x00, 0x74, 0x2f, 0xe5, 0xa3, + 0xe0, 0x00, 0xe0, 0x00, 0xb7, 0x5d, 0x00, 0x31, + 0x9b, 0xca, 0x19, 0xc5, 0x54, 0xec, 0xb6, 0x54, + 0xe7, 0xb1, 0x7d, 0xc4, 0x57, 0x9e, 0x6c, 0x89, + 0xad, 0x4a, 0x6d, 0x16, 0xd8, 0x3c, 0x05, 0x94, + 0x10, 0x16, 0x99, 0x38, 0x21, 0xa3, 0xb9, 0xc5, + 0x80, 0xff, 0xfc, 0xee, 0xd4, 0xd5, 0x3f, 0xdd, + 0x8c, 0xd7, 0x3d, 0x8f, 0x76, 0xec, 0x96, 0x9d, + 0x20, 0xac, 0xcb, 0x18, 0xf5, 0xb2, 0x9c, 0x12, + 0xf6, 0x7c, 0x33, 0xdc, 0x4f, 0x9a, 0xe5, 0x2d, + 0x63, 0x68, 0xa4, 0x2b, 0x1d, 0x0a, 0x1e, 0xf0, + 0xfe, 0x73, 0xf2, 0x5f, 0x7b, 0xb4, 0xea, 0x54, + 0xad, 0x27, 0xd1, 0xff, 0xb6, 0x50, 0x06, 0x7b, + 0x51, 0x3f, 0x25, 0x8a, 0xcf, 0x4c, 0x03, 0x3e, + 0xc3, 0xad, 0x47, 0x34, 0xcf, 0xba, 0x45, 0x79, + 0xd0, 0x7b, 0xf6, 0x66, 0x63, 0xc0, 0xc6, 0x69, + 0xa7, 0x51, 0x84, 0xa8, 0xa0, 0x0b, 0xbc, 0x6f, + 0x13, 0x89, 0xd6, 0x5e, 0xac, 0xca, 0x2f, 0xd2, + 0xe7, 0xe1, 0x1e, 0x78, 0x22, 0x3a, 0x59, 0x6c, + 0x9c, 0x8c, 0x65, 0xf1, 0x5b, 0xf4, 0xbf, 0xd5, + 0xdc, 0x05, 0xeb, 0x70, 0x10, 0xb8, 0x6c, 0xf2, + 0x13, 0x20, 0xb0, 0xdd, 0x3e, 0xb2, 0x92, 0x5b, + 0xa3, 0xf7, 0x94, 0xa1, 0xa1, 0x74, 0x36, 0x9a, + 0xf1, 0xd8, 0xc2, 0xf0, 0xc6, 0x29, 0x7e, 0x85, + 0x28, 0xf5, 0xf2, 0x21, 0x00, 0x00, 0x00, 0x00, + 0xc8, 0x80, 0x67, 0x40, 0xc3, 0xaa, 0x17, 0x57, + 0x00, 0x01, 0xd3, 0x01, 0xe1, 0x01, 0x00, 0x00, + 0x86, 0xdf, 0x9e, 0x05, 0xb1, 0xc4, 0x67, 0xfb, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x59, 0x5a +#elif defined(DO_BZIP2) + 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, + 0x53, 0x59, 0x5d, 0x09, 0x24, 0x1d, 0x00, 0x00, + 0x13, 0xd7, 0x80, 0x00, 0x10, 0x40, 0x05, 0x00, + 0x04, 0x02, 0x00, 0x3e, 0xa7, 0xff, 0x40, 0x30, + 0x00, 0xac, 0x43, 0x54, 0xf5, 0x36, 0x4c, 0xa7, + 0xa8, 0xd3, 0x6a, 0x60, 0x81, 0x40, 0x00, 0xd0, + 0x32, 0x64, 0x0d, 0x53, 0xda, 0x02, 0x09, 0xa2, + 0x68, 0x34, 0xd1, 0x27, 0x4a, 0xdd, 0xf2, 0x0a, + 0x73, 0x43, 0xf9, 0xa2, 0x51, 0x85, 0x76, 0x45, + 0x9a, 0x68, 0x3a, 0xe7, 0x0d, 0xc0, 0x21, 0x4a, + 0xc4, 0xf9, 0xf7, 0x40, 0xc3, 0x10, 0xb2, 0x9b, + 0x58, 0x56, 0x71, 0x50, 0x2f, 0xa4, 0xc5, 0x61, + 0x19, 0xf6, 0x59, 0x06, 0x82, 0x03, 0x7f, 0xeb, + 0xd2, 0x61, 0x88, 0xcd, 0xe8, 0xf7, 0xe8, 0x87, + 0x59, 0x9d, 0xe1, 0xf8, 0x19, 0x6e, 0xad, 0x77, + 0xbf, 0x34, 0x17, 0x21, 0x6b, 0x91, 0xc9, 0x52, + 0xd0, 0x81, 0x1e, 0xb5, 0x0b, 0xee, 0x42, 0x84, + 0x80, 0xd5, 0xa1, 0x8a, 0x04, 0x18, 0x4d, 0xf3, + 0xda, 0x7e, 0x3c, 0x40, 0xa4, 0xdb, 0xe5, 0xf0, + 0x37, 0x40, 0x3a, 0x7d, 0xa7, 0x45, 0x21, 0xf2, + 0x5a, 0x7b, 0x59, 0x56, 0x16, 0xd5, 0xac, 0x9f, + 0x60, 0x85, 0x0e, 0xf5, 0x73, 0xd9, 0x47, 0xe2, + 0xee, 0x48, 0xa7, 0x0a, 0x12, 0x0b, 0xa1, 0x24, + 0x83, 0xa0, + 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, + 0x53, 0x59, 0x2c, 0x24, 0x39, 0xa0, 0x00, 0x00, + 0x1f, 0x55, 0x80, 0x00, 0x10, 0x40, 0x05, 0x06, + 0x00, 0x3f, 0xe7, 0xff, 0x40, 0x30, 0x00, 0xb5, + 0x91, 0x13, 0x4f, 0x54, 0x7a, 0x6a, 0x6d, 0x4d, + 0xa2, 0x68, 0x0c, 0x84, 0x53, 0xf5, 0x30, 0x89, + 0xa3, 0xd4, 0x0d, 0x0f, 0x49, 0xa0, 0xd4, 0xf4, + 0xd1, 0x53, 0xf4, 0x93, 0x69, 0x3c, 0x81, 0x1a, + 0x65, 0x53, 0x90, 0x51, 0x07, 0x2a, 0xad, 0x8f, + 0x63, 0xba, 0x25, 0xc2, 0x0c, 0x8b, 0xb9, 0x95, + 0x15, 0xd8, 0xda, 0x61, 0x5c, 0xa9, 0xe4, 0x0b, + 0x21, 0xc9, 0x97, 0x57, 0x01, 0x28, 0x9b, 0xfb, + 0x94, 0xb9, 0x48, 0xa3, 0x0a, 0xc6, 0x1c, 0x54, + 0x98, 0x9a, 0x39, 0xc3, 0x87, 0x90, 0x33, 0x58, + 0x2d, 0x3e, 0x16, 0xb1, 0xae, 0x26, 0x89, 0x75, + 0xf5, 0x77, 0xa5, 0x8e, 0x5b, 0x8c, 0x8a, 0x39, + 0xbd, 0x75, 0x21, 0x9d, 0x99, 0x18, 0x4a, 0x91, + 0xab, 0xbc, 0x08, 0x87, 0xa4, 0xf1, 0x81, 0xb5, + 0xb4, 0xb0, 0xfe, 0x6b, 0x9f, 0xbe, 0x19, 0x82, + 0xd1, 0x50, 0xe1, 0x5e, 0x13, 0xb5, 0xc6, 0x2c, + 0xa4, 0x82, 0xf2, 0x5c, 0xc3, 0x20, 0x41, 0x13, + 0x56, 0x63, 0x3d, 0xec, 0x71, 0x2a, 0xbf, 0x2c, + 0x60, 0x2f, 0x7a, 0x4d, 0xcb, 0x3f, 0x8b, 0xb9, + 0x22, 0x9c, 0x28, 0x48, 0x16, 0x12, 0x1c, 0xd0, + 0x00, +#elif defined(DO_ZSTD) + 0x28, 0xb5, 0x2f, 0xfd, 0x04, 0x58, 0x75, 0x04, + 0x00, 0xb2, 0x4c, 0x20, 0x17, 0xa0, 0x25, 0x69, + 0x03, 0xf0, 0xb2, 0x37, 0xb1, 0x5e, 0xb9, 0x24, + 0x56, 0x5b, 0x52, 0x22, 0x39, 0x01, 0x44, 0x2b, + 0x03, 0x55, 0xe3, 0x47, 0x03, 0x12, 0x9a, 0xe1, + 0xf0, 0x94, 0x0b, 0xe5, 0xe2, 0xba, 0x7e, 0xfe, + 0x9c, 0xc7, 0x61, 0x43, 0xc8, 0xfa, 0xf0, 0x3a, + 0xfa, 0x51, 0xaa, 0x50, 0xa6, 0x2d, 0x9a, 0x78, + 0xce, 0x2f, 0x61, 0x20, 0x6c, 0x7e, 0x35, 0x60, + 0xfb, 0xdd, 0x4c, 0x63, 0xfb, 0x95, 0x35, 0xc0, + 0x82, 0x59, 0xc2, 0xc9, 0x78, 0x6e, 0x30, 0xe6, + 0xd2, 0x72, 0x15, 0x14, 0x18, 0x62, 0x5d, 0xeb, + 0x2d, 0x9d, 0x3e, 0xee, 0x2e, 0x58, 0x58, 0xe9, + 0x40, 0x68, 0xb9, 0x2f, 0x23, 0x99, 0x2a, 0x4d, + 0xe8, 0x49, 0x79, 0x70, 0x1f, 0xf9, 0xe2, 0x34, + 0x2e, 0xab, 0xa5, 0xa3, 0xf2, 0x70, 0x98, 0xd0, + 0xb2, 0xb1, 0x3e, 0x5d, 0x90, 0x20, 0xd9, 0x36, + 0x8b, 0xdb, 0xaa, 0x20, 0x40, 0x03, 0x14, 0x06, + 0x03, 0x16, 0x2a, 0x9d, 0x31, 0xbd, 0x28, 0x3b, + 0x0c, 0xac, 0x41, + 0x28, 0xb5, 0x2f, 0xfd, 0x04, 0x58, 0xbd, 0x04, + 0x00, 0x62, 0xcd, 0x22, 0x19, 0xa0, 0x25, 0x69, + 0x03, 0x60, 0x72, 0xc9, 0x36, 0xda, 0xd2, 0x8b, + 0xfc, 0xbf, 0x25, 0x42, 0xa9, 0x82, 0x38, 0x70, + 0x1a, 0x2e, 0x54, 0x95, 0x33, 0x02, 0x03, 0x51, + 0x36, 0x51, 0x80, 0xcc, 0x7a, 0x6e, 0x52, 0x2e, + 0x75, 0x64, 0x2d, 0x33, 0x2c, 0xd6, 0xdb, 0xfc, + 0x39, 0x31, 0xd5, 0xa8, 0xa2, 0x40, 0xd7, 0x12, + 0x4c, 0xc6, 0x76, 0xdc, 0x1e, 0x0f, 0xf4, 0x4e, + 0x0a, 0xd3, 0x0c, 0x87, 0x67, 0x25, 0x25, 0x52, + 0x66, 0x87, 0x95, 0xc6, 0x69, 0x0c, 0xb4, 0x5e, + 0x1d, 0xe7, 0x5e, 0xcd, 0x47, 0x41, 0x80, 0x89, + 0x5c, 0xa5, 0x4a, 0x32, 0x26, 0xb3, 0x3d, 0x2b, + 0xd5, 0xc0, 0x16, 0xde, 0xfb, 0x65, 0xcd, 0x6a, + 0x0c, 0x3f, 0xe7, 0xd6, 0xb2, 0x17, 0x7c, 0x25, + 0x35, 0x6b, 0x58, 0xf0, 0x95, 0xb5, 0xf2, 0xe4, + 0x4e, 0xf0, 0x34, 0x4f, 0x5f, 0x39, 0xd1, 0x90, + 0xf8, 0xb9, 0x59, 0xbe, 0x2e, 0xf9, 0xd4, 0x02, + 0x98, 0x50, 0x5a, 0xc2, 0xcf, 0xe1, 0x08, 0x02, + 0x00, 0x0f, 0x1e, 0x44, 0x40, 0x79, 0x50, 0x67, + 0x3d, 0xd3, 0x35, 0x8f, +#elif defined(DO_GZIP) + 0, +#endif +}; + +#if defined(DO_XZ) +static size_t in_stop = 244; +static size_t out_stop = 221; + +#define mkdecompressor decompressor_stream_xz_create +#elif defined(DO_BZIP2) +static size_t in_stop = 186; +static size_t out_stop = 221; + +#define mkdecompressor decompressor_stream_bzip2_create +#elif defined(DO_ZSTD) +static size_t in_stop = 319; +static size_t out_stop = 446; + +#define mkdecompressor decompressor_stream_zstd_create +#elif defined(DO_GZIP) +#define mkdecompressor decompressor_stream_gzip_create +#endif + +static const char orig[] = +"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n" +"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n" +"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n" +"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n" +"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n" +"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"; + +int main(int argc, char **argv) +{ + sqfs_u32 in_diff = 0, out_diff = 0; + xfrm_stream_t *xfrm; + char buffer[1024]; + int ret; + (void)argc; (void)argv; + + /* normal stream */ + xfrm = mkdecompressor(); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + ret = xfrm->process_data(xfrm, blob_in, sizeof(blob_in), + buffer, sizeof(buffer), + &in_diff, &out_diff, XFRM_STREAM_FLUSH_FULL); + TEST_EQUAL_I(ret, XFRM_STREAM_END); + + TEST_EQUAL_UI(in_diff, sizeof(blob_in)); + TEST_EQUAL_UI(out_diff, sizeof(orig) - 1); + ret = memcmp(buffer, orig, out_diff); + TEST_EQUAL_I(ret, 0); + + sqfs_drop(xfrm); + + /* concatenated streams */ +#if !defined(DO_GZIP) + xfrm = mkdecompressor(); + TEST_NOT_NULL(xfrm); + TEST_EQUAL_UI(((sqfs_object_t *)xfrm)->refcount, 1); + + in_diff = 0; + out_diff = 0; + + ret = xfrm->process_data(xfrm, blob_in_concat, sizeof(blob_in_concat), + buffer, sizeof(buffer), + &in_diff, &out_diff, XFRM_STREAM_FLUSH_FULL); + TEST_EQUAL_I(ret, XFRM_STREAM_END); + + TEST_EQUAL_UI(in_diff, in_stop); + TEST_EQUAL_UI(out_diff, out_stop); + ret = memcmp(buffer, orig, out_diff); + TEST_EQUAL_I(ret, 0); + + ret = xfrm->process_data(xfrm, blob_in_concat + in_diff, + sizeof(blob_in_concat) - in_diff, + buffer + out_diff, sizeof(buffer) - out_diff, + &in_diff, &out_diff, XFRM_STREAM_FLUSH_FULL); + TEST_EQUAL_I(ret, XFRM_STREAM_END); + + TEST_EQUAL_UI(in_diff, sizeof(blob_in_concat)); + TEST_EQUAL_UI(out_diff, sizeof(orig) - 1); + ret = memcmp(buffer, orig, out_diff); + TEST_EQUAL_I(ret, 0); + + sqfs_drop(xfrm); +#else + (void)blob_in_concat; +#endif + return EXIT_SUCCESS; +} |