diff options
Diffstat (limited to 't/unit-tests')
44 files changed, 3473 insertions, 3049 deletions
diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c index d54e455367..03a3aa8e87 100644 --- a/t/unit-tests/clar/clar.c +++ b/t/unit-tests/clar/clar.c @@ -350,7 +350,7 @@ static void clar_run_suite(const struct clar_suite *suite, const char *filter) { const struct clar_func *test = suite->tests; - size_t i, matchlen; + size_t i, matchlen = 0; struct clar_report *report; int exact = 0; diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h index 8b206179fc..2203743fb4 100644 --- a/t/unit-tests/clar/clar/fs.h +++ b/t/unit-tests/clar/clar/fs.h @@ -376,9 +376,12 @@ fs_copydir_helper(const char *source, const char *dest, int dest_mode) mkdir(dest, dest_mode); cl_assert_(source_dir = opendir(source), "Could not open source dir"); - while ((d = (errno = 0, readdir(source_dir))) != NULL) { + for (;;) { char *child; + errno = 0; + if ((d = readdir(source_dir)) == NULL) + break; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; @@ -479,9 +482,12 @@ fs_rmdir_helper(const char *path) struct dirent *d; cl_assert_(dir = opendir(path), "Could not open dir"); - while ((d = (errno = 0, readdir(dir))) != NULL) { + for (;;) { char *child; + errno = 0; + if ((d = readdir(dir)) == NULL) + break; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; diff --git a/t/unit-tests/generate-clar-decls.sh b/t/unit-tests/generate-clar-decls.sh index 3b315c64b3..abf6a2ea2a 100755 --- a/t/unit-tests/generate-clar-decls.sh +++ b/t/unit-tests/generate-clar-decls.sh @@ -14,6 +14,7 @@ do suite_name=$(basename "$suite") suite_name=${suite_name%.c} suite_name=${suite_name#u-} + suite_name=$(echo "$suite_name" | tr '-' '_') sed -ne "s/^\(void test_${suite_name}__[a-zA-Z_0-9][a-zA-Z_0-9]*(void)\)$/extern \1;/p" "$suite" || exit 1 done >"$OUTPUT" diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c index 8f0ccac532..e0b3180f23 100644 --- a/t/unit-tests/lib-oid.c +++ b/t/unit-tests/lib-oid.c @@ -1,9 +1,9 @@ -#include "test-lib.h" +#include "unit-test.h" #include "lib-oid.h" #include "strbuf.h" #include "hex.h" -int init_hash_algo(void) +int cl_setup_hash_algo(void) { static int algo = -1; @@ -11,42 +11,32 @@ int init_hash_algo(void) const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH"); algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1; - if (!check(algo != GIT_HASH_UNKNOWN)) - test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')", - algo_name); + cl_assert(algo != GIT_HASH_UNKNOWN); } return algo; } -static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid, +static void cl_parse_oid(const char *hex, struct object_id *oid, const struct git_hash_algo *algop) { - int ret; size_t sz = strlen(hex); struct strbuf buf = STRBUF_INIT; - if (!check(sz <= algop->hexsz)) { - test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)", - hex, (unsigned long)algop->hexsz); - return -1; - } + cl_assert(sz <= algop->hexsz); strbuf_add(&buf, hex, sz); strbuf_addchars(&buf, '0', algop->hexsz - sz); - ret = get_oid_hex_algop(buf.buf, oid, algop); - if (!check_int(ret, ==, 0)) - test_msg("BUG: invalid hex input (%s) provided", hex); + cl_assert_equal_i(get_oid_hex_algop(buf.buf, oid, algop), 0); strbuf_release(&buf); - return ret; } -int get_oid_arbitrary_hex(const char *hex, struct object_id *oid) + +void cl_parse_any_oid(const char *hex, struct object_id *oid) { - int hash_algo = init_hash_algo(); + int hash_algo = cl_setup_hash_algo(); - if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN)) - return -1; - return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]); + cl_assert(hash_algo != GIT_HASH_UNKNOWN); + cl_parse_oid(hex, oid, &hash_algos[hash_algo]); } diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h index 4e77c04bd2..4031775104 100644 --- a/t/unit-tests/lib-oid.h +++ b/t/unit-tests/lib-oid.h @@ -5,6 +5,7 @@ /* * Convert arbitrary hex string to object_id. + * * For example, passing "abc12" will generate * "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and * create object_id with that. @@ -12,14 +13,16 @@ * algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH * environment variable. */ -int get_oid_arbitrary_hex(const char *s, struct object_id *oid); + +void cl_parse_any_oid (const char *s, struct object_id *oid); /* * Returns one of GIT_HASH_{SHA1, SHA256, UNKNOWN} based on the value of * GIT_TEST_DEFAULT_HASH environment variable. The fallback value in the * absence of GIT_TEST_DEFAULT_HASH is GIT_HASH_SHA1. It also uses - * check(algo != GIT_HASH_UNKNOWN) before returning to verify if the + * cl_assert(algo != GIT_HASH_UNKNOWN) before returning to verify if the * GIT_TEST_DEFAULT_HASH's value is valid or not. */ -int init_hash_algo(void); + +int cl_setup_hash_algo(void); #endif /* LIB_OID_H */ diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c index 8a69612266..fdb5b11a20 100644 --- a/t/unit-tests/lib-reftable.c +++ b/t/unit-tests/lib-reftable.c @@ -1,12 +1,14 @@ -#define DISABLE_SIGN_COMPARE_WARNINGS - +#include "unit-test.h" #include "lib-reftable.h" -#include "test-lib.h" +#include "hex.h" +#include "parse-options.h" #include "reftable/constants.h" #include "reftable/writer.h" #include "strbuf.h" +#include "string-list.h" +#include "strvec.h" -void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) +void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) { memset(p, (uint8_t)i, hash_size(id)); } @@ -22,17 +24,17 @@ static int strbuf_writer_flush(void *arg UNUSED) return 0; } -struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, +struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf, struct reftable_write_options *opts) { struct reftable_writer *writer; int ret = reftable_writer_new(&writer, &strbuf_writer_write, &strbuf_writer_flush, buf, opts); - check(!ret); + cl_assert(!ret); return writer; } -void t_reftable_write_to_buf(struct reftable_buf *buf, +void cl_reftable_write_to_buf(struct reftable_buf *buf, struct reftable_ref_record *refs, size_t nrefs, struct reftable_log_record *logs, @@ -64,35 +66,36 @@ void t_reftable_write_to_buf(struct reftable_buf *buf, min = ui; } - writer = t_reftable_strbuf_writer(buf, &opts); - reftable_writer_set_limits(writer, min, max); + writer = cl_reftable_strbuf_writer(buf, &opts); + ret = reftable_writer_set_limits(writer, min, max); + cl_assert(!ret); if (nrefs) { ret = reftable_writer_add_refs(writer, refs, nrefs); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } if (nlogs) { ret = reftable_writer_add_logs(writer, logs, nlogs); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); } ret = reftable_writer_close(writer); - check_int(ret, ==, 0); + cl_assert_equal_i(ret, 0); stats = reftable_writer_stats(writer); - for (size_t i = 0; i < stats->ref_stats.blocks; i++) { + for (size_t i = 0; i < (size_t)stats->ref_stats.blocks; i++) { size_t off = i * (opts.block_size ? opts.block_size : DEFAULT_BLOCK_SIZE); if (!off) off = header_size(opts.hash_id == REFTABLE_HASH_SHA256 ? 2 : 1); - check_char(buf->buf[off], ==, 'r'); + cl_assert(buf->buf[off] == 'r'); } if (nrefs) - check_int(stats->ref_stats.blocks, >, 0); + cl_assert(stats->ref_stats.blocks > 0); if (nlogs) - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(writer); } diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h index e4c360fa7e..d7e6d3136f 100644 --- a/t/unit-tests/lib-reftable.h +++ b/t/unit-tests/lib-reftable.h @@ -1,21 +1,20 @@ -#ifndef LIB_REFTABLE_H -#define LIB_REFTABLE_H - +#include "git-compat-util.h" +#include "clar/clar.h" +#include "clar-decls.h" #include "git-compat-util.h" #include "reftable/reftable-writer.h" +#include "strbuf.h" struct reftable_buf; -void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); +void cl_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); -struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, +struct reftable_writer *cl_reftable_strbuf_writer(struct reftable_buf *buf, struct reftable_write_options *opts); -void t_reftable_write_to_buf(struct reftable_buf *buf, +void cl_reftable_write_to_buf(struct reftable_buf *buf, struct reftable_ref_record *refs, size_t nrecords, struct reftable_log_record *logs, size_t nlogs, struct reftable_write_options *opts); - -#endif diff --git a/t/unit-tests/t-example-decorate.c b/t/unit-tests/t-example-decorate.c deleted file mode 100644 index bfc776e223..0000000000 --- a/t/unit-tests/t-example-decorate.c +++ /dev/null @@ -1,74 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-lib.h" -#include "object.h" -#include "decorate.h" -#include "repository.h" - -struct test_vars { - struct object *one, *two, *three; - struct decoration n; - int decoration_a, decoration_b; -}; - -static void t_add(struct test_vars *vars) -{ - void *ret = add_decoration(&vars->n, vars->one, &vars->decoration_a); - - check(ret == NULL); - ret = add_decoration(&vars->n, vars->two, NULL); - check(ret == NULL); -} - -static void t_readd(struct test_vars *vars) -{ - void *ret = add_decoration(&vars->n, vars->one, NULL); - - check(ret == &vars->decoration_a); - ret = add_decoration(&vars->n, vars->two, &vars->decoration_b); - check(ret == NULL); -} - -static void t_lookup(struct test_vars *vars) -{ - void *ret = lookup_decoration(&vars->n, vars->one); - - check(ret == NULL); - ret = lookup_decoration(&vars->n, vars->two); - check(ret == &vars->decoration_b); - ret = lookup_decoration(&vars->n, vars->three); - check(ret == NULL); -} - -static void t_loop(struct test_vars *vars) -{ - int objects_noticed = 0; - - for (size_t i = 0; i < vars->n.size; i++) { - if (vars->n.entries[i].base) - objects_noticed++; - } - check_int(objects_noticed, ==, 2); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - struct object_id one_oid = { { 1 } }, two_oid = { { 2 } }, three_oid = { { 3 } }; - struct test_vars vars = { 0 }; - - vars.one = lookup_unknown_object(the_repository, &one_oid); - vars.two = lookup_unknown_object(the_repository, &two_oid); - vars.three = lookup_unknown_object(the_repository, &three_oid); - - TEST(t_add(&vars), - "Add 2 objects, one with a non-NULL decoration and one with a NULL decoration."); - TEST(t_readd(&vars), - "When re-adding an already existing object, the old decoration is returned."); - TEST(t_lookup(&vars), - "Lookup returns the added declarations, or NULL if the object was never added."); - TEST(t_loop(&vars), "The user can also loop through all entries."); - - clear_decoration(&vars.n, NULL); - - return test_done(); -} diff --git a/t/unit-tests/t-mem-pool.c b/t/unit-tests/t-mem-pool.c deleted file mode 100644 index fe500c704b..0000000000 --- a/t/unit-tests/t-mem-pool.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "test-lib.h" -#include "mem-pool.h" - -static void setup_static(void (*f)(struct mem_pool *), size_t block_alloc) -{ - struct mem_pool pool = { .block_alloc = block_alloc }; - f(&pool); - mem_pool_discard(&pool, 0); -} - -static void t_calloc_100(struct mem_pool *pool) -{ - size_t size = 100; - char *buffer = mem_pool_calloc(pool, 1, size); - for (size_t i = 0; i < size; i++) - check_int(buffer[i], ==, 0); - if (!check(pool->mp_block != NULL)) - return; - check(pool->mp_block->next_free != NULL); - check(pool->mp_block->end != NULL); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup_static(t_calloc_100, 1024 * 1024), - "mem_pool_calloc returns 100 zeroed bytes with big block"); - TEST(setup_static(t_calloc_100, 1), - "mem_pool_calloc returns 100 zeroed bytes with tiny block"); - - return test_done(); -} diff --git a/t/unit-tests/t-oid-array.c b/t/unit-tests/t-oid-array.c deleted file mode 100644 index 45b59a2a51..0000000000 --- a/t/unit-tests/t-oid-array.c +++ /dev/null @@ -1,126 +0,0 @@ -#define USE_THE_REPOSITORY_VARIABLE - -#include "test-lib.h" -#include "lib-oid.h" -#include "oid-array.h" -#include "hex.h" - -static int fill_array(struct oid_array *array, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oid_array_append(array, &oid); - } - if (!check_uint(array->nr, ==, n)) - return -1; - return 0; -} - -static int add_to_oid_array(const struct object_id *oid, void *data) -{ - struct oid_array *array = data; - - oid_array_append(array, oid); - return 0; -} - -static void t_enumeration(const char **input_args, size_t input_sz, - const char **expect_args, size_t expect_sz) -{ - struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, - actual = OID_ARRAY_INIT; - size_t i; - - if (fill_array(&input, input_args, input_sz)) - return; - if (fill_array(&expect, expect_args, expect_sz)) - return; - - oid_array_for_each_unique(&input, add_to_oid_array, &actual); - if (!check_uint(actual.nr, ==, expect.nr)) - return; - - for (i = 0; i < actual.nr; i++) { - if (!check(oideq(&actual.oid[i], &expect.oid[i]))) - test_msg("expected: %s\n got: %s\n index: %" PRIuMAX, - oid_to_hex(&expect.oid[i]), oid_to_hex(&actual.oid[i]), - (uintmax_t)i); - } - - oid_array_clear(&actual); - oid_array_clear(&input); - oid_array_clear(&expect); -} - -#define TEST_ENUMERATION(input, expect, desc) \ - TEST(t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)), \ - desc " works") - -static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, - int lower_bound, int upper_bound) -{ - struct oid_array array = OID_ARRAY_INIT; - struct object_id oid_query; - int ret; - - if (!check_int(get_oid_arbitrary_hex(query_hex, &oid_query), ==, 0)) - return; - if (fill_array(&array, input_hexes, n)) - return; - ret = oid_array_lookup(&array, &oid_query); - - if (!check_int(ret, <=, upper_bound) || - !check_int(ret, >=, lower_bound)) - test_msg("oid query for lookup: %s", oid_to_hex(&oid_query)); - - oid_array_clear(&array); -} - -#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound, desc) \ - TEST(t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ - lower_bound, upper_bound), \ - desc " works") - -static void setup(void) -{ - /* The hash algo is used by oid_array_lookup() internally */ - int algo = init_hash_algo(); - if (check_int(algo, !=, GIT_HASH_UNKNOWN)) - repo_set_hash_algo(the_repository, algo); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - const char *arr_input[] = { "88", "44", "aa", "55" }; - const char *arr_input_dup[] = { "88", "44", "aa", "55", - "88", "44", "aa", "55", - "88", "44", "aa", "55" }; - const char *res_sorted[] = { "44", "55", "88", "aa" }; - const char *nearly_55; - - if (!TEST(setup(), "setup")) - test_skip_all("hash algo initialization failed"); - - TEST_ENUMERATION(arr_input, res_sorted, "ordered enumeration"); - TEST_ENUMERATION(arr_input_dup, res_sorted, - "ordered enumeration with duplicate suppression"); - - TEST_LOOKUP(arr_input, "55", 1, 1, "lookup"); - TEST_LOOKUP(arr_input, "33", INT_MIN, -1, "lookup non-existent entry"); - TEST_LOOKUP(arr_input_dup, "55", 3, 5, "lookup with duplicates"); - TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1, - "lookup non-existent entry with duplicates"); - - nearly_55 = init_hash_algo() == GIT_HASH_SHA1 ? - "5500000000000000000000000000000000000001" : - "5500000000000000000000000000000000000000000000000000000000000001"; - TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0, - "lookup with almost duplicate values"); - TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1, - "lookup with single duplicate value"); - - return test_done(); -} diff --git a/t/unit-tests/t-oidmap.c b/t/unit-tests/t-oidmap.c deleted file mode 100644 index b22e52d08b..0000000000 --- a/t/unit-tests/t-oidmap.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidmap.h" -#include "hash.h" -#include "hex.h" - -/* - * Elements we will put in oidmap structs are made of a key: the entry.oid - * field, which is of type struct object_id, and a value: the name field (could - * be a refname for example). - */ -struct test_entry { - struct oidmap_entry entry; - char name[FLEX_ARRAY]; -}; - -static const char *const key_val[][2] = { { "11", "one" }, - { "22", "two" }, - { "33", "three" } }; - -static void setup(void (*f)(struct oidmap *map)) -{ - struct oidmap map = OIDMAP_INIT; - int ret = 0; - - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ - struct test_entry *entry; - - FLEX_ALLOC_STR(entry, name, key_val[i][1]); - if ((ret = get_oid_arbitrary_hex(key_val[i][0], &entry->entry.oid))) { - free(entry); - break; - } - entry = oidmap_put(&map, entry); - if (!check(entry == NULL)) - free(entry); - } - - if (!ret) - f(&map); - oidmap_free(&map, 1); -} - -static void t_replace(struct oidmap *map) -{ - struct test_entry *entry, *prev; - - FLEX_ALLOC_STR(entry, name, "un"); - if (get_oid_arbitrary_hex("11", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "one"); - free(prev); - - FLEX_ALLOC_STR(entry, name, "deux"); - if (get_oid_arbitrary_hex("22", &entry->entry.oid)) - return; - prev = oidmap_put(map, entry); - if (!check(prev != NULL)) - return; - check_str(prev->name, "two"); - free(prev); -} - -static void t_get(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_get(map, &oid) == NULL); - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_get(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); -} - -static void t_remove(struct oidmap *map) -{ - struct test_entry *entry; - struct object_id oid; - - if (get_oid_arbitrary_hex("11", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "one"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("22", &oid)) - return; - entry = oidmap_remove(map, &oid); - if (!check(entry != NULL)) - return; - check_str(entry->name, "two"); - check(oidmap_get(map, &oid) == NULL); - free(entry); - - if (get_oid_arbitrary_hex("44", &oid)) - return; - check(oidmap_remove(map, &oid) == NULL); -} - -static int key_val_contains(struct test_entry *entry, char seen[]) -{ - for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { - struct object_id oid; - - if (get_oid_arbitrary_hex(key_val[i][0], &oid)) - return -1; - - if (oideq(&entry->entry.oid, &oid)) { - if (seen[i]) - return 2; - seen[i] = 1; - return 0; - } - } - return 1; -} - -static void t_iterate(struct oidmap *map) -{ - struct oidmap_iter iter; - struct test_entry *entry; - char seen[ARRAY_SIZE(key_val)] = { 0 }; - int count = 0; - - oidmap_iter_init(map, &iter); - while ((entry = oidmap_iter_next(&iter))) { - int ret; - if (!check_int((ret = key_val_contains(entry, seen)), ==, 0)) { - switch (ret) { - case -1: - break; /* error message handled by get_oid_arbitrary_hex() */ - case 1: - test_msg("obtained entry was not given in the input\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - case 2: - test_msg("duplicate entry detected\n" - " name: %s\n oid: %s\n", - entry->name, oid_to_hex(&entry->entry.oid)); - break; - default: - test_msg("BUG: invalid return value (%d) from key_val_contains()", - ret); - break; - } - } else { - count++; - } - } - check_int(count, ==, ARRAY_SIZE(key_val)); - check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val)); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_replace), "replace works"); - TEST(setup(t_get), "get works"); - TEST(setup(t_remove), "remove works"); - TEST(setup(t_iterate), "iterate works"); - return test_done(); -} diff --git a/t/unit-tests/t-oidtree.c b/t/unit-tests/t-oidtree.c deleted file mode 100644 index a38754b066..0000000000 --- a/t/unit-tests/t-oidtree.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "test-lib.h" -#include "lib-oid.h" -#include "oidtree.h" -#include "hash.h" -#include "hex.h" -#include "strvec.h" - -#define FILL_TREE(tree, ...) \ - do { \ - const char *hexes[] = { __VA_ARGS__ }; \ - if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ - return; \ - } while (0) - -static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) -{ - for (size_t i = 0; i < n; i++) { - struct object_id oid; - if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) - return -1; - oidtree_insert(ot, &oid); - } - return 0; -} - -static void check_contains(struct oidtree *ot, const char *hex, int expected) -{ - struct object_id oid; - - if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0)) - return; - if (!check_int(oidtree_contains(ot, &oid), ==, expected)) - test_msg("oid: %s", oid_to_hex(&oid)); -} - -struct expected_hex_iter { - size_t i; - struct strvec expected_hexes; - const char *query; -}; - -static enum cb_next check_each_cb(const struct object_id *oid, void *data) -{ - struct expected_hex_iter *hex_iter = data; - struct object_id expected; - - if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) { - test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')", - hex_iter->query, oid_to_hex(oid)); - return CB_BREAK; - } - - if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i], - &expected), ==, 0)) - ; /* the data is bogus and cannot be used */ - else if (!check(oideq(oid, &expected))) - test_msg("expected: %s\n got: %s\n query: %s", - oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query); - - hex_iter->i += 1; - return CB_CONTINUE; -} - -LAST_ARG_MUST_BE_NULL -static void check_each(struct oidtree *ot, const char *query, ...) -{ - struct object_id oid; - struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, - .query = query }; - const char *arg; - va_list hex_args; - - va_start(hex_args, query); - while ((arg = va_arg(hex_args, const char *))) - strvec_push(&hex_iter.expected_hexes, arg); - va_end(hex_args); - - if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0)) - return; - oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); - - if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr)) - test_msg("error: could not find some 'object_id's for query ('%s')", query); - strvec_clear(&hex_iter.expected_hexes); -} - -static void setup(void (*f)(struct oidtree *ot)) -{ - struct oidtree ot; - - oidtree_init(&ot); - f(&ot); - oidtree_clear(&ot); -} - -static void t_contains(struct oidtree *ot) -{ - FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); - check_contains(ot, "44", 0); - check_contains(ot, "441", 0); - check_contains(ot, "440", 0); - check_contains(ot, "444", 1); - check_contains(ot, "4440", 1); - check_contains(ot, "4444", 0); -} - -static void t_each(struct oidtree *ot) -{ - FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); - check_each(ot, "12300", "123", NULL); - check_each(ot, "3211", NULL); /* should not reach callback */ - check_each(ot, "3210", "321", NULL); - check_each(ot, "32100", "321", NULL); - check_each(ot, "32", "320", "321", NULL); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(setup(t_contains), "oidtree insert and contains works"); - TEST(setup(t_each), "oidtree each works"); - return test_done(); -} diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c deleted file mode 100644 index a053635000..0000000000 --- a/t/unit-tests/t-prio-queue.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "test-lib.h" -#include "prio-queue.h" - -static int intcmp(const void *va, const void *vb, void *data UNUSED) -{ - const int *a = va, *b = vb; - return *a - *b; -} - - -#define MISSING -1 -#define DUMP -2 -#define STACK -3 -#define GET -4 -#define REVERSE -5 - -static int show(int *v) -{ - return v ? *v : MISSING; -} - -static void test_prio_queue(int *input, size_t input_size, - int *result, size_t result_size) -{ - struct prio_queue pq = { intcmp }; - int j = 0; - - for (size_t i = 0; i < input_size; i++) { - void *peek, *get; - switch(input[i]) { - case GET: - peek = prio_queue_peek(&pq); - get = prio_queue_get(&pq); - if (!check(peek == get)) - return; - if (!check_uint(j, <, result_size)) - break; - if (!check_int(result[j], ==, show(get))) - test_msg(" j: %d", j); - j++; - break; - case DUMP: - while ((peek = prio_queue_peek(&pq))) { - get = prio_queue_get(&pq); - if (!check(peek == get)) - return; - if (!check_uint(j, <, result_size)) - break; - if (!check_int(result[j], ==, show(get))) - test_msg(" j: %d", j); - j++; - } - break; - case STACK: - pq.compare = NULL; - break; - case REVERSE: - prio_queue_reverse(&pq); - break; - default: - prio_queue_put(&pq, &input[i]); - break; - } - } - check_uint(j, ==, result_size); - clear_prio_queue(&pq); -} - -#define TEST_INPUT(input, result) \ - test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }), - ((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 })), - "prio-queue works for basic input"); - TEST(TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }), - ((int []){ 2, 3, 4, 1, 5, 6 })), - "prio-queue works for mixed put & get commands"); - TEST(TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }), - ((int []){ 1, 2, MISSING, 1, 2, MISSING })), - "prio-queue works when queue is empty"); - TEST(TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), - ((int []){ 3, 2, 6, 4, 5, 1, 8 })), - "prio-queue works when used as a LIFO stack"); - TEST(TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), - ((int []){ 1, 2, 3, 4, 5, 6 })), - "prio-queue works when LIFO stack is reversed"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c deleted file mode 100644 index 1d640b280f..0000000000 --- a/t/unit-tests/t-reftable-basics.c +++ /dev/null @@ -1,201 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "test-lib.h" -#include "reftable/basics.h" - -struct integer_needle_lesseq_args { - int needle; - int *haystack; -}; - -static int integer_needle_lesseq(size_t i, void *_args) -{ - struct integer_needle_lesseq_args *args = _args; - return args->needle <= args->haystack[i]; -} - -static void *realloc_stub(void *p UNUSED, size_t size UNUSED) -{ - return NULL; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - if_test ("binary search with binsearch works") { - int haystack[] = { 2, 4, 6, 8, 10 }; - struct { - int needle; - size_t expected_idx; - } testcases[] = { - {-9000, 0}, - {-1, 0}, - {0, 0}, - {2, 0}, - {3, 1}, - {4, 1}, - {7, 3}, - {9, 4}, - {10, 4}, - {11, 5}, - {9000, 5}, - }; - - for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { - struct integer_needle_lesseq_args args = { - .haystack = haystack, - .needle = testcases[i].needle, - }; - size_t idx; - - idx = binsearch(ARRAY_SIZE(haystack), - &integer_needle_lesseq, &args); - check_int(idx, ==, testcases[i].expected_idx); - } - } - - if_test ("names_length returns size of a NULL-terminated string array") { - const char *a[] = { "a", "b", NULL }; - check_int(names_length(a), ==, 2); - } - - if_test ("names_equal compares NULL-terminated string arrays") { - const char *a[] = { "a", "b", "c", NULL }; - const char *b[] = { "a", "b", "d", NULL }; - const char *c[] = { "a", "b", NULL }; - - check(names_equal(a, a)); - check(!names_equal(a, b)); - check(!names_equal(a, c)); - } - - if_test ("parse_names works for basic input") { - char in1[] = "line\n"; - char in2[] = "a\nb\nc"; - char **out = parse_names(in1, strlen(in1)); - check(out != NULL); - check_str(out[0], "line"); - check(!out[1]); - free_names(out); - - out = parse_names(in2, strlen(in2)); - check(out != NULL); - check_str(out[0], "a"); - check_str(out[1], "b"); - check_str(out[2], "c"); - check(!out[3]); - free_names(out); - } - - if_test ("parse_names drops empty string") { - char in[] = "a\n\nb\n"; - char **out = parse_names(in, strlen(in)); - check(out != NULL); - check_str(out[0], "a"); - /* simply '\n' should be dropped as empty string */ - check_str(out[1], "b"); - check(!out[2]); - free_names(out); - } - - if_test ("common_prefix_size works") { - struct reftable_buf a = REFTABLE_BUF_INIT; - struct reftable_buf b = REFTABLE_BUF_INIT; - struct { - const char *a, *b; - int want; - } cases[] = { - {"abcdef", "abc", 3}, - { "abc", "ab", 2 }, - { "", "abc", 0 }, - { "abc", "abd", 2 }, - { "abc", "pqr", 0 }, - }; - - for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { - check(!reftable_buf_addstr(&a, cases[i].a)); - check(!reftable_buf_addstr(&b, cases[i].b)); - check_int(common_prefix_size(&a, &b), ==, cases[i].want); - reftable_buf_reset(&a); - reftable_buf_reset(&b); - } - reftable_buf_release(&a); - reftable_buf_release(&b); - } - - if_test ("put_be24 and get_be24 work") { - uint32_t in = 0x112233; - uint8_t dest[3]; - uint32_t out; - put_be24(dest, in); - out = get_be24(dest); - check_int(in, ==, out); - } - - if_test ("put_be16 and get_be16 work") { - uint32_t in = 0xfef1; - uint8_t dest[3]; - uint32_t out; - put_be16(dest, in); - out = get_be16(dest); - check_int(in, ==, out); - } - - if_test ("REFTABLE_ALLOC_GROW works") { - int *arr = NULL, *old_arr; - size_t alloc = 0, old_alloc; - - check(!REFTABLE_ALLOC_GROW(arr, 1, alloc)); - check(arr != NULL); - check_uint(alloc, >=, 1); - arr[0] = 42; - - old_alloc = alloc; - old_arr = arr; - reftable_set_alloc(NULL, realloc_stub, NULL); - check(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); - check(arr == old_arr); - check_uint(alloc, ==, old_alloc); - - old_alloc = alloc; - reftable_set_alloc(NULL, NULL, NULL); - check(!REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); - check(arr != NULL); - check_uint(alloc, >, old_alloc); - arr[alloc - 1] = 42; - - reftable_free(arr); - } - - if_test ("REFTABLE_ALLOC_GROW_OR_NULL works") { - int *arr = NULL; - size_t alloc = 0, old_alloc; - - REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc); - check(arr != NULL); - check_uint(alloc, >=, 1); - arr[0] = 42; - - old_alloc = alloc; - REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); - check(arr != NULL); - check_uint(alloc, >, old_alloc); - arr[alloc - 1] = 42; - - old_alloc = alloc; - reftable_set_alloc(NULL, realloc_stub, NULL); - REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); - check(arr == NULL); - check_uint(alloc, ==, 0); - reftable_set_alloc(NULL, NULL, NULL); - - reftable_free(arr); - } - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c deleted file mode 100644 index 22040aeefa..0000000000 --- a/t/unit-tests/t-reftable-block.c +++ /dev/null @@ -1,383 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "test-lib.h" -#include "reftable/block.h" -#include "reftable/blocksource.h" -#include "reftable/constants.h" -#include "reftable/reftable-error.h" -#include "strbuf.h" - -static void t_ref_block_read_write(void) -{ - const int header_off = 21; /* random */ - struct reftable_record recs[30]; - const size_t N = ARRAY_SIZE(recs); - const size_t block_size = 1024; - struct reftable_block block = { 0 }; - struct block_writer bw = { - .last_key = REFTABLE_BUF_INIT, - }; - struct reftable_record rec = { - .type = BLOCK_TYPE_REF, - }; - size_t i = 0; - int ret; - struct block_reader br = { 0 }; - struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; - - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, - header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); - - rec.u.ref.refname = (char *) ""; - rec.u.ref.value_type = REFTABLE_REF_DELETION; - ret = block_writer_add(&bw, &rec); - check_int(ret, ==, REFTABLE_API_ERROR); - - for (i = 0; i < N; i++) { - rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); - rec.u.ref.value_type = REFTABLE_REF_VAL1; - memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); - - recs[i] = rec; - ret = block_writer_add(&bw, &rec); - rec.u.ref.refname = NULL; - rec.u.ref.value_type = REFTABLE_REF_DELETION; - check_int(ret, ==, 0); - } - - ret = block_writer_finish(&bw); - check_int(ret, >, 0); - - block_writer_release(&bw); - - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - - block_iter_seek_start(&it, &br); - - for (i = 0; ; i++) { - ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); - if (ret > 0) { - check_int(i, ==, N); - break; - } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - for (i = 0; i < N; i++) { - block_iter_reset(&it); - reftable_record_key(&recs[i], &want); - - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - - want.len--; - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - block_reader_release(&br); - block_iter_close(&it); - reftable_record_release(&rec); - reftable_block_done(&br.block); - reftable_buf_release(&want); - reftable_buf_release(&buf); - for (i = 0; i < N; i++) - reftable_record_release(&recs[i]); -} - -static void t_log_block_read_write(void) -{ - const int header_off = 21; - struct reftable_record recs[30]; - const size_t N = ARRAY_SIZE(recs); - const size_t block_size = 2048; - struct reftable_block block = { 0 }; - struct block_writer bw = { - .last_key = REFTABLE_BUF_INIT, - }; - struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, - }; - size_t i = 0; - int ret; - struct block_reader br = { 0 }; - struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; - - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, - header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); - - for (i = 0; i < N; i++) { - rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); - rec.u.log.update_index = i; - rec.u.log.value_type = REFTABLE_LOG_UPDATE; - - recs[i] = rec; - ret = block_writer_add(&bw, &rec); - rec.u.log.refname = NULL; - rec.u.log.value_type = REFTABLE_LOG_DELETION; - check_int(ret, ==, 0); - } - - ret = block_writer_finish(&bw); - check_int(ret, >, 0); - - block_writer_release(&bw); - - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - - block_iter_seek_start(&it, &br); - - for (i = 0; ; i++) { - ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); - if (ret > 0) { - check_int(i, ==, N); - break; - } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - for (i = 0; i < N; i++) { - block_iter_reset(&it); - reftable_buf_reset(&want); - check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); - - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - - want.len--; - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - block_reader_release(&br); - block_iter_close(&it); - reftable_record_release(&rec); - reftable_block_done(&br.block); - reftable_buf_release(&want); - reftable_buf_release(&buf); - for (i = 0; i < N; i++) - reftable_record_release(&recs[i]); -} - -static void t_obj_block_read_write(void) -{ - const int header_off = 21; - struct reftable_record recs[30]; - const size_t N = ARRAY_SIZE(recs); - const size_t block_size = 1024; - struct reftable_block block = { 0 }; - struct block_writer bw = { - .last_key = REFTABLE_BUF_INIT, - }; - struct reftable_record rec = { - .type = BLOCK_TYPE_OBJ, - }; - size_t i = 0; - int ret; - struct block_reader br = { 0 }; - struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; - - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, - header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); - - for (i = 0; i < N; i++) { - uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; - DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes)); - - rec.u.obj.hash_prefix = allocated; - rec.u.obj.hash_prefix_len = 5; - - recs[i] = rec; - ret = block_writer_add(&bw, &rec); - rec.u.obj.hash_prefix = NULL; - rec.u.obj.hash_prefix_len = 0; - check_int(ret, ==, 0); - } - - ret = block_writer_finish(&bw); - check_int(ret, >, 0); - - block_writer_release(&bw); - - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - - block_iter_seek_start(&it, &br); - - for (i = 0; ; i++) { - ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); - if (ret > 0) { - check_int(i, ==, N); - break; - } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - for (i = 0; i < N; i++) { - block_iter_reset(&it); - reftable_record_key(&recs[i], &want); - - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - block_reader_release(&br); - block_iter_close(&it); - reftable_record_release(&rec); - reftable_block_done(&br.block); - reftable_buf_release(&want); - reftable_buf_release(&buf); - for (i = 0; i < N; i++) - reftable_record_release(&recs[i]); -} - -static void t_index_block_read_write(void) -{ - const int header_off = 21; - struct reftable_record recs[30]; - const size_t N = ARRAY_SIZE(recs); - const size_t block_size = 1024; - struct reftable_block block = { 0 }; - struct block_writer bw = { - .last_key = REFTABLE_BUF_INIT, - }; - struct reftable_record rec = { - .type = BLOCK_TYPE_INDEX, - .u.idx.last_key = REFTABLE_BUF_INIT, - }; - size_t i = 0; - int ret; - struct block_reader br = { 0 }; - struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; - - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, - header_off, hash_size(REFTABLE_HASH_SHA1)); - check(!ret); - - for (i = 0; i < N; i++) { - char buf[128]; - - snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); - - reftable_buf_init(&recs[i].u.idx.last_key); - recs[i].type = BLOCK_TYPE_INDEX; - check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); - recs[i].u.idx.offset = i; - - ret = block_writer_add(&bw, &recs[i]); - check_int(ret, ==, 0); - } - - ret = block_writer_finish(&bw); - check_int(ret, >, 0); - - block_writer_release(&bw); - - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); - - block_iter_seek_start(&it, &br); - - for (i = 0; ; i++) { - ret = block_iter_next(&it, &rec); - check_int(ret, >=, 0); - if (ret > 0) { - check_int(i, ==, N); - break; - } - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - for (i = 0; i < N; i++) { - block_iter_reset(&it); - reftable_record_key(&recs[i], &want); - - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - - check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); - - want.len--; - ret = block_iter_seek_key(&it, &br, &want); - check_int(ret, ==, 0); - - ret = block_iter_next(&it, &rec); - check_int(ret, ==, 0); - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); - } - - block_reader_release(&br); - block_iter_close(&it); - reftable_record_release(&rec); - reftable_block_done(&br.block); - reftable_buf_release(&want); - reftable_buf_release(&buf); - for (i = 0; i < N; i++) - reftable_record_release(&recs[i]); -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_index_block_read_write(), "read-write operations on index blocks work"); - TEST(t_log_block_read_write(), "read-write operations on log blocks work"); - TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); - TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c deleted file mode 100644 index 546df6005e..0000000000 --- a/t/unit-tests/t-reftable-reader.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "test-lib.h" -#include "lib-reftable.h" -#include "reftable/blocksource.h" -#include "reftable/reader.h" - -static int t_reader_seek_once(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -static int t_reader_reseek(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - - for (size_t i = 0; i < 5; i++) { - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - } - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_reader_seek_once(), "reader can seek once"); - TEST(t_reader_reseek(), "reader can reseek multiple times"); - return test_done(); -} diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c deleted file mode 100644 index 3f4044d697..0000000000 --- a/t/unit-tests/t-strbuf.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "test-lib.h" -#include "strbuf.h" - -/* wrapper that supplies tests with an empty, initialized strbuf */ -static void setup(void (*f)(struct strbuf*, const void*), - const void *data) -{ - struct strbuf buf = STRBUF_INIT; - - f(&buf, data); - strbuf_release(&buf); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); -} - -/* wrapper that supplies tests with a populated, initialized strbuf */ -static void setup_populated(void (*f)(struct strbuf*, const void*), - const char *init_str, const void *data) -{ - struct strbuf buf = STRBUF_INIT; - - strbuf_addstr(&buf, init_str); - check_uint(buf.len, ==, strlen(init_str)); - f(&buf, data); - strbuf_release(&buf); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); -} - -static int assert_sane_strbuf(struct strbuf *buf) -{ - /* Initialized strbufs should always have a non-NULL buffer */ - if (!check(!!buf->buf)) - return 0; - /* Buffers should always be NUL-terminated */ - if (!check_char(buf->buf[buf->len], ==, '\0')) - return 0; - /* - * Freshly-initialized strbufs may not have a dynamically allocated - * buffer - */ - if (buf->len == 0 && buf->alloc == 0) - return 1; - /* alloc must be at least one byte larger than len */ - return check_uint(buf->len, <, buf->alloc); -} - -static void t_static_init(void) -{ - struct strbuf buf = STRBUF_INIT; - - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, ==, 0); - check_char(buf.buf[0], ==, '\0'); -} - -static void t_dynamic_init(void) -{ - struct strbuf buf; - - strbuf_init(&buf, 1024); - check(assert_sane_strbuf(&buf)); - check_uint(buf.len, ==, 0); - check_uint(buf.alloc, >=, 1024); - check_char(buf.buf[0], ==, '\0'); - strbuf_release(&buf); -} - -static void t_addch(struct strbuf *buf, const void *data) -{ - const char *p_ch = data; - const char ch = *p_ch; - size_t orig_alloc = buf->alloc; - size_t orig_len = buf->len; - - if (!check(assert_sane_strbuf(buf))) - return; - strbuf_addch(buf, ch); - if (!check(assert_sane_strbuf(buf))) - return; - if (!(check_uint(buf->len, ==, orig_len + 1) && - check_uint(buf->alloc, >=, orig_alloc))) - return; /* avoid de-referencing buf->buf */ - check_char(buf->buf[buf->len - 1], ==, ch); - check_char(buf->buf[buf->len], ==, '\0'); -} - -static void t_addstr(struct strbuf *buf, const void *data) -{ - const char *text = data; - size_t len = strlen(text); - size_t orig_alloc = buf->alloc; - size_t orig_len = buf->len; - - if (!check(assert_sane_strbuf(buf))) - return; - strbuf_addstr(buf, text); - if (!check(assert_sane_strbuf(buf))) - return; - if (!(check_uint(buf->len, ==, orig_len + len) && - check_uint(buf->alloc, >=, orig_alloc) && - check_uint(buf->alloc, >, orig_len + len) && - check_char(buf->buf[orig_len + len], ==, '\0'))) - return; - check_str(buf->buf + orig_len, text); -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - if (!TEST(t_static_init(), "static initialization works")) - test_skip_all("STRBUF_INIT is broken"); - TEST(t_dynamic_init(), "dynamic initialization works"); - TEST(setup(t_addch, "a"), "strbuf_addch adds char"); - TEST(setup(t_addch, ""), "strbuf_addch adds NUL char"); - TEST(setup_populated(t_addch, "initial value", "a"), - "strbuf_addch appends to initial value"); - TEST(setup(t_addstr, "hello there"), "strbuf_addstr adds string"); - TEST(setup_populated(t_addstr, "initial value", "hello there"), - "strbuf_addstr appends string to initial value"); - - return test_done(); -} diff --git a/t/unit-tests/t-strcmp-offset.c b/t/unit-tests/t-strcmp-offset.c deleted file mode 100644 index 6880f21161..0000000000 --- a/t/unit-tests/t-strcmp-offset.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "test-lib.h" -#include "read-cache-ll.h" - -static void check_strcmp_offset(const char *string1, const char *string2, - int expect_result, uintmax_t expect_offset) -{ - size_t offset; - int result = strcmp_offset(string1, string2, &offset); - - /* - * Because different CRTs behave differently, only rely on signs of the - * result values. - */ - result = (result < 0 ? -1 : - result > 0 ? 1 : - 0); - - check_int(result, ==, expect_result); - check_uint((uintmax_t)offset, ==, expect_offset); -} - -#define TEST_STRCMP_OFFSET(string1, string2, expect_result, expect_offset) \ - TEST(check_strcmp_offset(string1, string2, expect_result, \ - expect_offset), \ - "strcmp_offset(%s, %s) works", #string1, #string2) - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST_STRCMP_OFFSET("abc", "abc", 0, 3); - TEST_STRCMP_OFFSET("abc", "def", -1, 0); - TEST_STRCMP_OFFSET("abc", "abz", -1, 2); - TEST_STRCMP_OFFSET("abc", "abcdef", -1, 3); - - return test_done(); -} diff --git a/t/unit-tests/t-trailer.c b/t/unit-tests/t-trailer.c deleted file mode 100644 index 184593e73d..0000000000 --- a/t/unit-tests/t-trailer.c +++ /dev/null @@ -1,317 +0,0 @@ -#define DISABLE_SIGN_COMPARE_WARNINGS - -#include "test-lib.h" -#include "trailer.h" - -struct contents { - const char *raw; - const char *key; - const char *val; -}; - -static void t_trailer_iterator(const char *msg, size_t num_expected, - struct contents *contents) -{ - struct trailer_iterator iter; - size_t i = 0; - - trailer_iterator_init(&iter, msg); - while (trailer_iterator_advance(&iter)) { - if (num_expected) { - check_str(iter.raw, contents[i].raw); - check_str(iter.key.buf, contents[i].key); - check_str(iter.val.buf, contents[i].val); - } - i++; - } - trailer_iterator_release(&iter); - - check_uint(i, ==, num_expected); -} - -static void run_t_trailer_iterator(void) -{ - - static struct test_cases { - const char *name; - const char *msg; - size_t num_expected; - struct contents contents[10]; - } tc[] = { - { - "empty input", - "", - 0, - {{0}}, - }, - { - "no newline at beginning", - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 0, - {{0}}, - }, - { - "newline at beginning", - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 3, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "without body text", - "subject: foo bar\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 3, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, without divider", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n" - "Signed-off-by: x\n", - 4, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, without divider (second trailer block)", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n" - "Signed-off-by: x\n" - "\n" - /* - * Because this is the last trailer block, it takes - * precedence over the first one encountered above. - */ - "Helped-by: x\n" - "Signed-off-by: x\n", - 2, - { - { - .raw = "Helped-by: x\n", - .key = "Helped-by", - .val = "x", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, with divider", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "---\n" - "\n" - /* - * This trailer still counts because the iterator - * always ignores the divider. - */ - "Signed-off-by: x\n", - 1, - { - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with non-trailer lines in trailer block", - "subject: foo bar\n" - "\n" - /* - * Even though this trailer block has a non-trailer line - * in it, it's still a valid trailer block because it's - * at least 25% trailers and is Git-generated (see - * git_generated_prefixes[] in trailer.c). - */ - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "Signed-off-by: x\n", - /* - * Even though there is only really 1 real "trailer" - * (Signed-off-by), we still have 4 trailer objects - * because we still want to iterate through the entire - * block. - */ - 4, - { - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with non-trailer lines (one too many) in trailer block", - "subject: foo bar\n" - "\n" - /* - * This block has only 20% trailers, so it's below the - * 25% threshold. - */ - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "Signed-off-by: x\n", - 0, - {{0}}, - }, - { - "with non-trailer lines (only 1) in trailer block, but no Git-generated trailers", - "subject: foo bar\n" - "\n" - /* - * This block has only 1 non-trailer out of 10 (IOW, 90% - * trailers) but is not considered a trailer block - * because the 25% threshold only applies to cases where - * there was a Git-generated trailer. - */ - "Reviewed-by: x\n" - "Reviewed-by: x\n" - "Reviewed-by: x\n" - "Helped-by: x\n" - "Helped-by: x\n" - "Helped-by: x\n" - "Acked-by: x\n" - "Acked-by: x\n" - "Acked-by: x\n" - "not a trailer line\n", - 0, - {{0}}, - }, - }; - - for (int i = 0; i < sizeof(tc) / sizeof(tc[0]); i++) { - TEST(t_trailer_iterator(tc[i].msg, - tc[i].num_expected, - tc[i].contents), - "%s", tc[i].name); - } -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - run_t_trailer_iterator(); - return test_done(); -} diff --git a/t/unit-tests/u-dir.c b/t/unit-tests/u-dir.c new file mode 100644 index 0000000000..2d0adaa39e --- /dev/null +++ b/t/unit-tests/u-dir.c @@ -0,0 +1,47 @@ +#include "unit-test.h" +#include "dir.h" + +#define TEST_WITHIN_DEPTH(path, depth, max_depth, expect) do { \ + int actual = within_depth(path, strlen(path), \ + depth, max_depth); \ + if (actual != expect) \ + cl_failf("path '%s' with depth '%d' and max-depth '%d': expected %d, got %d", \ + path, depth, max_depth, expect, actual); \ + } while (0) + +void test_dir__within_depth(void) +{ + /* depth = 0; max_depth = 0 */ + TEST_WITHIN_DEPTH("", 0, 0, 1); + TEST_WITHIN_DEPTH("file", 0, 0, 1); + TEST_WITHIN_DEPTH("a", 0, 0, 1); + TEST_WITHIN_DEPTH("a/file", 0, 0, 0); + TEST_WITHIN_DEPTH("a/b", 0, 0, 0); + TEST_WITHIN_DEPTH("a/b/file", 0, 0, 0); + + /* depth = 0; max_depth = 1 */ + TEST_WITHIN_DEPTH("", 0, 1, 1); + TEST_WITHIN_DEPTH("file", 0, 1, 1); + TEST_WITHIN_DEPTH("a", 0, 1, 1); + TEST_WITHIN_DEPTH("a/file", 0, 1, 1); + TEST_WITHIN_DEPTH("a/b", 0, 1, 1); + TEST_WITHIN_DEPTH("a/b/file", 0, 1, 0); + + /* depth = 1; max_depth = 1 */ + TEST_WITHIN_DEPTH("", 1, 1, 1); + TEST_WITHIN_DEPTH("file", 1, 1, 1); + TEST_WITHIN_DEPTH("a", 1, 1, 1); + TEST_WITHIN_DEPTH("a/file", 1, 1, 0); + TEST_WITHIN_DEPTH("a/b", 1, 1, 0); + TEST_WITHIN_DEPTH("a/b/file", 1, 1, 0); + + /* depth = 1; max_depth = 0 */ + TEST_WITHIN_DEPTH("", 1, 0, 0); + TEST_WITHIN_DEPTH("file", 1, 0, 0); + TEST_WITHIN_DEPTH("a", 1, 0, 0); + TEST_WITHIN_DEPTH("a/file", 1, 0, 0); + TEST_WITHIN_DEPTH("a/b", 1, 0, 0); + TEST_WITHIN_DEPTH("a/b/file", 1, 0, 0); + + +} diff --git a/t/unit-tests/u-example-decorate.c b/t/unit-tests/u-example-decorate.c new file mode 100644 index 0000000000..9b1d1ce753 --- /dev/null +++ b/t/unit-tests/u-example-decorate.c @@ -0,0 +1,64 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "unit-test.h" +#include "object.h" +#include "decorate.h" +#include "repository.h" + +struct test_vars { + struct object *one, *two, *three; + struct decoration n; + int decoration_a, decoration_b; +}; + +static struct test_vars vars; + +void test_example_decorate__initialize(void) +{ + struct object_id one_oid = { { 1 } }, two_oid = { { 2 } }, three_oid = { { 3 } }; + + vars.one = lookup_unknown_object(the_repository, &one_oid); + vars.two = lookup_unknown_object(the_repository, &two_oid); + vars.three = lookup_unknown_object(the_repository, &three_oid); +} + +void test_example_decorate__cleanup(void) +{ + clear_decoration(&vars.n, NULL); +} + +void test_example_decorate__add(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, NULL), NULL); +} + +void test_example_decorate__readd(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, NULL), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.one, NULL), &vars.decoration_a); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); +} + +void test_example_decorate__lookup(void) +{ + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.one, NULL), NULL); + cl_assert_equal_p(lookup_decoration(&vars.n, vars.two), &vars.decoration_b); + cl_assert_equal_p(lookup_decoration(&vars.n, vars.one), NULL); +} + +void test_example_decorate__loop(void) +{ + int objects_noticed = 0; + + cl_assert_equal_p(add_decoration(&vars.n, vars.one, &vars.decoration_a), NULL); + cl_assert_equal_p(add_decoration(&vars.n, vars.two, &vars.decoration_b), NULL); + + for (size_t i = 0; i < vars.n.size; i++) + if (vars.n.entries[i].base) + objects_noticed++; + + cl_assert_equal_i(objects_noticed, 2); +} diff --git a/t/unit-tests/t-hash.c b/t/unit-tests/u-hash.c index e62647019b..bd4ac6a6e1 100644 --- a/t/unit-tests/t-hash.c +++ b/t/unit-tests/u-hash.c @@ -1,84 +1,109 @@ -#include "test-lib.h" +#include "unit-test.h" #include "hex.h" #include "strbuf.h" static void check_hash_data(const void *data, size_t data_length, const char *expected_hashes[]) { - if (!check(data != NULL)) { - test_msg("BUG: NULL data pointer provided"); - return; - } + cl_assert(data != NULL); for (size_t i = 1; i < ARRAY_SIZE(hash_algos); i++) { - git_hash_ctx ctx; + struct git_hash_ctx ctx; unsigned char hash[GIT_MAX_HEXSZ]; const struct git_hash_algo *algop = &hash_algos[i]; algop->init_fn(&ctx); - algop->update_fn(&ctx, data, data_length); - algop->final_fn(hash, &ctx); + git_hash_update(&ctx, data, data_length); + git_hash_final(hash, &ctx); - if (!check_str(hash_to_hex_algop(hash, algop), expected_hashes[i - 1])) - test_msg("result does not match with the expected for %s\n", hash_algos[i].name); + cl_assert_equal_s(hash_to_hex_algop(hash,algop), expected_hashes[i - 1]); } } /* Works with a NUL terminated string. Doesn't work if it should contain a NUL character. */ #define TEST_HASH_STR(data, expected_sha1, expected_sha256) do { \ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \ - TEST(check_hash_data(data, strlen(data), expected_hashes), \ - "SHA1 and SHA256 (%s) works", #data); \ + check_hash_data(data, strlen(data), expected_hashes); \ } while (0) /* Only works with a literal string, useful when it contains a NUL character. */ #define TEST_HASH_LITERAL(literal, expected_sha1, expected_sha256) do { \ const char *expected_hashes[] = { expected_sha1, expected_sha256 }; \ - TEST(check_hash_data(literal, (sizeof(literal) - 1), expected_hashes), \ - "SHA1 and SHA256 (%s) works", #literal); \ + check_hash_data(literal, (sizeof(literal) - 1), expected_hashes); \ } while (0) -int cmd_main(int argc UNUSED, const char **argv UNUSED) +void test_hash__empty_string(void) { - struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT; - struct strbuf alphabet_100000 = STRBUF_INIT; - - strbuf_addstrings(&aaaaaaaaaa_100000, "aaaaaaaaaa", 100000); - strbuf_addstrings(&alphabet_100000, "abcdefghijklmnopqrstuvwxyz", 100000); - TEST_HASH_STR("", "da39a3ee5e6b4b0d3255bfef95601890afd80709", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); +} + +void test_hash__single_character(void) +{ TEST_HASH_STR("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"); +} + +void test_hash__multi_character(void) +{ TEST_HASH_STR("abc", "a9993e364706816aba3e25717850c26c9cd0d89d", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); +} + +void test_hash__message_digest(void) +{ TEST_HASH_STR("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3", "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); +} + +void test_hash__alphabet(void) +{ TEST_HASH_STR("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89", "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73"); +} + +void test_hash__aaaaaaaaaa_100000(void) +{ + struct strbuf aaaaaaaaaa_100000 = STRBUF_INIT; + strbuf_addstrings(&aaaaaaaaaa_100000, "aaaaaaaaaa", 100000); TEST_HASH_STR(aaaaaaaaaa_100000.buf, "34aa973cd4c4daa4f61eeb2bdbad27316534016f", "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); + strbuf_release(&aaaaaaaaaa_100000); +} + +void test_hash__alphabet_100000(void) +{ + struct strbuf alphabet_100000 = STRBUF_INIT; + strbuf_addstrings(&alphabet_100000, "abcdefghijklmnopqrstuvwxyz", 100000); TEST_HASH_STR(alphabet_100000.buf, "e7da7c55b3484fdf52aebec9cbe7b85a98f02fd4", "e406ba321ca712ad35a698bf0af8d61fc4dc40eca6bdcea4697962724ccbde35"); + strbuf_release(&alphabet_100000); +} + +void test_hash__zero_blob_literal(void) +{ TEST_HASH_LITERAL("blob 0\0", "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"); +} + +void test_hash__three_blob_literal(void) +{ TEST_HASH_LITERAL("blob 3\0abc", "f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f", "c1cf6e465077930e88dc5136641d402f72a229ddd996f627d60e9639eaba35a6"); +} + +void test_hash__zero_tree_literal(void) +{ TEST_HASH_LITERAL("tree 0\0", "4b825dc642cb6eb9a060e54bf8d69288fbee4904", "6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321"); - - strbuf_release(&aaaaaaaaaa_100000); - strbuf_release(&alphabet_100000); - - return test_done(); } diff --git a/t/unit-tests/t-hashmap.c b/t/unit-tests/u-hashmap.c index 83b79dff39..eb80aa1348 100644 --- a/t/unit-tests/t-hashmap.c +++ b/t/unit-tests/u-hashmap.c @@ -1,4 +1,4 @@ -#include "test-lib.h" +#include "unit-test.h" #include "hashmap.h" #include "strbuf.h" @@ -83,23 +83,23 @@ static void t_replace(struct hashmap *map, unsigned int ignore_case) struct test_entry *entry; entry = alloc_test_entry("key1", "value1", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); entry = alloc_test_entry(ignore_case ? "Key1" : "key1", "value2", ignore_case); entry = hashmap_put_entry(map, entry, ent); - if (check(entry != NULL)) - check_str(get_value(entry), "value1"); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), "value1"); free(entry); entry = alloc_test_entry("fooBarFrotz", "value3", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); entry = alloc_test_entry(ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value4", ignore_case); entry = hashmap_put_entry(map, entry, ent); - if (check(entry != NULL)) - check_str(get_value(entry), "value3"); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), "value3"); free(entry); } @@ -122,20 +122,18 @@ static void t_get(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } for (size_t i = 0; i < ARRAY_SIZE(query); i++) { entry = get_test_entry(map, query[i][0], ignore_case); - if (check(entry != NULL)) - check_str(get_value(entry), query[i][1]); - else - test_msg("query key: %s", query[i][0]); + cl_assert(entry != NULL); + cl_assert_equal_s(get_value(entry), query[i][1]); } - check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); + cl_assert_equal_p(get_test_entry(map, "notInMap", ignore_case), NULL); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); } static void t_add(struct hashmap *map, unsigned int ignore_case) @@ -165,39 +163,19 @@ static void t_add(struct hashmap *map, unsigned int ignore_case) hashmap_for_each_entry_from(map, entry, ent) { - int ret; - if (!check_int((ret = key_val_contains( - key_val, seen, - ARRAY_SIZE(key_val), entry)), - ==, 0)) { - switch (ret) { - case 1: - test_msg("found entry was not given in the input\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - case 2: - test_msg("duplicate entry detected\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - } - } else { - count++; - } + int ret = key_val_contains(key_val, seen, + ARRAY_SIZE(key_val), entry); + cl_assert_equal_i(ret, 0); + count++; } - check_int(count, ==, 2); + cl_assert_equal_i(count, 2); } - for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { - if (!check_int(seen[i], ==, 1)) - test_msg("following key-val pair was not iterated over:\n" - " key: %s\n value: %s", - key_val[i][0], key_val[i][1]); - } + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) + cl_assert_equal_i(seen[i], 1); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); - check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); + cl_assert_equal_p(get_test_entry(map, "notInMap", ignore_case), NULL); } static void t_remove(struct hashmap *map, unsigned int ignore_case) @@ -211,24 +189,25 @@ static void t_remove(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } for (size_t i = 0; i < ARRAY_SIZE(remove); i++) { entry = alloc_test_entry(remove[i][0], "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, remove[i][0]); - if (check(removed != NULL)) - check_str(get_value(removed), remove[i][1]); + cl_assert(removed != NULL); + cl_assert_equal_s(get_value(removed), remove[i][1]); free(entry); free(removed); } entry = alloc_test_entry("notInMap", "", ignore_case); - check_pointer_eq(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL); + cl_assert_equal_p(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL); free(entry); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val) - ARRAY_SIZE(remove)); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), + ARRAY_SIZE(key_val) - ARRAY_SIZE(remove)); } static void t_iterate(struct hashmap *map, unsigned int ignore_case) @@ -242,38 +221,21 @@ static void t_iterate(struct hashmap *map, unsigned int ignore_case) for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); } hashmap_for_each_entry(map, &iter, entry, ent /* member name */) { - int ret; - if (!check_int((ret = key_val_contains(key_val, seen, - ARRAY_SIZE(key_val), - entry)), ==, 0)) { - switch (ret) { - case 1: - test_msg("found entry was not given in the input\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - case 2: - test_msg("duplicate entry detected\n" - " key: %s\n value: %s", - entry->key, get_value(entry)); - break; - } - } + int ret = key_val_contains(key_val, seen, + ARRAY_SIZE(key_val), + entry); + cl_assert(ret == 0); } - for (size_t i = 0; i < ARRAY_SIZE(seen); i++) { - if (!check_int(seen[i], ==, 1)) - test_msg("following key-val pair was not iterated over:\n" - " key: %s\n value: %s", - key_val[i][0], key_val[i][1]); - } + for (size_t i = 0; i < ARRAY_SIZE(seen); i++) + cl_assert_equal_i(seen[i], 1); - check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val)); + cl_assert_equal_i(hashmap_get_size(map), ARRAY_SIZE(key_val)); } static void t_alloc(struct hashmap *map, unsigned int ignore_case) @@ -284,17 +246,17 @@ static void t_alloc(struct hashmap *map, unsigned int ignore_case) char *key = xstrfmt("key%d", i); char *value = xstrfmt("value%d", i); entry = alloc_test_entry(key, value, ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); free(key); free(value); } - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, 51); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), 51); entry = alloc_test_entry("key52", "value52", ignore_case); - check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL); - check_int(map->tablesize, ==, 256); - check_int(hashmap_get_size(map), ==, 52); + cl_assert_equal_p(hashmap_put_entry(map, entry, ent), NULL); + cl_assert_equal_i(map->tablesize, 256); + cl_assert_equal_i(hashmap_get_size(map), 52); for (int i = 1; i <= 12; i++) { char *key = xstrfmt("key%d", i); @@ -302,27 +264,27 @@ static void t_alloc(struct hashmap *map, unsigned int ignore_case) entry = alloc_test_entry(key, "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, key); - if (check(removed != NULL)) - check_str(value, get_value(removed)); + cl_assert(removed != NULL); + cl_assert_equal_s(value, get_value(removed)); free(key); free(value); free(entry); free(removed); } - check_int(map->tablesize, ==, 256); - check_int(hashmap_get_size(map), ==, 40); + cl_assert_equal_i(map->tablesize, 256); + cl_assert_equal_i(hashmap_get_size(map), 40); entry = alloc_test_entry("key40", "", ignore_case); removed = hashmap_remove_entry(map, entry, ent, "key40"); - if (check(removed != NULL)) - check_str("value40", get_value(removed)); - check_int(map->tablesize, ==, 64); - check_int(hashmap_get_size(map), ==, 39); + cl_assert(removed != NULL); + cl_assert_equal_s("value40", get_value(removed)); + cl_assert_equal_i(map->tablesize, 64); + cl_assert_equal_i(hashmap_get_size(map), 39); free(entry); free(removed); } -static void t_intern(void) +void test_hashmap__intern(void) { const char *values[] = { "value1", "Value1", "value2", "value2" }; @@ -330,32 +292,68 @@ static void t_intern(void) const char *i1 = strintern(values[i]); const char *i2 = strintern(values[i]); - if (!check(!strcmp(i1, values[i]))) - test_msg("strintern(%s) returns %s\n", values[i], i1); - else if (!check(i1 != values[i])) - test_msg("strintern(%s) returns input pointer\n", - values[i]); - else if (!check_pointer_eq(i1, i2)) - test_msg("address('%s') != address('%s'), so strintern('%s') != strintern('%s')", - i1, i2, values[i], values[i]); - else - check_str(i1, values[i]); + cl_assert_equal_s(i1, values[i]); + cl_assert(i1 != values[i]); + cl_assert_equal_p(i1, i2); } } -int cmd_main(int argc UNUSED, const char **argv UNUSED) +void test_hashmap__replace_case_sensitive(void) +{ + setup(t_replace, 0); +} + +void test_hashmap__replace_case_insensitive(void) +{ + setup(t_replace, 1); +} + +void test_hashmap__get_case_sensitive(void) +{ + setup(t_get, 0); +} + +void test_hashmap__get_case_insensitive(void) +{ + setup(t_get, 1); +} + +void test_hashmap__add_case_sensitive(void) +{ + setup(t_add, 0); +} + +void test_hashmap__add_case_insensitive(void) +{ + setup(t_add, 1); +} + +void test_hashmap__remove_case_sensitive(void) +{ + setup(t_remove, 0); +} + +void test_hashmap__remove_case_insensitive(void) +{ + setup(t_remove, 1); +} + +void test_hashmap__iterate_case_sensitive(void) +{ + setup(t_iterate, 0); +} + +void test_hashmap__iterate_case_insensitive(void) +{ + setup(t_iterate, 1); +} + +void test_hashmap__alloc_case_sensitive(void) +{ + setup(t_alloc, 0); +} + +void test_hashmap__alloc_case_insensitive(void) { - TEST(setup(t_replace, 0), "replace works"); - TEST(setup(t_replace, 1), "replace (case insensitive) works"); - TEST(setup(t_get, 0), "get works"); - TEST(setup(t_get, 1), "get (case insensitive) works"); - TEST(setup(t_add, 0), "add works"); - TEST(setup(t_add, 1), "add (case insensitive) works"); - TEST(setup(t_remove, 0), "remove works"); - TEST(setup(t_remove, 1), "remove (case insensitive) works"); - TEST(setup(t_iterate, 0), "iterate works"); - TEST(setup(t_iterate, 1), "iterate (case insensitive) works"); - TEST(setup(t_alloc, 0), "grow / shrink works"); - TEST(t_intern(), "string interning works"); - return test_done(); + setup(t_alloc, 1); } diff --git a/t/unit-tests/u-mem-pool.c b/t/unit-tests/u-mem-pool.c new file mode 100644 index 0000000000..2bc2493b7e --- /dev/null +++ b/t/unit-tests/u-mem-pool.c @@ -0,0 +1,25 @@ +#include "unit-test.h" +#include "mem-pool.h" + +static void test_many_pool_allocations(size_t block_alloc) +{ + struct mem_pool pool = { .block_alloc = block_alloc }; + size_t size = 100; + char *buffer = mem_pool_calloc(&pool, 1, size); + for (size_t i = 0; i < size; i++) + cl_assert_equal_i(0, buffer[i]); + cl_assert(pool.mp_block != NULL); + cl_assert(pool.mp_block->next_free != NULL); + cl_assert(pool.mp_block->end != NULL); + mem_pool_discard(&pool, 0); +} + +void test_mem_pool__big_block(void) +{ + test_many_pool_allocations(1024 * 1024); +} + +void test_mem_pool__tiny_block(void) +{ + test_many_pool_allocations(1); +} diff --git a/t/unit-tests/u-oid-array.c b/t/unit-tests/u-oid-array.c new file mode 100644 index 0000000000..e48a433f21 --- /dev/null +++ b/t/unit-tests/u-oid-array.c @@ -0,0 +1,129 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "unit-test.h" +#include "lib-oid.h" +#include "oid-array.h" +#include "hex.h" + +static void fill_array(struct oid_array *array, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + + cl_parse_any_oid(hexes[i], &oid); + oid_array_append(array, &oid); + } + cl_assert_equal_i(array->nr, n); +} + +static int add_to_oid_array(const struct object_id *oid, void *data) +{ + struct oid_array *array = data; + + oid_array_append(array, oid); + return 0; +} + +static void t_enumeration(const char **input_args, size_t input_sz, + const char **expect_args, size_t expect_sz) +{ + struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT, + actual = OID_ARRAY_INIT; + size_t i; + + fill_array(&input, input_args, input_sz); + fill_array(&expect, expect_args, expect_sz); + + oid_array_for_each_unique(&input, add_to_oid_array, &actual); + cl_assert_equal_i(actual.nr, expect.nr); + + for (i = 0; i < actual.nr; i++) + cl_assert(oideq(&actual.oid[i], &expect.oid[i])); + + oid_array_clear(&actual); + oid_array_clear(&input); + oid_array_clear(&expect); +} + +#define TEST_ENUMERATION(input, expect) \ + t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)); + +static void t_lookup(const char **input_hexes, size_t n, const char *query_hex, + int lower_bound, int upper_bound) +{ + struct oid_array array = OID_ARRAY_INIT; + struct object_id oid_query; + int ret; + + cl_parse_any_oid(query_hex, &oid_query); + fill_array(&array, input_hexes, n); + ret = oid_array_lookup(&array, &oid_query); + + cl_assert(ret <= upper_bound); + cl_assert(ret >= lower_bound); + + oid_array_clear(&array); +} + +#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound) \ + t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \ + lower_bound, upper_bound); + +void test_oid_array__initialize(void) +{ + /* The hash algo is used by oid_array_lookup() internally */ + int algo = cl_setup_hash_algo(); + repo_set_hash_algo(the_repository, algo); +} + +static const char *arr_input[] = { "88", "44", "aa", "55" }; +static const char *arr_input_dup[] = { "88", "44", "aa", "55", + "88", "44", "aa", "55", + "88", "44", "aa", "55" }; +static const char *res_sorted[] = { "44", "55", "88", "aa" }; + +void test_oid_array__enumerate_unique(void) +{ + TEST_ENUMERATION(arr_input, res_sorted); +} + +void test_oid_array__enumerate_duplicate(void) +{ + TEST_ENUMERATION(arr_input_dup, res_sorted); +} + +void test_oid_array__lookup(void) +{ + TEST_LOOKUP(arr_input, "55", 1, 1); +} + +void test_oid_array__lookup_non_existent(void) +{ + TEST_LOOKUP(arr_input, "33", INT_MIN, -1); +} + +void test_oid_array__lookup_duplicates(void) +{ + TEST_LOOKUP(arr_input_dup, "55", 3, 5); +} + +void test_oid_array__lookup_non_existent_dup(void) +{ + TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1); +} + +void test_oid_array__lookup_almost_dup(void) +{ + const char *nearly_55; + + nearly_55 = cl_setup_hash_algo() == GIT_HASH_SHA1 ? + "5500000000000000000000000000000000000001" : + "5500000000000000000000000000000000000000000000000000000000000001"; + + TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0); +} + +void test_oid_array__lookup_single_dup(void) +{ + TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1); +} diff --git a/t/unit-tests/u-oidmap.c b/t/unit-tests/u-oidmap.c new file mode 100644 index 0000000000..b23af449f6 --- /dev/null +++ b/t/unit-tests/u-oidmap.c @@ -0,0 +1,136 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidmap.h" +#include "hash.h" +#include "hex.h" + +/* + * Elements we will put in oidmap structs are made of a key: the entry.oid + * field, which is of type struct object_id, and a value: the name field (could + * be a refname for example). + */ +struct test_entry { + struct oidmap_entry entry; + char name[FLEX_ARRAY]; +}; + +static const char *const key_val[][2] = { { "11", "one" }, + { "22", "two" }, + { "33", "three" } }; + +static struct oidmap map; + +void test_oidmap__initialize(void) +{ + oidmap_init(&map, 0); + + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){ + struct test_entry *entry; + + FLEX_ALLOC_STR(entry, name, key_val[i][1]); + cl_parse_any_oid(key_val[i][0], &entry->entry.oid); + cl_assert(oidmap_put(&map, entry) == NULL); + } +} + +void test_oidmap__cleanup(void) +{ + oidmap_clear(&map, 1); +} + +void test_oidmap__replace(void) +{ + struct test_entry *entry, *prev; + + FLEX_ALLOC_STR(entry, name, "un"); + cl_parse_any_oid("11", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "one"); + free(prev); + + FLEX_ALLOC_STR(entry, name, "deux"); + cl_parse_any_oid("22", &entry->entry.oid); + prev = oidmap_put(&map, entry); + cl_assert(prev != NULL); + cl_assert_equal_s(prev->name, "two"); + free(prev); +} + +void test_oidmap__get(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("22", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_get(&map, &oid) == NULL); + + cl_parse_any_oid("11", &oid); + entry = oidmap_get(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); +} + +void test_oidmap__remove(void) +{ + struct test_entry *entry; + struct object_id oid; + + cl_parse_any_oid("11", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "one"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("22", &oid); + entry = oidmap_remove(&map, &oid); + cl_assert(entry != NULL); + cl_assert_equal_s(entry->name, "two"); + cl_assert(oidmap_get(&map, &oid) == NULL); + free(entry); + + cl_parse_any_oid("44", &oid); + cl_assert(oidmap_remove(&map, &oid) == NULL); +} + +static int key_val_contains(struct test_entry *entry, char seen[]) +{ + for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) { + struct object_id oid; + + cl_parse_any_oid(key_val[i][0], &oid); + + if (oideq(&entry->entry.oid, &oid)) { + if (seen[i]) + return 2; + seen[i] = 1; + return 0; + } + } + return 1; +} + +void test_oidmap__iterate(void) +{ + struct oidmap_iter iter; + struct test_entry *entry; + char seen[ARRAY_SIZE(key_val)] = { 0 }; + int count = 0; + + oidmap_iter_init(&map, &iter); + while ((entry = oidmap_iter_next(&iter))) { + if (key_val_contains(entry, seen) != 0) { + cl_failf("Unexpected entry: name = %s, oid = %s", + entry->name, oid_to_hex(&entry->entry.oid)); + } + count++; + } + cl_assert_equal_i(count, ARRAY_SIZE(key_val)); + cl_assert_equal_i(hashmap_get_size(&map.map), ARRAY_SIZE(key_val)); +} diff --git a/t/unit-tests/u-oidtree.c b/t/unit-tests/u-oidtree.c new file mode 100644 index 0000000000..e6eede2740 --- /dev/null +++ b/t/unit-tests/u-oidtree.c @@ -0,0 +1,107 @@ +#include "unit-test.h" +#include "lib-oid.h" +#include "oidtree.h" +#include "hash.h" +#include "hex.h" +#include "strvec.h" + +static struct oidtree ot; + +#define FILL_TREE(tree, ...) \ + do { \ + const char *hexes[] = { __VA_ARGS__ }; \ + if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ + return; \ + } while (0) + +static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + cl_parse_any_oid(hexes[i], &oid); + oidtree_insert(ot, &oid); + } + return 0; +} + +static void check_contains(struct oidtree *ot, const char *hex, int expected) +{ + struct object_id oid; + + cl_parse_any_oid(hex, &oid); + cl_assert_equal_i(oidtree_contains(ot, &oid), expected); +} + +struct expected_hex_iter { + size_t i; + struct strvec expected_hexes; + const char *query; +}; + +static enum cb_next check_each_cb(const struct object_id *oid, void *data) +{ + struct expected_hex_iter *hex_iter = data; + struct object_id expected; + + cl_assert(hex_iter->i < hex_iter->expected_hexes.nr); + + cl_parse_any_oid(hex_iter->expected_hexes.v[hex_iter->i], + &expected); + cl_assert_equal_s(oid_to_hex(oid), oid_to_hex(&expected)); + hex_iter->i += 1; + return CB_CONTINUE; +} + +LAST_ARG_MUST_BE_NULL +static void check_each(struct oidtree *ot, const char *query, ...) +{ + struct object_id oid; + struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, + .query = query }; + const char *arg; + va_list hex_args; + + va_start(hex_args, query); + while ((arg = va_arg(hex_args, const char *))) + strvec_push(&hex_iter.expected_hexes, arg); + va_end(hex_args); + + cl_parse_any_oid(query, &oid); + oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); + + if (hex_iter.i != hex_iter.expected_hexes.nr) + cl_failf("error: could not find some 'object_id's for query ('%s')", query); + + strvec_clear(&hex_iter.expected_hexes); +} + +void test_oidtree__initialize(void) +{ + oidtree_init(&ot); +} + +void test_oidtree__cleanup(void) +{ + oidtree_clear(&ot); +} + +void test_oidtree__contains(void) +{ + FILL_TREE(&ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); + check_contains(&ot, "44", 0); + check_contains(&ot, "441", 0); + check_contains(&ot, "440", 0); + check_contains(&ot, "444", 1); + check_contains(&ot, "4440", 1); + check_contains(&ot, "4444", 0); +} + +void test_oidtree__each(void) +{ + FILL_TREE(&ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); + check_each(&ot, "12300", "123", NULL); + check_each(&ot, "3211", NULL); /* should not reach callback */ + check_each(&ot, "3210", "321", NULL); + check_each(&ot, "32100", "321", NULL); + check_each(&ot, "32", "320", "321", NULL); +} diff --git a/t/unit-tests/u-prio-queue.c b/t/unit-tests/u-prio-queue.c new file mode 100644 index 0000000000..63e58114ae --- /dev/null +++ b/t/unit-tests/u-prio-queue.c @@ -0,0 +1,117 @@ +#include "unit-test.h" +#include "prio-queue.h" + +static int intcmp(const void *va, const void *vb, void *data UNUSED) +{ + const int *a = va, *b = vb; + return *a - *b; +} + + +#define MISSING -1 +#define DUMP -2 +#define STACK -3 +#define GET -4 +#define REVERSE -5 +#define REPLACE -6 + +static int show(int *v) +{ + return v ? *v : MISSING; +} + +static void test_prio_queue(int *input, size_t input_size, + int *result, size_t result_size) +{ + struct prio_queue pq = { intcmp }; + size_t j = 0; + + for (size_t i = 0; i < input_size; i++) { + void *peek, *get; + switch(input[i]) { + case GET: + peek = prio_queue_peek(&pq); + get = prio_queue_get(&pq); + cl_assert(peek == get); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(get)); + j++; + break; + case DUMP: + while ((peek = prio_queue_peek(&pq))) { + get = prio_queue_get(&pq); + cl_assert(peek == get); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(get)); + j++; + } + break; + case STACK: + pq.compare = NULL; + break; + case REVERSE: + prio_queue_reverse(&pq); + break; + case REPLACE: + peek = prio_queue_peek(&pq); + cl_assert(i + 1 < input_size); + cl_assert(input[i + 1] >= 0); + cl_assert(j < result_size); + cl_assert_equal_i(result[j], show(peek)); + j++; + prio_queue_replace(&pq, &input[++i]); + break; + default: + prio_queue_put(&pq, &input[i]); + break; + } + } + cl_assert_equal_i(j, result_size); + clear_prio_queue(&pq); +} + +#define TEST_INPUT(input, result) \ + test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) + +void test_prio_queue__basic(void) +{ + TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }), + ((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 })); +} + +void test_prio_queue__mixed(void) +{ + TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }), + ((int []){ 2, 3, 4, 1, 5, 6 })); +} + +void test_prio_queue__empty(void) +{ + TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }), + ((int []){ 1, 2, MISSING, 1, 2, MISSING })); +} + +void test_prio_queue__replace(void) +{ + TEST_INPUT(((int []){ REPLACE, 6, 2, 4, REPLACE, 5, 7, GET, + REPLACE, 1, DUMP }), + ((int []){ MISSING, 2, 4, 5, 1, 6, 7 })); +} + +void test_prio_queue__stack(void) +{ + TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), + ((int []){ 3, 2, 6, 4, 5, 1, 8 })); +} + +void test_prio_queue__reverse_stack(void) +{ + TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), + ((int []){ 1, 2, 3, 4, 5, 6 })); +} + +void test_prio_queue__replace_stack(void) +{ + TEST_INPUT(((int []){ STACK, 8, 1, 5, REPLACE, 4, 6, 2, 3, DUMP }), + ((int []){ 5, 3, 2, 6, 4, 1, 8 })); +} diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c new file mode 100644 index 0000000000..a0471083e7 --- /dev/null +++ b/t/unit-tests/u-reftable-basics.c @@ -0,0 +1,227 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "unit-test.h" +#include "lib-reftable.h" +#include "reftable/basics.h" + +struct integer_needle_lesseq_args { + int needle; + int *haystack; +}; + +static int integer_needle_lesseq(size_t i, void *_args) +{ + struct integer_needle_lesseq_args *args = _args; + return args->needle <= args->haystack[i]; +} + +static void *realloc_stub(void *p UNUSED, size_t size UNUSED) +{ + return NULL; +} + +void test_reftable_basics__binsearch(void) +{ + int haystack[] = { 2, 4, 6, 8, 10 }; + struct { + int needle; + size_t expected_idx; + } testcases[] = { + {-9000, 0}, + {-1, 0}, + {0, 0}, + {2, 0}, + {3, 1}, + {4, 1}, + {7, 3}, + {9, 4}, + {10, 4}, + {11, 5}, + {9000, 5}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) { + struct integer_needle_lesseq_args args = { + .haystack = haystack, + .needle = testcases[i].needle, + }; + size_t idx; + + idx = binsearch(ARRAY_SIZE(haystack), + &integer_needle_lesseq, &args); + cl_assert_equal_i(idx, testcases[i].expected_idx); + } +} + +void test_reftable_basics__names_length(void) +{ + const char *a[] = { "a", "b", NULL }; + cl_assert_equal_i(names_length(a), 2); +} + +void test_reftable_basics__names_equal(void) +{ + const char *a[] = { "a", "b", "c", NULL }; + const char *b[] = { "a", "b", "d", NULL }; + const char *c[] = { "a", "b", NULL }; + + cl_assert(names_equal(a, a)); + cl_assert(!names_equal(a, b)); + cl_assert(!names_equal(a, c)); +} + +void test_reftable_basics__parse_names(void) +{ + char in1[] = "line\n"; + char in2[] = "a\nb\nc"; + char **out = parse_names(in1, strlen(in1)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "line"); + cl_assert(!out[1]); + free_names(out); + + out = parse_names(in2, strlen(in2)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "a"); + cl_assert_equal_s(out[1], "b"); + cl_assert_equal_s(out[2], "c"); + cl_assert(!out[3]); + free_names(out); +} + +void test_reftable_basics__parse_names_drop_empty_string(void) +{ + char in[] = "a\n\nb\n"; + char **out = parse_names(in, strlen(in)); + cl_assert(out != NULL); + cl_assert_equal_s(out[0], "a"); + /* simply '\n' should be dropped as empty string */ + cl_assert_equal_s(out[1], "b"); + cl_assert(out[2] == NULL); + free_names(out); +} + +void test_reftable_basics__common_prefix_size(void) +{ + struct reftable_buf a = REFTABLE_BUF_INIT; + struct reftable_buf b = REFTABLE_BUF_INIT; + struct { + const char *a, *b; + int want; + } cases[] = { + {"abcdef", "abc", 3}, + { "abc", "ab", 2 }, + { "", "abc", 0 }, + { "abc", "abd", 2 }, + { "abc", "pqr", 0 }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + cl_assert_equal_i(reftable_buf_addstr(&a, cases[i].a), 0); + cl_assert_equal_i(reftable_buf_addstr(&b, cases[i].b), 0); + cl_assert_equal_i(common_prefix_size(&a, &b), cases[i].want); + reftable_buf_reset(&a); + reftable_buf_reset(&b); + } + reftable_buf_release(&a); + reftable_buf_release(&b); +} + +void test_reftable_basics__put_get_be64(void) +{ + uint64_t in = 0x1122334455667788; + uint8_t dest[8]; + uint64_t out; + reftable_put_be64(dest, in); + out = reftable_get_be64(dest); + cl_assert(in == out); +} + +void test_reftable_basics__put_get_be32(void) +{ + uint32_t in = 0x11223344; + uint8_t dest[4]; + uint32_t out; + reftable_put_be32(dest, in); + out = reftable_get_be32(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__put_get_be24(void) +{ + uint32_t in = 0x112233; + uint8_t dest[3]; + uint32_t out; + reftable_put_be24(dest, in); + out = reftable_get_be24(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__put_get_be16(void) +{ + uint32_t in = 0xfef1; + uint8_t dest[3]; + uint32_t out; + reftable_put_be16(dest, in); + out = reftable_get_be16(dest); + cl_assert_equal_i(in, out); +} + +void test_reftable_basics__alloc_grow(void) +{ + int *arr = NULL, *old_arr; + size_t alloc = 0, old_alloc; + + cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, 1, alloc), 0); + cl_assert(arr != NULL); + cl_assert(alloc >= 1); + arr[0] = 42; + + old_alloc = alloc; + old_arr = arr; + reftable_set_alloc(NULL, realloc_stub, NULL); + cl_assert(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); + cl_assert(arr == old_arr); + cl_assert_equal_i(alloc, old_alloc); + + old_alloc = alloc; + reftable_set_alloc(NULL, NULL, NULL); + cl_assert_equal_i(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc), 0); + cl_assert(arr != NULL); + cl_assert(alloc > old_alloc); + arr[alloc - 1] = 42; + + reftable_free(arr); +} + +void test_reftable_basics__alloc_grow_or_null(void) +{ + int *arr = NULL; + size_t alloc = 0, old_alloc; + + REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc); + cl_assert(arr != NULL); + cl_assert(alloc >= 1); + arr[0] = 42; + + old_alloc = alloc; + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + cl_assert(arr != NULL); + cl_assert(alloc > old_alloc); + arr[alloc - 1] = 42; + + old_alloc = alloc; + reftable_set_alloc(NULL, realloc_stub, NULL); + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + cl_assert(arr == NULL); + cl_assert_equal_i(alloc, 0); + reftable_set_alloc(NULL, NULL, NULL); + + reftable_free(arr); +} diff --git a/t/unit-tests/u-reftable-block.c b/t/unit-tests/u-reftable-block.c new file mode 100644 index 0000000000..f4bded7d26 --- /dev/null +++ b/t/unit-tests/u-reftable-block.c @@ -0,0 +1,458 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "unit-test.h" +#include "lib-reftable.h" +#include "reftable/block.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/reftable-error.h" +#include "strbuf.h" + +void test_reftable_block__read_write(void) +{ + const int header_off = 21; /* random */ + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block_source source = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = REFTABLE_BLOCK_TYPE_REF, + }; + size_t i = 0; + int ret; + struct reftable_block block = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + cl_assert(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, + (uint8_t *) block_data.buf, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + cl_assert(!ret); + + rec.u.ref.refname = (char *) ""; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + ret = block_writer_add(&bw, &rec); + cl_assert_equal_i(ret, REFTABLE_API_ERROR); + + for (i = 0; i < N; i++) { + rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); + rec.u.ref.value_type = REFTABLE_REF_VAL1; + memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.ref.refname = NULL; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + cl_assert_equal_i(ret, 0); + } + + ret = block_writer_finish(&bw); + cl_assert(ret > 0); + + block_writer_release(&bw); + + block_source_from_buf(&source ,&block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); + + block_iter_init(&it, &block); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + cl_assert(ret >= 0); + if (ret > 0) { + cl_assert_equal_i(i, N); + break; + } + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + for (i = 0; i < N; i++) { + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + + want.len--; + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + reftable_block_release(&block); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_buf_release(&want); + reftable_buf_release(&block_data); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +void test_reftable_block__log_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 2048; + struct reftable_block_source source = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = REFTABLE_BLOCK_TYPE_LOG, + }; + size_t i = 0; + int ret; + struct reftable_block block = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + cl_assert(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + cl_assert(!ret); + + for (i = 0; i < N; i++) { + rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); + rec.u.log.update_index = i; + rec.u.log.value_type = REFTABLE_LOG_UPDATE; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.log.refname = NULL; + rec.u.log.value_type = REFTABLE_LOG_DELETION; + cl_assert_equal_i(ret, 0); + } + + ret = block_writer_finish(&bw); + cl_assert(ret > 0); + + block_writer_release(&bw); + + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_LOG); + + block_iter_init(&it, &block); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + cl_assert(ret >= 0); + if (ret > 0) { + cl_assert_equal_i(i, N); + break; + } + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + for (i = 0; i < N; i++) { + reftable_buf_reset(&want); + cl_assert(reftable_buf_addstr(&want, recs[i].u.log.refname) == 0); + + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + + want.len--; + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + reftable_block_release(&block); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_buf_release(&want); + reftable_buf_release(&block_data); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +void test_reftable_block__obj_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block_source source = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = REFTABLE_BLOCK_TYPE_OBJ, + }; + size_t i = 0; + int ret; + struct reftable_block block = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + cl_assert(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + cl_assert(!ret); + + for (i = 0; i < N; i++) { + uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; + DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes)); + + rec.u.obj.hash_prefix = allocated; + rec.u.obj.hash_prefix_len = 5; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.obj.hash_prefix = NULL; + rec.u.obj.hash_prefix_len = 0; + cl_assert_equal_i(ret, 0); + } + + ret = block_writer_finish(&bw); + cl_assert(ret > 0); + + block_writer_release(&bw); + + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_OBJ); + + block_iter_init(&it, &block); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + cl_assert(ret >= 0); + if (ret > 0) { + cl_assert_equal_i(i, N); + break; + } + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + for (i = 0; i < N; i++) { + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + reftable_block_release(&block); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_buf_release(&want); + reftable_buf_release(&block_data); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +void test_reftable_block__ref_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block_source source = { 0 }; + struct block_writer bw = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record rec = { + .type = REFTABLE_BLOCK_TYPE_INDEX, + .u.idx.last_key = REFTABLE_BUF_INIT, + }; + size_t i = 0; + int ret; + struct reftable_block block = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + cl_assert(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, + header_off, hash_size(REFTABLE_HASH_SHA1)); + cl_assert(!ret); + + for (i = 0; i < N; i++) { + char buf[128]; + + snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); + + reftable_buf_init(&recs[i].u.idx.last_key); + recs[i].type = REFTABLE_BLOCK_TYPE_INDEX; + cl_assert(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); + recs[i].u.idx.offset = i; + + ret = block_writer_add(&bw, &recs[i]); + cl_assert_equal_i(ret, 0); + } + + ret = block_writer_finish(&bw); + cl_assert(ret > 0); + + block_writer_release(&bw); + + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_INDEX); + + block_iter_init(&it, &block); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + cl_assert(ret >= 0); + if (ret > 0) { + cl_assert_equal_i(i, N); + break; + } + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + for (i = 0; i < N; i++) { + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + + cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + + want.len--; + ret = block_iter_seek_key(&it, &want); + cl_assert_equal_i(ret, 0); + + ret = block_iter_next(&it, &rec); + cl_assert_equal_i(ret, 0); + cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); + } + + reftable_block_release(&block); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_buf_release(&want); + reftable_buf_release(&block_data); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +void test_reftable_block__iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct block_writer writer = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record expected_refs[20]; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_block block = { 0 }; + struct reftable_buf data; + int err; + + data.len = 1024; + REFTABLE_CALLOC_ARRAY(data.buf, data.len); + cl_assert(data.buf != NULL); + + err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, + (uint8_t *) data.buf, data.len, + 0, hash_size(REFTABLE_HASH_SHA1)); + cl_assert(!err); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) { + expected_refs[i] = (struct reftable_record) { + .type = REFTABLE_BLOCK_TYPE_REF, + .u.ref = { + .value_type = REFTABLE_REF_VAL1, + .refname = xstrfmt("refs/heads/branch-%02"PRIuMAX, (uintmax_t)i), + }, + }; + memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); + + err = block_writer_add(&writer, &expected_refs[i]); + cl_assert_equal_i(err, 0); + } + + err = block_writer_finish(&writer); + cl_assert(err > 0); + + block_source_from_buf(&source, &data); + reftable_block_init(&block, &source, 0, 0, data.len, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); + + err = reftable_block_init_iterator(&block, &it); + cl_assert_equal_i(err, 0); + + for (size_t i = 0; ; i++) { + err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) { + cl_assert_equal_i(i, ARRAY_SIZE(expected_refs)); + break; + } + cl_assert_equal_i(err, 0); + + cl_assert(reftable_ref_record_equal(&ref, + &expected_refs[i].u.ref, REFTABLE_HASH_SIZE_SHA1)); + } + + err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist"); + cl_assert_equal_i(err, 0); + err = reftable_iterator_next_ref(&it, &ref); + cl_assert_equal_i(err, 1); + + err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13"); + cl_assert_equal_i(err, 0); + err = reftable_iterator_next_ref(&it, &ref); + cl_assert_equal_i(err, 0); + cl_assert(reftable_ref_record_equal(&ref, + &expected_refs[13].u.ref,REFTABLE_HASH_SIZE_SHA1)); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) + reftable_free(expected_refs[i].u.ref.refname); + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_block_release(&block); + block_writer_release(&writer); + reftable_buf_release(&data); +} diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/u-reftable-merged.c index 60836f80d6..54cb7fc2a7 100644 --- a/t/unit-tests/t-reftable-merged.c +++ b/t/unit-tests/u-reftable-merged.c @@ -6,12 +6,12 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" #include "lib-reftable.h" #include "reftable/blocksource.h" #include "reftable/constants.h" #include "reftable/merged.h" -#include "reftable/reader.h" +#include "reftable/table.h" #include "reftable/reftable-error.h" #include "reftable/reftable-merged.h" #include "reftable/reftable-writer.h" @@ -19,7 +19,7 @@ https://developers.google.com/open-source/licenses/bsd static struct reftable_merged_table * merged_table_from_records(struct reftable_ref_record **refs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -28,33 +28,33 @@ merged_table_from_records(struct reftable_ref_record **refs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + cl_assert(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); - check(*source != NULL); + cl_assert(*source != NULL); for (size_t i = 0; i < n; i++) { - t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); + cl_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); - check(!err); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); + cl_assert(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); - check(!err); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); + cl_assert(!err); return mt; } -static void readers_destroy(struct reftable_reader **readers, const size_t n) +static void tables_destroy(struct reftable_table **tables, const size_t n) { for (size_t i = 0; i < n; i++) - reftable_reader_decref(readers[i]); - reftable_free(readers); + reftable_table_decref(tables[i]); + reftable_free(tables); } -static void t_merged_single_record(void) +void test_reftable_merged__single_record(void) { struct reftable_ref_record r1[] = { { .refname = (char *) "b", @@ -77,31 +77,32 @@ static void t_merged_single_record(void) size_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_ref_record ref = { 0 }; struct reftable_iterator it = { 0 }; int err; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); - check(!err); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "a"); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); - check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&r2[0], &ref, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); reftable_free(bs); } -static void t_merged_refs(void) +void test_reftable_merged__refs(void) { struct reftable_ref_record r1[] = { { @@ -154,9 +155,9 @@ static void t_merged_refs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; int err; struct reftable_ref_record *out = NULL; @@ -164,13 +165,13 @@ static void t_merged_refs(void) size_t cap = 0; size_t i; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); - check(!err); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "a"); - check(!err); - check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); - check_int(reftable_merged_table_min_update_index(mt), ==, 1); - check_int(reftable_merged_table_max_update_index(mt), ==, 3); + cl_assert(err == 0); + cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1); + cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1); + cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3); while (len < 100) { /* cap loops/recursion. */ struct reftable_ref_record ref = { 0 }; @@ -178,27 +179,27 @@ static void t_merged_refs(void) if (err > 0) break; - check(!REFTABLE_ALLOC_GROW(out, len + 1, cap)); + cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0); out[len++] = ref; } reftable_iterator_destroy(&it); - check_int(ARRAY_SIZE(want), ==, len); + cl_assert_equal_i(ARRAY_SIZE(want), len); for (i = 0; i < len; i++) - check(reftable_ref_record_equal(want[i], &out[i], - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_ref_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1) != 0); for (i = 0; i < len; i++) reftable_ref_record_release(&out[i]); reftable_free(out); for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } -static void t_merged_seek_multiple_times(void) +void test_reftable_merged__seek_multiple_times(void) { struct reftable_ref_record r1[] = { { @@ -238,42 +239,39 @@ static void t_merged_seek_multiple_times(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); for (size_t i = 0; i < 5; i++) { int err = reftable_iterator_seek_ref(&it, "c"); - check(!err); + cl_assert(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r1[1], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[1], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r2[1], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[1], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_next_ref(&it, &rec); - check(err > 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) > 0); } for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); reftable_free(sources); } -static void t_merged_seek_multiple_times_without_draining(void) +void test_reftable_merged__seek_multiple_times_no_drain(void) { struct reftable_ref_record r1[] = { { @@ -313,32 +311,27 @@ static void t_merged_seek_multiple_times_without_draining(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; - int err; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); - err = reftable_iterator_seek_ref(&it, "b"); - check(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r2[0], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_seek_ref(&it, "b") == 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r2[0], + REFTABLE_HASH_SIZE_SHA1), 1); - err = reftable_iterator_seek_ref(&it, "a"); - check(!err); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - err = reftable_ref_record_equal(&rec, &r1[0], REFTABLE_HASH_SIZE_SHA1); - check(err == 1); + cl_assert(reftable_iterator_seek_ref(&it, "a") == 0); + cl_assert(reftable_iterator_next_ref(&it, &rec) == 0); + cl_assert_equal_i(reftable_ref_record_equal(&rec, &r1[0], + REFTABLE_HASH_SIZE_SHA1), 1); for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); @@ -348,7 +341,7 @@ static void t_merged_seek_multiple_times_without_draining(void) static struct reftable_merged_table * merged_table_from_log_records(struct reftable_log_record **logs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -358,26 +351,26 @@ merged_table_from_log_records(struct reftable_log_record **logs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + cl_assert(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); - check(*source != NULL); + cl_assert(*source != NULL); for (size_t i = 0; i < n; i++) { - t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); + cl_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); - check(!err); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); + cl_assert(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); - check(!err); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); + cl_assert(!err); return mt; } -static void t_merged_logs(void) +void test_reftable_merged__logs(void) { struct reftable_log_record r1[] = { { @@ -435,23 +428,23 @@ static void t_merged_logs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = merged_table_from_log_records( - logs, &bs, &readers, sizes, bufs, 3); + logs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; - int err; struct reftable_log_record *out = NULL; size_t len = 0; size_t cap = 0; size_t i; + int err; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); - check(!err); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); + cl_assert(!err); err = reftable_iterator_seek_log(&it, "a"); - check(!err); - check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); - check_int(reftable_merged_table_min_update_index(mt), ==, 1); - check_int(reftable_merged_table_max_update_index(mt), ==, 3); + cl_assert(!err); + cl_assert_equal_i(reftable_merged_table_hash_id(mt), REFTABLE_HASH_SHA1); + cl_assert_equal_i(reftable_merged_table_min_update_index(mt), 1); + cl_assert_equal_i(reftable_merged_table_max_update_index(mt), 3); while (len < 100) { /* cap loops/recursion. */ struct reftable_log_record log = { 0 }; @@ -459,24 +452,24 @@ static void t_merged_logs(void) if (err > 0) break; - check(!REFTABLE_ALLOC_GROW(out, len + 1, cap)); + cl_assert(REFTABLE_ALLOC_GROW(out, len + 1, cap) == 0); out[len++] = log; } reftable_iterator_destroy(&it); - check_int(ARRAY_SIZE(want), ==, len); + cl_assert_equal_i(ARRAY_SIZE(want), len); for (i = 0; i < len; i++) - check(reftable_log_record_equal(want[i], &out[i], - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_log_record_equal(want[i], &out[i], + REFTABLE_HASH_SIZE_SHA1) != 0); - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); - check(!err); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); + cl_assert(!err); err = reftable_iterator_seek_log_at(&it, "a", 2); - check(!err); + cl_assert(!err); reftable_log_record_release(&out[0]); - err = reftable_iterator_next_log(&it, &out[0]); - check(!err); - check(reftable_log_record_equal(&out[0], &r3[0], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_iterator_next_log(&it, &out[0]) == 0); + cl_assert(reftable_log_record_equal(&out[0], &r3[0], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_iterator_destroy(&it); for (i = 0; i < len; i++) @@ -485,16 +478,16 @@ static void t_merged_logs(void) for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } -static void t_default_write_opts(void) +void test_reftable_merged__default_write_opts(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record rec = { .refname = (char *) "master", .update_index = 1, @@ -502,45 +495,30 @@ static void t_default_write_opts(void) int err; struct reftable_block_source source = { 0 }; uint32_t hash_id; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_merged_table *merged = NULL; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &rec); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &rec), 0); - err = reftable_writer_close(w); - check(!err); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); - check(!err); + err = reftable_table_new(&table, &source, "filename"); + cl_assert(!err); - hash_id = reftable_reader_hash_id(rd); - check_int(hash_id, ==, REFTABLE_HASH_SHA1); + hash_id = reftable_table_hash_id(table); + cl_assert_equal_i(hash_id, REFTABLE_HASH_SHA1); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA256); - check_int(err, ==, REFTABLE_FORMAT_ERROR); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA1); - check(!err); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA256); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA1); + cl_assert(!err); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_merged_table_free(merged); reftable_buf_release(&buf); } - - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_default_write_opts(), "merged table with default write opts"); - TEST(t_merged_logs(), "merged table with multiple log updates for same ref"); - TEST(t_merged_refs(), "merged table with multiple updates to same ref"); - TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times"); - TEST(t_merged_seek_multiple_times_without_draining(), "merged table can seek multiple times without draining"); - TEST(t_merged_single_record(), "ref occurring in only one record can be fetched"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/u-reftable-pq.c index f3f8a0cdf3..f8a28f6e07 100644 --- a/t/unit-tests/t-reftable-pq.c +++ b/t/unit-tests/u-reftable-pq.c @@ -6,7 +6,8 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" +#include "lib-reftable.h" #include "reftable/constants.h" #include "reftable/pq.h" #include "strbuf.h" @@ -15,16 +16,18 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) { for (size_t i = 1; i < pq->len; i++) { size_t parent = (i - 1) / 2; - check(pq_less(&pq->heap[parent], &pq->heap[i])); + cl_assert(pq_less(&pq->heap[parent], &pq->heap[i]) != 0); } } static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b) { - return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index); + int cmp; + cl_assert_equal_i(reftable_record_cmp(a->rec, b->rec, &cmp), 0); + return !cmp && (a->index == b->index); } -static void t_pq_record(void) +void test_reftable_pq__record(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[54]; @@ -32,7 +35,8 @@ static void t_pq_record(void) char *last = NULL; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i); } @@ -49,13 +53,15 @@ static void t_pq_record(void) while (!merged_iter_pqueue_is_empty(pq)) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + cl_assert(pq_entry_equal(&top, &e)); + cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); if (last) - check_int(strcmp(last, e.rec->u.ref.refname), <, 0); + cl_assert(strcmp(last, e.rec->u.ref.refname) < 0); last = e.rec->u.ref.refname; } @@ -64,7 +70,7 @@ static void t_pq_record(void) merged_iter_pqueue_release(&pq); } -static void t_pq_index(void) +void test_reftable_pq__index(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[13]; @@ -72,7 +78,8 @@ static void t_pq_index(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -90,28 +97,31 @@ static void t_pq_index(void) for (i = N - 1; i > 0; i--) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); - check_int(e.index, ==, i); + cl_assert(pq_entry_equal(&top, &e)); + cl_assert(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); + cl_assert_equal_i(e.index, i); if (last) - check_str(last, e.rec->u.ref.refname); + cl_assert_equal_s(last, e.rec->u.ref.refname); last = e.rec->u.ref.refname; } merged_iter_pqueue_release(&pq); } -static void t_merged_iter_pqueue_top(void) +void test_reftable_pq__merged_iter_pqueue_top(void) { struct merged_iter_pqueue pq = { 0 }; struct reftable_record recs[13]; size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + cl_assert(!reftable_record_init(&recs[i], + REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -129,25 +139,18 @@ static void t_merged_iter_pqueue_top(void) for (i = N - 1; i > 0; i--) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + cl_assert_equal_i(merged_iter_pqueue_remove(&pq, &e), 0); merged_iter_pqueue_check(&pq); - check(pq_entry_equal(&top, &e)); - check(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(pq_entry_equal(&top, &e) != 0); + cl_assert(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1) != 0); for (size_t j = 0; i < pq.len; j++) { - check(pq_less(&top, &pq.heap[j])); - check_int(top.index, >, j); + cl_assert(pq_less(&top, &pq.heap[j]) != 0); + cl_assert(top.index > j); } } merged_iter_pqueue_release(&pq); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_pq_record(), "pq works with record-based comparison"); - TEST(t_pq_index(), "pq works with index-based comparison"); - TEST(t_merged_iter_pqueue_top(), "merged_iter_pqueue_top works"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/u-reftable-readwrite.c index 6b75a419b9..4d8c4be5f1 100644 --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/u-reftable-readwrite.c @@ -8,37 +8,37 @@ https://developers.google.com/open-source/licenses/bsd #define DISABLE_SIGN_COMPARE_WARNINGS -#include "test-lib.h" +#include "unit-test.h" #include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/blocksource.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/reftable-writer.h" +#include "reftable/table.h" #include "strbuf.h" static const int update_index = 5; -static void t_buffer(void) +void test_reftable_readwrite__buffer(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_block out = { 0 }; + struct reftable_block_data out = { 0 }; int n; uint8_t in[] = "hello"; - check(!reftable_buf_add(&buf, in, sizeof(in))); + cl_assert_equal_i(reftable_buf_add(&buf, in, sizeof(in)), 0); block_source_from_buf(&source, &buf); - check_int(block_source_size(&source), ==, 6); - n = block_source_read_block(&source, &out, 0, sizeof(in)); - check_int(n, ==, sizeof(in)); - check(!memcmp(in, out.data, n)); - reftable_block_done(&out); + cl_assert_equal_i(block_source_size(&source), 6); + n = block_source_read_data(&source, &out, 0, sizeof(in)); + cl_assert_equal_i(n, sizeof(in)); + cl_assert(!memcmp(in, out.data, n)); + block_source_release_data(&out); - n = block_source_read_block(&source, &out, 1, 2); - check_int(n, ==, 2); - check(!memcmp(out.data, "el", 2)); + n = block_source_read_data(&source, &out, 1, 2); + cl_assert_equal_i(n, 2); + cl_assert(!memcmp(out.data, "el", 2)); - reftable_block_done(&out); + block_source_release_data(&out); block_source_close(&source); reftable_buf_release(&buf); } @@ -55,41 +55,41 @@ static void write_table(char ***names, struct reftable_buf *buf, int N, int i; REFTABLE_CALLOC_ARRAY(*names, N + 1); - check(*names != NULL); + cl_assert(*names != NULL); REFTABLE_CALLOC_ARRAY(refs, N); - check(refs != NULL); + cl_assert(refs != NULL); REFTABLE_CALLOC_ARRAY(logs, N); - check(logs != NULL); + cl_assert(logs != NULL); for (i = 0; i < N; i++) { refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i); refs[i].update_index = update_index; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); } for (i = 0; i < N; i++) { logs[i].refname = (*names)[i]; logs[i].update_index = update_index; logs[i].value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); logs[i].value.update.message = (char *) "message"; } - t_reftable_write_to_buf(buf, refs, N, logs, N, &opts); + cl_reftable_write_to_buf(buf, refs, N, logs, N, &opts); reftable_free(refs); reftable_free(logs); } -static void t_log_buffer_size(void) +void test_reftable_readwrite__log_buffer_size(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_write_options opts = { .block_size = 4096, }; - int err; int i; struct reftable_log_record log = { .refname = (char *) "refs/heads/master", @@ -102,32 +102,30 @@ static void t_log_buffer_size(void) .time = 0x5e430672, .message = (char *) "commit: 9\n", } } }; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); /* This tests buffer extension for log compression. Must use a random hash, to ensure that the compressed part is larger than the original. */ for (i = 0; i < REFTABLE_HASH_SIZE_SHA1; i++) { - log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); - log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); + log.value.update.old_hash[i] = (uint8_t)(git_rand(0) % 256); + log.value.update.new_hash[i] = (uint8_t)(git_rand(0) % 256); } reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - check(!err); - err = reftable_writer_close(w); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_overflow(void) +void test_reftable_readwrite__log_overflow(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; char msg[256] = { 0 }; struct reftable_write_options opts = { .block_size = ARRAY_SIZE(msg), }; - int err; struct reftable_log_record log = { .refname = (char *) "refs/heads/master", .update_index = update_index, @@ -144,21 +142,22 @@ static void t_log_overflow(void) }, }, }; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); memset(msg, 'x', sizeof(msg) - 1); reftable_writer_set_limits(w, update_index, update_index); - err = reftable_writer_add_log(w, &log); - check_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR); + cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_ENTRY_TOO_BIG_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_write_limits(void) +void test_reftable_readwrite__log_write_limits(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); struct reftable_log_record log = { .refname = (char *)"refs/head/master", .update_index = 0, @@ -174,29 +173,25 @@ static void t_log_write_limits(void) }, }, }; - int err; reftable_writer_set_limits(w, 1, 1); /* write with update_index (0) below set limits (1, 1) */ - err = reftable_writer_add_log(w, &log); - check_int(err, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); /* write with update_index (1) in the set limits (1, 1) */ log.update_index = 1; - err = reftable_writer_add_log(w, &log); - check_int(err, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); /* write with update_index (3) above set limits (1, 1) */ log.update_index = 3; - err = reftable_writer_add_log(w, &log); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_log(w, &log), REFTABLE_API_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_log_write_read(void) +void test_reftable_readwrite__log_write_read(void) { struct reftable_write_options opts = { .block_size = 256, @@ -204,16 +199,17 @@ static void t_log_write_read(void) struct reftable_ref_record ref = { 0 }; struct reftable_log_record log = { 0 }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); const struct reftable_stats *stats = NULL; - int N = 2, err, i, n; + int N = 2, i; char **names; + int err; names = reftable_calloc(N + 1, sizeof(*names)); - check(names != NULL); + cl_assert(names != NULL); reftable_writer_set_limits(w, 0, N); @@ -225,8 +221,7 @@ static void t_log_write_read(void) ref.refname = name; ref.update_index = i; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); } for (i = 0; i < N; i++) { @@ -235,81 +230,80 @@ static void t_log_write_read(void) log.refname = names[i]; log.update_index = i; log.value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(log.value.update.old_hash, i, - REFTABLE_HASH_SHA1); - t_reftable_set_hash(log.value.update.new_hash, i + 1, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(log.value.update.old_hash, i, + REFTABLE_HASH_SHA1); + cl_reftable_set_hash(log.value.update.new_hash, i + 1, + REFTABLE_HASH_SHA1); - err = reftable_writer_add_log(w, &log); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); } - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_close(w), 0); stats = reftable_writer_stats(w); - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(w); w = NULL; block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); - check(!err); + err = reftable_table_new(&table, &source, "file.log"); + cl_assert(!err); - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[N - 1]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); + cl_assert(!err); /* end of iteration. */ - err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >, 0); + cl_assert(reftable_iterator_next_ref(&it, &ref) > 0); reftable_iterator_destroy(&it); reftable_ref_record_release(&ref); - err = reftable_reader_init_log_iterator(reader, &it); - check(!err); + err = reftable_table_init_log_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_log(&it, ""); - check(!err); + cl_assert(!err); for (i = 0; ; i++) { int err = reftable_iterator_next_log(&it, &log); if (err > 0) break; - check(!err); - check_str(names[i], log.refname); - check_int(i, ==, log.update_index); + cl_assert(!err); + cl_assert_equal_s(names[i], log.refname); + cl_assert_equal_i(i, log.update_index); reftable_log_record_release(&log); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_iterator_destroy(&it); /* cleanup. */ reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } -static void t_log_zlib_corruption(void) +void test_reftable_readwrite__log_zlib_corruption(void) { struct reftable_write_options opts = { .block_size = 256, }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); const struct reftable_stats *stats = NULL; char message[100] = { 0 }; - int err, i, n; + int i; + int err; struct reftable_log_record log = { .refname = (char *) "refname", .value_type = REFTABLE_LOG_UPDATE, @@ -325,18 +319,15 @@ static void t_log_zlib_corruption(void) }; for (i = 0; i < sizeof(message) - 1; i++) - message[i] = (uint8_t)(git_rand() % 64 + ' '); + message[i] = (uint8_t)(git_rand(0) % 64 + ' '); reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_log(w, &log); - check(!err); - - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_add_log(w, &log), 0); + cl_assert_equal_i(reftable_writer_close(w), 0); stats = reftable_writer_stats(w); - check_int(stats->log_stats.blocks, >, 0); + cl_assert(stats->log_stats.blocks > 0); reftable_writer_free(w); w = NULL; @@ -345,29 +336,29 @@ static void t_log_zlib_corruption(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); - check(!err); + err = reftable_table_new(&table, &source, "file.log"); + cl_assert(!err); - err = reftable_reader_init_log_iterator(reader, &it); - check(!err); + err = reftable_table_init_log_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_log(&it, "refname"); - check_int(err, ==, REFTABLE_ZLIB_ERROR); + cl_assert_equal_i(err, REFTABLE_ZLIB_ERROR); reftable_iterator_destroy(&it); /* cleanup. */ - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } -static void t_table_read_write_sequential(void) +void test_reftable_readwrite__table_read_write_sequential(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; struct reftable_iterator it = { 0 }; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err = 0; int j = 0; @@ -375,73 +366,73 @@ static void t_table_read_write_sequential(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); - check(!err); + err = reftable_table_new(&table, &source, "file.ref"); + cl_assert(!err); - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); for (j = 0; ; j++) { struct reftable_ref_record ref = { 0 }; int r = reftable_iterator_next_ref(&it, &ref); - check_int(r, >=, 0); + cl_assert(r >= 0); if (r > 0) break; - check_str(names[j], ref.refname); - check_int(update_index, ==, ref.update_index); + cl_assert_equal_s(names[j], ref.refname); + cl_assert_equal_i(update_index, ref.update_index); reftable_ref_record_release(&ref); } - check_int(j, ==, N); + cl_assert_equal_i(j, N); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); free_names(names); } -static void t_table_write_small_table(void) +void test_reftable_readwrite__table_write_small_table(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 1; write_table(&names, &buf, N, 4096, REFTABLE_HASH_SHA1); - check_int(buf.len, <, 200); + cl_assert(buf.len < 200); reftable_buf_release(&buf); free_names(names); } -static void t_table_read_api(void) +void test_reftable_readwrite__table_read_api(void) { char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; - int err; struct reftable_log_record log = { 0 }; struct reftable_iterator it = { 0 }; + int err; write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); - check(!err); + err = reftable_table_new(&table, &source, "file.ref"); + cl_assert(!err); - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[0]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_log(&it, &log); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(err, REFTABLE_API_ERROR); reftable_buf_release(&buf); free_names(names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -450,7 +441,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; int err; int i = 0; @@ -463,43 +454,44 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); - check(!err); - check_int(hash_id, ==, reftable_reader_hash_id(reader)); + err = reftable_table_new(&table, &source, "file.ref"); + cl_assert(!err); + cl_assert_equal_i(hash_id, reftable_table_hash_id(table)); if (!index) { - reader->ref_offsets.index_offset = 0; + table->ref_offsets.index_offset = 0; } else { - check_int(reader->ref_offsets.index_offset, >, 0); + cl_assert(table->ref_offsets.index_offset > 0); } for (i = 1; i < N; i++) { - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, names[i]); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &ref); - check(!err); - check_str(names[i], ref.refname); - check_int(REFTABLE_REF_VAL1, ==, ref.value_type); - check_int(i, ==, ref.value.val1[0]); + cl_assert(!err); + cl_assert_equal_s(names[i], ref.refname); + cl_assert_equal_i(REFTABLE_REF_VAL1, ref.value_type); + cl_assert_equal_i(i, ref.value.val1[0]); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); } - check(!reftable_buf_addstr(&pastLast, names[N - 1])); - check(!reftable_buf_addstr(&pastLast, "/")); + cl_assert_equal_i(reftable_buf_addstr(&pastLast, names[N - 1]), + 0); + cl_assert_equal_i(reftable_buf_addstr(&pastLast, "/"), 0); - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, pastLast.buf); if (err == 0) { struct reftable_ref_record ref = { 0 }; int err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >, 0); + cl_assert(err > 0); } else { - check_int(err, >, 0); + cl_assert(err > 0); } reftable_buf_release(&pastLast); @@ -507,20 +499,20 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } -static void t_table_read_write_seek_linear(void) +void test_reftable_readwrite__table_read_write_seek_linear(void) { t_table_read_write_seek(0, REFTABLE_HASH_SHA1); } -static void t_table_read_write_seek_linear_sha256(void) +void test_reftable_readwrite__table_read_write_seek_linear_sha256(void) { t_table_read_write_seek(0, REFTABLE_HASH_SHA256); } -static void t_table_read_write_seek_index(void) +void test_reftable_readwrite__table_read_write_seek_index(void) { t_table_read_write_seek(1, REFTABLE_HASH_SHA1); } @@ -535,17 +527,19 @@ static void t_table_refs_for(int indexed) .block_size = 256, }; struct reftable_ref_record ref = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, + &opts); struct reftable_iterator it = { 0 }; - int N = 50, n, j, err, i; + int N = 50, j, i; + int err; want_names = reftable_calloc(N + 1, sizeof(*want_names)); - check(want_names != NULL); + cl_assert(want_names != NULL); - t_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); for (i = 0; i < N; i++) { uint8_t hash[REFTABLE_HASH_SIZE_SHA1]; @@ -561,121 +555,117 @@ static void t_table_refs_for(int indexed) ref.refname = name; ref.value_type = REFTABLE_REF_VAL2; - t_reftable_set_hash(ref.value.val2.value, i / 4, - REFTABLE_HASH_SHA1); - t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val2.value, i / 4, + REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val2.target_value, + 3 + i / 4, REFTABLE_HASH_SHA1); /* 80 bytes / entry, so 3 entries per block. Yields 17 */ /* blocks. */ - n = reftable_writer_add_ref(w, &ref); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); if (!memcmp(ref.value.val2.value, want_hash, REFTABLE_HASH_SIZE_SHA1) || !memcmp(ref.value.val2.target_value, want_hash, REFTABLE_HASH_SIZE_SHA1)) want_names[want_names_len++] = xstrdup(name); } - n = reftable_writer_close(w); - check_int(n, ==, 0); + cl_assert_equal_i(reftable_writer_close(w), 0); reftable_writer_free(w); w = NULL; block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); - check(!err); + err = reftable_table_new(&table, &source, "file.ref"); + cl_assert(!err); if (!indexed) - reader->obj_offsets.is_present = 0; + table->obj_offsets.is_present = 0; - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); - err = reftable_reader_refs_for(reader, &it, want_hash); - check(!err); + err = reftable_table_refs_for(table, &it, want_hash); + cl_assert(!err); for (j = 0; ; j++) { int err = reftable_iterator_next_ref(&it, &ref); - check_int(err, >=, 0); + cl_assert(err >= 0); if (err > 0) break; - check_int(j, <, want_names_len); - check_str(ref.refname, want_names[j]); + cl_assert(j < want_names_len); + cl_assert_equal_s(ref.refname, want_names[j]); reftable_ref_record_release(&ref); } - check_int(j, ==, want_names_len); + cl_assert_equal_i(j, want_names_len); reftable_buf_release(&buf); free_names(want_names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); } -static void t_table_refs_for_no_index(void) +void test_reftable_readwrite__table_refs_for_no_index(void) { t_table_refs_for(0); } -static void t_table_refs_for_obj_index(void) +void test_reftable_readwrite__table_refs_for_obj_index(void) { t_table_refs_for(1); } -static void t_write_empty_table(void) +void test_reftable_readwrite__write_empty_table(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_block_source source = { 0 }; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; int err; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_close(w); - check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + cl_assert_equal_i(reftable_writer_close(w), REFTABLE_EMPTY_TABLE_ERROR); reftable_writer_free(w); - check_int(buf.len, ==, header_size(1) + footer_size(1)); + cl_assert_equal_i(buf.len, header_size(1) + footer_size(1)); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); - check(!err); + err = reftable_table_new(&table, &source, "filename"); + cl_assert(!err); - err = reftable_reader_init_ref_iterator(rd, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert(!err); err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert(err > 0); reftable_iterator_destroy(&it); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_buf_release(&buf); } -static void t_write_object_id_min_length(void) +void test_reftable_readwrite__write_object_id_min_length(void) { struct reftable_write_options opts = { .block_size = 75, }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .update_index = 1, .value_type = REFTABLE_REF_VAL1, .value.val1 = {42}, }; - int err; int i; reftable_writer_set_limits(w, 1, 1); @@ -686,30 +676,27 @@ static void t_write_object_id_min_length(void) char name[256]; snprintf(name, sizeof(name), "ref%05d", i); ref.refname = name; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), 0); } - err = reftable_writer_close(w); - check(!err); - check_int(reftable_writer_stats(w)->object_id_len, ==, 2); + cl_assert_equal_i(reftable_writer_close(w), 0); + cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 2); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_object_id_length(void) +void test_reftable_readwrite__write_object_id_length(void) { struct reftable_write_options opts = { .block_size = 75, }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .update_index = 1, .value_type = REFTABLE_REF_VAL1, .value.val1 = {42}, }; - int err; int i; reftable_writer_set_limits(w, 1, 1); @@ -721,44 +708,39 @@ static void t_write_object_id_length(void) snprintf(name, sizeof(name), "ref%05d", i); ref.refname = name; ref.value.val1[15] = i; - err = reftable_writer_add_ref(w, &ref); - check(!err); + cl_assert(reftable_writer_add_ref(w, &ref) == 0); } - err = reftable_writer_close(w); - check(!err); - check_int(reftable_writer_stats(w)->object_id_len, ==, 16); + cl_assert_equal_i(reftable_writer_close(w), 0); + cl_assert_equal_i(reftable_writer_stats(w)->object_id_len, 16); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_empty_key(void) +void test_reftable_readwrite__write_empty_key(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record ref = { .refname = (char *) "", .update_index = 1, .value_type = REFTABLE_REF_DELETION, }; - int err; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &ref); - check_int(err, ==, REFTABLE_API_ERROR); - - err = reftable_writer_close(w); - check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &ref), REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_close(w), + REFTABLE_EMPTY_TABLE_ERROR); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_key_order(void) +void test_reftable_readwrite__write_key_order(void) { struct reftable_write_options opts = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; - struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); + struct reftable_writer *w = cl_reftable_strbuf_writer(&buf, &opts); struct reftable_ref_record refs[2] = { { .refname = (char *) "b", @@ -776,24 +758,21 @@ static void t_write_key_order(void) }, } }; - int err; reftable_writer_set_limits(w, 1, 1); - err = reftable_writer_add_ref(w, &refs[0]); - check(!err); - err = reftable_writer_add_ref(w, &refs[1]); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), 0); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[1]), + REFTABLE_API_ERROR); refs[0].update_index = 2; - err = reftable_writer_add_ref(w, &refs[0]); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_writer_add_ref(w, &refs[0]), REFTABLE_API_ERROR); reftable_writer_close(w); reftable_writer_free(w); reftable_buf_release(&buf); } -static void t_write_multiple_indices(void) +void test_reftable_readwrite__write_multiple_indices(void) { struct reftable_write_options opts = { .block_size = 100, @@ -803,11 +782,12 @@ static void t_write_multiple_indices(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; char buf[128]; - int err, i; + int i; + int err; - writer = t_reftable_strbuf_writer(&writer_buf, &opts); + writer = cl_reftable_strbuf_writer(&writer_buf, &opts); reftable_writer_set_limits(writer, 1, 1); for (i = 0; i < 100; i++) { struct reftable_ref_record ref = { @@ -819,8 +799,7 @@ static void t_write_multiple_indices(void) snprintf(buf, sizeof(buf), "refs/heads/%04d", i); ref.refname = buf; - err = reftable_writer_add_ref(writer, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0); } for (i = 0; i < 100; i++) { @@ -836,8 +815,7 @@ static void t_write_multiple_indices(void) snprintf(buf, sizeof(buf), "refs/heads/%04d", i); log.refname = buf; - err = reftable_writer_add_log(writer, &log); - check(!err); + cl_assert_equal_i(reftable_writer_add_log(writer, &log), 0); } reftable_writer_close(writer); @@ -847,30 +825,30 @@ static void t_write_multiple_indices(void) * for each of the block types. */ stats = reftable_writer_stats(writer); - check_int(stats->ref_stats.index_offset, >, 0); - check_int(stats->obj_stats.index_offset, >, 0); - check_int(stats->log_stats.index_offset, >, 0); + cl_assert(stats->ref_stats.index_offset > 0); + cl_assert(stats->obj_stats.index_offset > 0); + cl_assert(stats->log_stats.index_offset > 0); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); - check(!err); + err = reftable_table_new(&table, &source, "filename"); + cl_assert(!err); /* * Seeking the log uses the log index now. In case there is any * confusion regarding indices we would notice here. */ - err = reftable_reader_init_log_iterator(reader, &it); - check(!err); + err = reftable_table_init_log_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_log(&it, ""); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); } -static void t_write_multi_level_index(void) +void test_reftable_readwrite__write_multi_level_index(void) { struct reftable_write_options opts = { .block_size = 100, @@ -880,10 +858,10 @@ static void t_write_multi_level_index(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; int err; - writer = t_reftable_strbuf_writer(&writer_buf, &opts); + writer = cl_reftable_strbuf_writer(&writer_buf, &opts); reftable_writer_set_limits(writer, 1, 1); for (size_t i = 0; i < 200; i++) { struct reftable_ref_record ref = { @@ -896,8 +874,7 @@ static void t_write_multi_level_index(void) snprintf(buf, sizeof(buf), "refs/heads/%03" PRIuMAX, (uintmax_t)i); ref.refname = buf; - err = reftable_writer_add_ref(writer, &ref); - check(!err); + cl_assert_equal_i(reftable_writer_add_ref(writer, &ref), 0); } reftable_writer_close(writer); @@ -906,80 +883,52 @@ static void t_write_multi_level_index(void) * multi-level index. */ stats = reftable_writer_stats(writer); - check_int(stats->ref_stats.max_index_level, ==, 2); + cl_assert_equal_i(stats->ref_stats.max_index_level, 2); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); - check(!err); + err = reftable_table_new(&table, &source, "filename"); + cl_assert(!err); /* * Seeking the last ref should work as expected. */ - err = reftable_reader_init_ref_iterator(reader, &it); - check(!err); + err = reftable_table_init_ref_iterator(table, &it); + cl_assert(!err); err = reftable_iterator_seek_ref(&it, "refs/heads/199"); - check(!err); + cl_assert(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); reftable_buf_release(&buf); } -static void t_corrupt_table_empty(void) +void test_reftable_readwrite__corrupt_table_empty(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + err = reftable_table_new(&table, &source, "file.log"); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); } -static void t_corrupt_table(void) +void test_reftable_readwrite__corrupt_table(void) { uint8_t zeros[1024] = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; - check(!reftable_buf_add(&buf, zeros, sizeof(zeros))); + + cl_assert(!reftable_buf_add(&buf, zeros, sizeof(zeros))); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + err = reftable_table_new(&table, &source, "file.log"); + cl_assert_equal_i(err, REFTABLE_FORMAT_ERROR); reftable_buf_release(&buf); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_buffer(), "strbuf works as blocksource"); - TEST(t_corrupt_table(), "read-write on corrupted table"); - TEST(t_corrupt_table_empty(), "read-write on an empty table"); - TEST(t_log_buffer_size(), "buffer extension for log compression"); - TEST(t_log_overflow(), "log overflow returns expected error"); - TEST(t_log_write_limits(), "writer limits for writing log records"); - TEST(t_log_write_read(), "read-write on log records"); - TEST(t_log_zlib_corruption(), "reading corrupted log record returns expected error"); - TEST(t_table_read_api(), "read on a table"); - TEST(t_table_read_write_seek_index(), "read-write on a table with index"); - TEST(t_table_read_write_seek_linear(), "read-write on a table without index (SHA1)"); - TEST(t_table_read_write_seek_linear_sha256(), "read-write on a table without index (SHA256)"); - TEST(t_table_read_write_sequential(), "sequential read-write on a table"); - TEST(t_table_refs_for_no_index(), "refs-only table with no index"); - TEST(t_table_refs_for_obj_index(), "refs-only table with index"); - TEST(t_table_write_small_table(), "write_table works"); - TEST(t_write_empty_key(), "write on refs with empty keys"); - TEST(t_write_empty_table(), "read-write on empty tables"); - TEST(t_write_key_order(), "refs must be written in increasing order"); - TEST(t_write_multi_level_index(), "table with multi-level index"); - TEST(t_write_multiple_indices(), "table with indices for multiple block types"); - TEST(t_write_object_id_length(), "prefix compression on writing refs"); - TEST(t_write_object_id_min_length(), "prefix compression on writing refs"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/u-reftable-record.c index 42bc64cec8..6c8c0d5374 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/u-reftable-record.c @@ -6,7 +6,8 @@ https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" +#include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/constants.h" #include "reftable/record.h" @@ -17,16 +18,17 @@ static void t_copy(struct reftable_record *rec) uint8_t typ; typ = reftable_record_type(rec); - reftable_record_init(©, typ); + cl_assert_equal_i(reftable_record_init(©, typ), 0); reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); /* do it twice to catch memory leaks */ reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); - check(reftable_record_equal(rec, ©, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(rec, ©, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(©); } -static void t_varint_roundtrip(void) +void test_reftable_record__varint_roundtrip(void) { uint64_t inputs[] = { 0, 1, @@ -49,54 +51,75 @@ static void t_varint_roundtrip(void) int n = put_var_int(&out, in); uint64_t got = 0; - check_int(n, >, 0); + cl_assert(n > 0); out.len = n; n = get_var_int(&got, &out); - check_int(n, >, 0); + cl_assert(n > 0); - check_int(got, ==, in); + cl_assert_equal_i(got, in); } } +void test_reftable_record__varint_overflow(void) +{ + unsigned char buf[] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, + }; + struct string_view view = { + .buf = buf, + .len = sizeof(buf), + }; + uint64_t value; + cl_assert_equal_i(get_var_int(&value, &view), -1); +} + static void set_hash(uint8_t *h, int j) { - for (int i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) + for (size_t i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) h[i] = (j >> i) & 0xff; } -static void t_reftable_ref_record_comparison(void) +void test_reftable_record__ref_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_VAL1, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_DELETION, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "HEAD", .u.ref.value_type = REFTABLE_REF_SYMREF, .u.ref.value.symref = (char *) "refs/heads/master", }, }; + int cmp; - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) == 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + cl_assert(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1) == 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.ref.value_type = in[0].u.ref.value_type; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); } -static void t_reftable_ref_record_compare_name(void) +void test_reftable_record__ref_record_compare_name(void) { struct reftable_ref_record recs[3] = { { @@ -110,21 +133,24 @@ static void t_reftable_ref_record_compare_name(void) }, }; - check_int(reftable_ref_record_compare_name(&recs[0], &recs[1]), <, 0); - check_int(reftable_ref_record_compare_name(&recs[1], &recs[0]), >, 0); - check_int(reftable_ref_record_compare_name(&recs[0], &recs[2]), ==, 0); + cl_assert(reftable_ref_record_compare_name(&recs[0], + &recs[1]) < 0); + cl_assert(reftable_ref_record_compare_name(&recs[1], + &recs[0]) > 0); + cl_assert_equal_i(reftable_ref_record_compare_name(&recs[0], + &recs[2]), 0); } -static void t_reftable_ref_record_roundtrip(void) +void test_reftable_record__ref_record_roundtrip(void) { struct reftable_buf scratch = REFTABLE_BUF_INIT; for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) { struct reftable_record in = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.value_type = i, }; - struct reftable_record out = { .type = BLOCK_TYPE_REF }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_REF }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -152,19 +178,21 @@ static void t_reftable_ref_record_roundtrip(void) t_copy(&in); - check_int(reftable_record_val_type(&in), ==, i); - check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION); + cl_assert_equal_i(reftable_record_val_type(&in), i); + cl_assert_equal_i(reftable_record_is_deletion(&in), + i == REFTABLE_REF_DELETION); reftable_record_key(&in, &key); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); /* decode into a non-zero reftable_record to test for leaks. */ m = reftable_record_decode(&out, key, i, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_ref_record_equal(&in.u.ref, &out.u.ref, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_ref_record_equal(&in.u.ref, + &out.u.ref, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(&in); reftable_buf_release(&key); @@ -174,39 +202,45 @@ static void t_reftable_ref_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_reftable_log_record_comparison(void) +void test_reftable_record__log_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 42, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 22, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/main", .u.log.update_index = 22, }, }; - - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + int cmp; + + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); /* comparison should be reversed for equal keys, because * comparison is now performed on the basis of update indices */ - check_int(reftable_record_cmp(&in[0], &in[1]), <, 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(cmp < 0); in[1].u.log.update_index = in[0].u.log.update_index; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); } -static void t_reftable_log_record_compare_key(void) +void test_reftable_record__log_record_compare_key(void) { struct reftable_log_record logs[3] = { { @@ -223,19 +257,24 @@ static void t_reftable_log_record_compare_key(void) }, }; - check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0); - check_int(reftable_log_record_compare_key(&logs[1], &logs[0]), >, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[1]) < 0); + cl_assert(reftable_log_record_compare_key(&logs[1], + &logs[0]) > 0); logs[1].update_index = logs[0].update_index; - check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[1]) < 0); - check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), >, 0); - check_int(reftable_log_record_compare_key(&logs[2], &logs[0]), <, 0); + cl_assert(reftable_log_record_compare_key(&logs[0], + &logs[2]) > 0); + cl_assert(reftable_log_record_compare_key(&logs[2], + &logs[0]) < 0); logs[2].update_index = logs[0].update_index; - check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), ==, 0); + cl_assert_equal_i(reftable_log_record_compare_key(&logs[0], &logs[2]), 0); } -static void t_reftable_log_record_roundtrip(void) +void test_reftable_record__log_record_roundtrip(void) { struct reftable_log_record in[] = { { @@ -269,12 +308,12 @@ static void t_reftable_log_record_roundtrip(void) set_hash(in[2].value.update.new_hash, 3); set_hash(in[2].value.update.old_hash, 4); - check(!reftable_log_record_is_deletion(&in[0])); - check(reftable_log_record_is_deletion(&in[1])); - check(!reftable_log_record_is_deletion(&in[2])); + cl_assert_equal_i(reftable_log_record_is_deletion(&in[0]), 0); + cl_assert(reftable_log_record_is_deletion(&in[1]) != 0); + cl_assert_equal_i(reftable_log_record_is_deletion(&in[2]), 0); for (size_t i = 0; i < ARRAY_SIZE(in); i++) { - struct reftable_record rec = { .type = BLOCK_TYPE_LOG }; + struct reftable_record rec = { .type = REFTABLE_BLOCK_TYPE_LOG }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -283,7 +322,7 @@ static void t_reftable_log_record_roundtrip(void) }; /* populate out, to check for leaks. */ struct reftable_record out = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log = { .refname = xstrdup("old name"), .value_type = REFTABLE_LOG_UPDATE, @@ -305,14 +344,14 @@ static void t_reftable_log_record_roundtrip(void) reftable_record_key(&rec, &key); n = reftable_record_encode(&rec, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >=, 0); + cl_assert(n >= 0); valtype = reftable_record_val_type(&rec); m = reftable_record_decode(&out, key, valtype, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_log_record_equal(&in[i], &out.u.log, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_log_record_equal(&in[i], &out.u.log, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&in[i]); reftable_buf_release(&key); reftable_record_release(&out); @@ -321,7 +360,7 @@ static void t_reftable_log_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_key_roundtrip(void) +void test_reftable_record__key_roundtrip(void) { uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -336,63 +375,72 @@ static void t_key_roundtrip(void) int n, m; uint8_t rt_extra; - check(!reftable_buf_addstr(&last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&key, "refs/tags/bla")); + cl_assert_equal_i(reftable_buf_addstr(&last_key, + "refs/heads/master"), 0); + cl_assert_equal_i(reftable_buf_addstr(&key, + "refs/tags/bla"), 0); extra = 6; n = reftable_encode_key(&restart, dest, last_key, key, extra); - check(!restart); - check_int(n, >, 0); + cl_assert(!restart); + cl_assert(n > 0); - check(!reftable_buf_addstr(&roundtrip, "refs/heads/master")); + cl_assert_equal_i(reftable_buf_addstr(&roundtrip, + "refs/heads/master"), 0); m = reftable_decode_key(&roundtrip, &rt_extra, dest); - check_int(n, ==, m); - check(!reftable_buf_cmp(&key, &roundtrip)); - check_int(rt_extra, ==, extra); + cl_assert_equal_i(n, m); + cl_assert_equal_i(reftable_buf_cmp(&key, &roundtrip), 0); + cl_assert_equal_i(rt_extra, extra); reftable_buf_release(&last_key); reftable_buf_release(&key); reftable_buf_release(&roundtrip); } -static void t_reftable_obj_record_comparison(void) +void test_reftable_record__obj_record_comparison(void) { uint8_t id_bytes[] = { 0, 1, 2, 3, 4, 5, 6 }; uint64_t offsets[] = { 0, 16, 32, 48, 64, 80, 96, 112}; struct reftable_record in[3] = { { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 8, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 5, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 5, }, }; + int cmp; - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.obj.offset_len = in[0].u.obj.offset_len; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); } -static void t_reftable_obj_record_roundtrip(void) +void test_reftable_record__obj_record_roundtrip(void) { uint8_t testHash1[REFTABLE_HASH_SIZE_SHA1] = { 1, 2, 3, 4, 0 }; uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; @@ -423,27 +471,28 @@ static void t_reftable_obj_record_roundtrip(void) .len = sizeof(buffer), }; struct reftable_record in = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u = { .obj = recs[i], }, }; struct reftable_buf key = REFTABLE_BUF_INIT; - struct reftable_record out = { .type = BLOCK_TYPE_OBJ }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_OBJ }; int n, m; uint8_t extra; - check(!reftable_record_is_deletion(&in)); + cl_assert_equal_i(reftable_record_is_deletion(&in), 0); t_copy(&in); reftable_record_key(&in, &key); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); extra = reftable_record_val_type(&in); m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); - check_int(n, ==, m); + cl_assert_equal_i(n, m); - check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(&in, &out, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_buf_release(&key); reftable_record_release(&out); } @@ -451,47 +500,57 @@ static void t_reftable_obj_record_roundtrip(void) reftable_buf_release(&scratch); } -static void t_reftable_index_record_comparison(void) +void test_reftable_record__index_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 22, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, }; - check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); - check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); + int cmp; + + cl_assert_equal_i(reftable_buf_addstr(&in[0].u.idx.last_key, + "refs/heads/master"), 0); + cl_assert_equal_i(reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master"), 0); + cl_assert(reftable_buf_addstr(&in[2].u.idx.last_key, + "refs/heads/branch") == 0); - check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert_equal_i(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); - check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + cl_assert_equal_i(reftable_record_equal(&in[1], &in[2], + REFTABLE_HASH_SIZE_SHA1), 0); + cl_assert_equal_i(reftable_record_cmp(&in[1], &in[2], &cmp), 0); + cl_assert(cmp > 0); in[1].u.idx.offset = in[0].u.idx.offset; - check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + cl_assert(reftable_record_equal(&in[0], &in[1], + REFTABLE_HASH_SIZE_SHA1) != 0); + cl_assert_equal_i(reftable_record_cmp(&in[0], &in[1], &cmp), 0); + cl_assert(!cmp); for (size_t i = 0; i < ARRAY_SIZE(in); i++) reftable_record_release(&in[i]); } -static void t_reftable_index_record_roundtrip(void) +void test_reftable_record__index_record_roundtrip(void) { struct reftable_record in = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .offset = 42, .last_key = REFTABLE_BUF_INIT, @@ -505,48 +564,32 @@ static void t_reftable_index_record_roundtrip(void) struct reftable_buf scratch = REFTABLE_BUF_INIT; struct reftable_buf key = REFTABLE_BUF_INIT; struct reftable_record out = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int n, m; uint8_t extra; - check(!reftable_buf_addstr(&in.u.idx.last_key, "refs/heads/master")); + cl_assert_equal_i(reftable_buf_addstr(&in.u.idx.last_key, + "refs/heads/master"), 0); reftable_record_key(&in, &key); t_copy(&in); - check(!reftable_record_is_deletion(&in)); - check(!reftable_buf_cmp(&key, &in.u.idx.last_key)); + cl_assert_equal_i(reftable_record_is_deletion(&in), 0); + cl_assert_equal_i(reftable_buf_cmp(&key, &in.u.idx.last_key), 0); n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); - check_int(n, >, 0); + cl_assert(n > 0); extra = reftable_record_val_type(&in); - m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, - &scratch); - check_int(m, ==, n); + m = reftable_record_decode(&out, key, extra, dest, + REFTABLE_HASH_SIZE_SHA1, &scratch); + cl_assert_equal_i(m, n); - check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); + cl_assert(reftable_record_equal(&in, &out, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_record_release(&out); reftable_buf_release(&key); reftable_buf_release(&scratch); reftable_buf_release(&in.u.idx.last_key); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record"); - TEST(t_reftable_log_record_comparison(), "comparison operations work on log record"); - TEST(t_reftable_index_record_comparison(), "comparison operations work on index record"); - TEST(t_reftable_obj_record_comparison(), "comparison operations work on obj record"); - TEST(t_reftable_ref_record_compare_name(), "reftable_ref_record_compare_name works"); - TEST(t_reftable_log_record_compare_key(), "reftable_log_record_compare_key works"); - TEST(t_reftable_log_record_roundtrip(), "record operations work on log record"); - TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record"); - TEST(t_varint_roundtrip(), "put_var_int and get_var_int work"); - TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work"); - TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record"); - TEST(t_reftable_index_record_roundtrip(), "record operations work on index record"); - - return test_done(); -} diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/u-reftable-stack.c index aeec195b2b..a8b91812e8 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/u-reftable-stack.c @@ -8,13 +8,13 @@ https://developers.google.com/open-source/licenses/bsd #define DISABLE_SIGN_COMPARE_WARNINGS -#include "test-lib.h" -#include "lib-reftable.h" +#include "unit-test.h" #include "dir.h" +#include "lib-reftable.h" #include "reftable/merged.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/stack.h" +#include "reftable/table.h" #include "strbuf.h" #include "tempfile.h" #include <dirent.h> @@ -70,11 +70,11 @@ static char *get_tmp_template(int linenumber) static char *get_tmp_dir(int linenumber) { char *dir = get_tmp_template(linenumber); - check(mkdtemp(dir) != NULL); + cl_assert(mkdtemp(dir) != NULL); return dir; } -static void t_read_file(void) +void test_reftable_stack__read_file(void) { char *fn = get_tmp_template(__LINE__); struct tempfile *tmp = mks_tempfile(fn); @@ -84,17 +84,17 @@ static void t_read_file(void) char **names = NULL; const char *want[] = { "line1", "line2", "line3" }; - check_int(fd, >, 0); + cl_assert(fd > 0); n = write_in_full(fd, out, strlen(out)); - check_int(n, ==, strlen(out)); + cl_assert_equal_i(n, strlen(out)); err = close(fd); - check_int(err, >=, 0); + cl_assert(err >= 0); err = read_lines(fn, &names); - check(!err); + cl_assert(!err); for (size_t i = 0; names[i]; i++) - check_str(want[i], names[i]); + cl_assert_equal_s(want[i], names[i]); free_names(names); (void) remove(fn); delete_tempfile(&tmp); @@ -103,7 +103,8 @@ static void t_read_file(void) static int write_test_ref(struct reftable_writer *wr, void *arg) { struct reftable_ref_record *ref = arg; - reftable_writer_set_limits(wr, ref->update_index, ref->update_index); + cl_assert_equal_i(reftable_writer_set_limits(wr, + ref->update_index, ref->update_index), 0); return reftable_writer_add_ref(wr, ref); } @@ -111,7 +112,6 @@ static void write_n_ref_tables(struct reftable_stack *st, size_t n) { int disable_auto_compact; - int err; disable_auto_compact = st->opts.disable_auto_compact; st->opts.disable_auto_compact = 1; @@ -125,10 +125,10 @@ static void write_n_ref_tables(struct reftable_stack *st, snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i); ref.refname = buf; - t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); - err = reftable_stack_add(st, &write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, + &write_test_ref, &ref, 0), 0); } st->opts.disable_auto_compact = disable_auto_compact; @@ -143,11 +143,13 @@ static int write_test_log(struct reftable_writer *wr, void *arg) { struct write_log_arg *wla = arg; - reftable_writer_set_limits(wr, wla->update_index, wla->update_index); + cl_assert_equal_i(reftable_writer_set_limits(wr, + wla->update_index, + wla->update_index), 0); return reftable_writer_add_log(wr, wla->log); } -static void t_reftable_stack_add_one(void) +void test_reftable_stack__add_one(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_buf scratch = REFTABLE_BUF_INIT; @@ -156,7 +158,6 @@ static void t_reftable_stack_add_one(void) .default_permissions = 0660, }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref = { .refname = (char *) "HEAD", .update_index = 1, @@ -165,32 +166,37 @@ static void t_reftable_stack_add_one(void) }; struct reftable_ref_record dest = { 0 }; struct stat stat_result = { 0 }; + int err; + err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert(!err); - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + err = reftable_stack_add(st, write_test_ref, &ref, 0); + cl_assert(!err); err = reftable_stack_read_ref(st, ref.refname, &dest); - check(!err); - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); - check_int(st->readers_len, >, 0); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1)); + cl_assert(st->tables_len > 0); #ifndef GIT_WINDOWS_NATIVE - check(!reftable_buf_addstr(&scratch, dir)); - check(!reftable_buf_addstr(&scratch, "/tables.list")); - err = stat(scratch.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&scratch, + "/tables.list"), 0); + cl_assert_equal_i(stat(scratch.buf, &stat_result), 0); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); reftable_buf_reset(&scratch); - check(!reftable_buf_addstr(&scratch, dir)); - check(!reftable_buf_addstr(&scratch, "/")); + cl_assert_equal_i(reftable_buf_addstr(&scratch, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&scratch, "/"), 0); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&scratch, st->readers[0]->name)); + cl_assert(!reftable_buf_addstr(&scratch, st->tables[0]->name)); err = stat(scratch.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert(!err); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); #else (void) stat_result; #endif @@ -202,14 +208,13 @@ static void t_reftable_stack_add_one(void) umask(mask); } -static void t_reftable_stack_uptodate(void) +void test_reftable_stack__uptodate(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL; struct reftable_stack *st2 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; struct reftable_ref_record ref1 = { .refname = (char *) "HEAD", .update_index = 1, @@ -227,34 +232,25 @@ static void t_reftable_stack_uptodate(void) /* simulate multi-process access to the same stack by creating two stacks for the same directory. */ - err = reftable_new_stack(&st1, dir, &opts); - check(!err); - - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_add(st1, write_test_ref, &ref1); - check(!err); - - err = reftable_stack_add(st2, write_test_ref, &ref2); - check_int(err, ==, REFTABLE_OUTDATED_ERROR); - - err = reftable_stack_reload(st2); - check(!err); - - err = reftable_stack_add(st2, write_test_ref, &ref2); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st1, write_test_ref, + &ref1, 0), 0); + cl_assert_equal_i(reftable_stack_add(st2, write_test_ref, + &ref2, 0), REFTABLE_OUTDATED_ERROR); + cl_assert_equal_i(reftable_stack_reload(st2), 0); + cl_assert_equal_i(reftable_stack_add(st2, write_test_ref, + &ref2, 0), 0); reftable_stack_destroy(st1); reftable_stack_destroy(st2); clear_dir(dir); } -static void t_reftable_stack_transaction_api(void) +void test_reftable_stack__transaction_api(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_addition *add = NULL; struct reftable_ref_record ref = { @@ -265,37 +261,32 @@ static void t_reftable_stack_transaction_api(void) }; struct reftable_ref_record dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); reftable_addition_destroy(add); - err = reftable_stack_new_addition(&add, st, 0); - check(!err); - - err = reftable_addition_add(add, write_test_ref, &ref); - check(!err); - - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &ref), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); - err = reftable_stack_read_ref(st, ref.refname, &dest); - check(!err); - check_int(REFTABLE_REF_SYMREF, ==, dest.value_type); - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st, ref.refname, + &dest), 0); + cl_assert_equal_i(REFTABLE_REF_SYMREF, dest.value_type); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_transaction_with_reload(void) +void test_reftable_stack__transaction_with_reload(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_stack *st1 = NULL, *st2 = NULL; - int err; struct reftable_addition *add = NULL; struct reftable_ref_record refs[2] = { { @@ -313,17 +304,12 @@ static void t_reftable_stack_transaction_with_reload(void) }; struct reftable_ref_record ref = { 0 }; - err = reftable_new_stack(&st1, dir, NULL); - check(!err); - err = reftable_new_stack(&st2, dir, NULL); - check(!err); - - err = reftable_stack_new_addition(&add, st1, 0); - check(!err); - err = reftable_addition_add(add, write_test_ref, &refs[0]); - check(!err); - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, NULL), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, NULL), 0); + cl_assert_equal_i(reftable_stack_new_addition(&add, st1, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &refs[0]), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); /* @@ -331,20 +317,20 @@ static void t_reftable_stack_transaction_with_reload(void) * create the addition and lock the stack by default, but allow the * reload to happen when REFTABLE_STACK_NEW_ADDITION_RELOAD is set. */ - err = reftable_stack_new_addition(&add, st2, 0); - check_int(err, ==, REFTABLE_OUTDATED_ERROR); - err = reftable_stack_new_addition(&add, st2, REFTABLE_STACK_NEW_ADDITION_RELOAD); - check(!err); - err = reftable_addition_add(add, write_test_ref, &refs[1]); - check(!err); - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, st2, 0), + REFTABLE_OUTDATED_ERROR); + cl_assert_equal_i(reftable_stack_new_addition(&add, st2, + REFTABLE_STACK_NEW_ADDITION_RELOAD), 0); + cl_assert_equal_i(reftable_addition_add(add, write_test_ref, + &refs[1]), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); for (size_t i = 0; i < ARRAY_SIZE(refs); i++) { - err = reftable_stack_read_ref(st2, refs[i].refname, &ref); - check(!err); - check(reftable_ref_record_equal(&refs[i], &ref, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st2, + refs[i].refname, &ref) , 0); + cl_assert(reftable_ref_record_equal(&refs[i], &ref, + REFTABLE_HASH_SIZE_SHA1) != 0); } reftable_ref_record_release(&ref); @@ -353,17 +339,15 @@ static void t_reftable_stack_transaction_with_reload(void) clear_dir(dir); } -static void t_reftable_stack_transaction_api_performs_auto_compaction(void) +void test_reftable_stack__transaction_api_performs_auto_compaction(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = {0}; struct reftable_addition *add = NULL; struct reftable_stack *st = NULL; size_t n = 20; - int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (size_t i = 0; i <= n; i++) { struct reftable_ref_record ref = { @@ -383,14 +367,11 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) */ st->opts.disable_auto_compact = i != n; - err = reftable_stack_new_addition(&add, st, 0); - check(!err); - - err = reftable_addition_add(add, write_test_ref, &ref); - check(!err); - - err = reftable_addition_commit(add); - check(!err); + cl_assert_equal_i(reftable_stack_new_addition(&add, + st, 0), 0); + cl_assert_equal_i(reftable_addition_add(add, + write_test_ref, &ref), 0); + cl_assert_equal_i(reftable_addition_commit(add), 0); reftable_addition_destroy(add); @@ -400,16 +381,16 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + cl_assert_equal_i(st->merged->tables_len, i + 1); else - check_int(st->merged->readers_len, ==, 1); + cl_assert_equal_i(st->merged->tables_len, 1); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_fails_gracefully(void) +void test_reftable_stack__auto_compaction_fails_gracefully(void) { struct reftable_ref_record ref = { .refname = (char *) "refs/heads/master", @@ -423,32 +404,31 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); - check_int(st->merged->readers_len, ==, 1); - check_int(st->stats.attempts, ==, 0); - check_int(st->stats.failures, ==, 0); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref, 0), 0); + cl_assert_equal_i(st->merged->tables_len, 1); + cl_assert_equal_i(st->stats.attempts, 0); + cl_assert_equal_i(st->stats.failures, 0); /* * Lock the newly written table such that it cannot be compacted. * Adding a new table to the stack should not be impacted by this, even * though auto-compaction will now fail. */ - check(!reftable_buf_addstr(&table_path, dir)); - check(!reftable_buf_addstr(&table_path, "/")); - check(!reftable_buf_addstr(&table_path, st->readers[0]->name)); - check(!reftable_buf_addstr(&table_path, ".lock")); + cl_assert(!reftable_buf_addstr(&table_path, dir)); + cl_assert(!reftable_buf_addstr(&table_path, "/")); + cl_assert(!reftable_buf_addstr(&table_path, + st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, "", 0); ref.update_index = 2; - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); - check_int(st->merged->readers_len, ==, 2); - check_int(st->stats.attempts, ==, 1); - check_int(st->stats.failures, ==, 1); + err = reftable_stack_add(st, write_test_ref, &ref, 0); + cl_assert(!err); + cl_assert_equal_i(st->merged->tables_len, 2); + cl_assert_equal_i(st->stats.attempts, 1); + cl_assert_equal_i(st->stats.failures, 1); reftable_stack_destroy(st); reftable_buf_release(&table_path); @@ -460,12 +440,11 @@ static int write_error(struct reftable_writer *wr UNUSED, void *arg) return *((int *)arg); } -static void t_reftable_stack_update_index_check(void) +void test_reftable_stack__update_index_check(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref1 = { .refname = (char *) "name1", .update_index = 1, @@ -479,39 +458,33 @@ static void t_reftable_stack_update_index_check(void) .value.symref = (char *) "master", }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref1); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref2); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref1, 0), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref2, 0), REFTABLE_API_ERROR); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_lock_failure(void) +void test_reftable_stack__lock_failure(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err, i; + int i; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) { - err = reftable_stack_add(st, write_error, &i); - check_int(err, ==, i); - } + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) + cl_assert_equal_i(reftable_stack_add(st, write_error, + &i, 0), i); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_add(void) +void test_reftable_stack__add(void) { - int err = 0; struct reftable_write_options opts = { .exact_log_message = 1, .default_permissions = 0660, @@ -524,9 +497,10 @@ static void t_reftable_stack_add(void) struct reftable_buf path = REFTABLE_BUF_INIT; struct stat stat_result; size_t i, N = ARRAY_SIZE(refs); + int err = 0; err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert(!err); for (i = 0; i < N; i++) { char buf[256]; @@ -534,66 +508,66 @@ static void t_reftable_stack_add(void) refs[i].refname = xstrdup(buf); refs[i].update_index = i + 1; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); logs[i].refname = xstrdup(buf); logs[i].update_index = N + i + 1; logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.email = xstrdup("identity@invalid"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &refs[i], 0), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); } - err = reftable_stack_compact_all(st, NULL); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); for (i = 0; i < N; i++) { struct reftable_ref_record dest = { 0 }; - int err = reftable_stack_read_ref(st, refs[i].refname, &dest); - check(!err); - check(reftable_ref_record_equal(&dest, refs + i, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_ref(st, + refs[i].refname, &dest), 0); + cl_assert(reftable_ref_record_equal(&dest, refs + i, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); } for (i = 0; i < N; i++) { struct reftable_log_record dest = { 0 }; - int err = reftable_stack_read_log(st, refs[i].refname, &dest); - check(!err); - check(reftable_log_record_equal(&dest, logs + i, - REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_stack_read_log(st, + refs[i].refname, &dest), 0); + cl_assert(reftable_log_record_equal(&dest, logs + i, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&dest); } #ifndef GIT_WINDOWS_NATIVE - check(!reftable_buf_addstr(&path, dir)); - check(!reftable_buf_addstr(&path, "/tables.list")); - err = stat(path.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&path, "/tables.list"), 0); + cl_assert_equal_i(stat(path.buf, &stat_result), 0); + cl_assert_equal_i((stat_result.st_mode & 0777), opts.default_permissions); reftable_buf_reset(&path); - check(!reftable_buf_addstr(&path, dir)); - check(!reftable_buf_addstr(&path, "/")); + cl_assert_equal_i(reftable_buf_addstr(&path, dir), 0); + cl_assert_equal_i(reftable_buf_addstr(&path, "/"), 0); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&path, st->readers[0]->name)); + cl_assert(!reftable_buf_addstr(&path, st->tables[0]->name)); err = stat(path.buf, &stat_result); - check(!err); - check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); + cl_assert(!err); + cl_assert_equal_i((stat_result.st_mode & 0777), + opts.default_permissions); #else (void) stat_result; #endif @@ -608,7 +582,7 @@ static void t_reftable_stack_add(void) clear_dir(dir); } -static void t_reftable_stack_iterator(void) +void test_reftable_stack__iterator(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; @@ -619,27 +593,27 @@ static void t_reftable_stack_iterator(void) size_t N = ARRAY_SIZE(refs), i; int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i < N; i++) { refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); refs[i].update_index = i + 1; refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); logs[i].update_index = i + 1; logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.email = xstrdup("johndoe@invalid"); logs[i].value.update.message = xstrdup("commit\n"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } - for (i = 0; i < N; i++) { - err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &refs[i], 0), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { @@ -647,8 +621,8 @@ static void t_reftable_stack_iterator(void) .update_index = reftable_stack_next_update_index(st), }; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); } reftable_stack_init_ref_iterator(st, &it); @@ -659,16 +633,16 @@ static void t_reftable_stack_iterator(void) err = reftable_iterator_next_ref(&it, &ref); if (err > 0) break; - check(!err); - check(reftable_ref_record_equal(&ref, &refs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_ref_record_equal(&ref, &refs[i], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&ref); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_iterator_destroy(&it); - err = reftable_stack_init_log_iterator(st, &it); - check(!err); + cl_assert_equal_i(reftable_stack_init_log_iterator(st, &it), 0); reftable_iterator_seek_log(&it, logs[0].refname); for (i = 0; ; i++) { @@ -677,11 +651,12 @@ static void t_reftable_stack_iterator(void) err = reftable_iterator_next_log(&it, &log); if (err > 0) break; - check(!err); - check(reftable_log_record_equal(&log, &logs[i], REFTABLE_HASH_SIZE_SHA1)); + cl_assert(!err); + cl_assert(reftable_log_record_equal(&log, &logs[i], + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_log_record_release(&log); } - check_int(i, ==, N); + cl_assert_equal_i(i, N); reftable_stack_destroy(st); reftable_iterator_destroy(&it); @@ -692,9 +667,8 @@ static void t_reftable_stack_iterator(void) clear_dir(dir); } -static void t_reftable_stack_log_normalize(void) +void test_reftable_stack__log_normalize(void) { - int err = 0; struct reftable_write_options opts = { 0, }; @@ -719,28 +693,26 @@ static void t_reftable_stack_log_normalize(void) .update_index = 1, }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); input.value.update.message = (char *) "one\ntwo"; - err = reftable_stack_add(st, write_test_log, &arg); - check_int(err, ==, REFTABLE_API_ERROR); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), REFTABLE_API_ERROR); input.value.update.message = (char *) "one"; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); - - err = reftable_stack_read_log(st, input.refname, &dest); - check(!err); - check_str(dest.value.update.message, "one\n"); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); + cl_assert_equal_i(reftable_stack_read_log(st, input.refname, + &dest), 0); + cl_assert_equal_s(dest.value.update.message, "one\n"); input.value.update.message = (char *) "two\n"; arg.update_index = 2; - err = reftable_stack_add(st, write_test_log, &arg); - check(!err); - err = reftable_stack_read_log(st, input.refname, &dest); - check(!err); - check_str(dest.value.update.message, "two\n"); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); + cl_assert_equal_i(reftable_stack_read_log(st, input.refname, + &dest), 0); + cl_assert_equal_s(dest.value.update.message, "two\n"); /* cleanup */ reftable_stack_destroy(st); @@ -748,20 +720,18 @@ static void t_reftable_stack_log_normalize(void) clear_dir(dir); } -static void t_reftable_stack_tombstone(void) +void test_reftable_stack__tombstone(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record refs[2] = { 0 }; struct reftable_log_record logs[2] = { 0 }; size_t i, N = ARRAY_SIZE(refs); struct reftable_ref_record dest = { 0 }; struct reftable_log_record log_dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); /* even entries add the refs, odd entries delete them. */ for (i = 0; i < N; i++) { @@ -770,8 +740,8 @@ static void t_reftable_stack_tombstone(void) refs[i].update_index = i + 1; if (i % 2 == 0) { refs[i].value_type = REFTABLE_REF_VAL1; - t_reftable_set_hash(refs[i].value.val1, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(refs[i].value.val1, i, + REFTABLE_HASH_SHA1); } logs[i].refname = xstrdup(buf); @@ -783,42 +753,37 @@ static void t_reftable_stack_tombstone(void) logs[i].update_index = 1; if (i % 2 == 0) { logs[i].value_type = REFTABLE_LOG_UPDATE; - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); logs[i].value.update.email = xstrdup("identity@invalid"); } } - for (i = 0; i < N; i++) { - int err = reftable_stack_add(st, write_test_ref, &refs[i]); - check(!err); - } + for (i = 0; i < N; i++) + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &refs[i], 0), 0); for (i = 0; i < N; i++) { struct write_log_arg arg = { .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); } - err = reftable_stack_read_ref(st, "branch", &dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_read_ref(st, "branch", + &dest), 1); reftable_ref_record_release(&dest); - err = reftable_stack_read_log(st, "branch", &log_dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_read_log(st, "branch", + &log_dest), 1); reftable_log_record_release(&log_dest); - err = reftable_stack_compact_all(st, NULL); - check(!err); - - err = reftable_stack_read_ref(st, "branch", &dest); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, "branch", &log_dest); - check_int(err, ==, 1); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); + cl_assert_equal_i(reftable_stack_read_ref(st, "branch", + &dest), 1); + cl_assert_equal_i(reftable_stack_read_log(st, "branch", + &log_dest), 1); reftable_ref_record_release(&dest); reftable_log_record_release(&log_dest); @@ -831,12 +796,11 @@ static void t_reftable_stack_tombstone(void) clear_dir(dir); } -static void t_reftable_stack_hash_id(void) +void test_reftable_stack__hash_id(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; struct reftable_ref_record ref = { .refname = (char *) "master", @@ -850,62 +814,57 @@ static void t_reftable_stack_hash_id(void) struct reftable_stack *st_default = NULL; struct reftable_ref_record dest = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref, 0), 0); /* can't read it with the wrong hash ID. */ - err = reftable_new_stack(&st32, dir, &opts32); - check_int(err, ==, REFTABLE_FORMAT_ERROR); + cl_assert_equal_i(reftable_new_stack(&st32, dir, + &opts32), REFTABLE_FORMAT_ERROR); /* check that we can read it back with default opts too. */ - err = reftable_new_stack(&st_default, dir, &opts_default); - check(!err); - - err = reftable_stack_read_ref(st_default, "master", &dest); - check(!err); - - check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); + cl_assert_equal_i(reftable_new_stack(&st_default, dir, + &opts_default), 0); + cl_assert_equal_i(reftable_stack_read_ref(st_default, "master", + &dest), 0); + cl_assert(reftable_ref_record_equal(&ref, &dest, + REFTABLE_HASH_SIZE_SHA1) != 0); reftable_ref_record_release(&dest); reftable_stack_destroy(st); reftable_stack_destroy(st_default); clear_dir(dir); } -static void t_suggest_compaction_segment(void) +void test_reftable_stack__suggest_compaction_segment(void) { uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 }; struct segment min = suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - check_int(min.start, ==, 1); - check_int(min.end, ==, 10); + cl_assert_equal_i(min.start, 1); + cl_assert_equal_i(min.end, 10); } -static void t_suggest_compaction_segment_nothing(void) +void test_reftable_stack__suggest_compaction_segment_nothing(void) { uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 }; struct segment result = suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2); - check_int(result.start, ==, result.end); + cl_assert_equal_i(result.start, result.end); } -static void t_reflog_expire(void) +void test_reftable_stack__reflog_expire(void) { char *dir = get_tmp_dir(__LINE__); struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; struct reftable_log_record logs[20] = { 0 }; size_t i, N = ARRAY_SIZE(logs) - 1; - int err; struct reftable_log_expiry_config expiry = { .time = 10, }; struct reftable_log_record log = { 0 }; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 1; i <= N; i++) { char buf[256]; @@ -916,8 +875,8 @@ static void t_reflog_expire(void) logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.time = i; logs[i].value.update.email = xstrdup("identity@invalid"); - t_reftable_set_hash(logs[i].value.update.new_hash, i, - REFTABLE_HASH_SHA1); + cl_reftable_set_hash(logs[i].value.update.new_hash, i, + REFTABLE_HASH_SHA1); } for (i = 1; i <= N; i++) { @@ -925,31 +884,23 @@ static void t_reflog_expire(void) .log = &logs[i], .update_index = reftable_stack_next_update_index(st), }; - int err = reftable_stack_add(st, write_test_log, &arg); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_log, + &arg, 0), 0); } - err = reftable_stack_compact_all(st, NULL); - check(!err); - - err = reftable_stack_compact_all(st, &expiry); - check(!err); - - err = reftable_stack_read_log(st, logs[9].refname, &log); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, logs[11].refname, &log); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, NULL), 0); + cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0); + cl_assert_equal_i(reftable_stack_read_log(st, logs[9].refname, + &log), 1); + cl_assert_equal_i(reftable_stack_read_log(st, logs[11].refname, + &log), 0); expiry.min_update_index = 15; - err = reftable_stack_compact_all(st, &expiry); - check(!err); - - err = reftable_stack_read_log(st, logs[14].refname, &log); - check_int(err, ==, 1); - - err = reftable_stack_read_log(st, logs[16].refname, &log); - check(!err); + cl_assert_equal_i(reftable_stack_compact_all(st, &expiry), 0); + cl_assert_equal_i(reftable_stack_read_log(st, logs[14].refname, + &log), 1); + cl_assert_equal_i(reftable_stack_read_log(st, logs[16].refname, + &log), 0); /* cleanup */ reftable_stack_destroy(st); @@ -961,26 +912,21 @@ static void t_reflog_expire(void) static int write_nothing(struct reftable_writer *wr, void *arg UNUSED) { - reftable_writer_set_limits(wr, 1, 1); + cl_assert_equal_i(reftable_writer_set_limits(wr, 1, 1), 0); return 0; } -static void t_empty_add(void) +void test_reftable_stack__empty_add(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; - int err; char *dir = get_tmp_dir(__LINE__); struct reftable_stack *st2 = NULL; - err = reftable_new_stack(&st, dir, &opts); - check(!err); - - err = reftable_stack_add(st, write_nothing, NULL); - check(!err); - - err = reftable_new_stack(&st2, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_add(st, write_nothing, + NULL, 0), 0); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); clear_dir(dir); reftable_stack_destroy(st); reftable_stack_destroy(st2); @@ -996,18 +942,17 @@ static int fastlogN(uint64_t sz, uint64_t N) return l - 1; } -static void t_reftable_stack_auto_compaction(void) +void test_reftable_stack__auto_compaction(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t i, N = 100; + int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i < N; i++) { char name[100]; @@ -1019,33 +964,32 @@ static void t_reftable_stack_auto_compaction(void) }; snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + err = reftable_stack_add(st, write_test_ref, &ref, 0); + cl_assert(!err); err = reftable_stack_auto_compact(st); - check(!err); - check(i < 2 || st->merged->readers_len < 2 * fastlogN(i, 2)); + cl_assert(!err); + cl_assert(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2)); } - check_int(reftable_stack_compaction_stats(st)->entries_written, <, - (uint64_t)(N * fastlogN(N, 2))); + cl_assert(reftable_stack_compaction_stats(st)->entries_written < + (uint64_t)(N * fastlogN(N, 2))); reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_factor(void) +void test_reftable_stack__auto_compaction_factor(void) { struct reftable_write_options opts = { .auto_compaction_factor = 5, }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t N = 100; + int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (size_t i = 0; i < N; i++) { char name[20]; @@ -1056,17 +1000,17 @@ static void t_reftable_stack_auto_compaction_factor(void) }; xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i); - err = reftable_stack_add(st, &write_test_ref, &ref); - check(!err); + err = reftable_stack_add(st, &write_test_ref, &ref, 0); + cl_assert(!err); - check(i < 5 || st->merged->readers_len < 5 * fastlogN(i, 5)); + cl_assert(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5)); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_auto_compaction_with_locked_tables(void) +void test_reftable_stack__auto_compaction_with_locked_tables(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, @@ -1076,21 +1020,20 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 5); - check_int(st->merged->readers_len, ==, 5); + cl_assert_equal_i(st->merged->tables_len, 5); /* * Given that all tables we have written should be roughly the same * size, we expect that auto-compaction will want to compact all of the * tables. Locking any of the tables will keep it from doing so. */ - check(!reftable_buf_addstr(&buf, dir)); - check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[2]->name)); - check(!reftable_buf_addstr(&buf, ".lock")); + cl_assert(!reftable_buf_addstr(&buf, dir)); + cl_assert(!reftable_buf_addstr(&buf, "/")); + cl_assert(!reftable_buf_addstr(&buf, st->tables[2]->name)); + cl_assert(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); /* @@ -1100,25 +1043,23 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) * only compact the newest two tables. */ err = reftable_stack_auto_compact(st); - check(!err); - check_int(st->stats.failures, ==, 0); - check_int(st->merged->readers_len, ==, 4); + cl_assert(!err); + cl_assert_equal_i(st->stats.failures, 0); + cl_assert_equal_i(st->merged->tables_len, 4); reftable_stack_destroy(st); reftable_buf_release(&buf); clear_dir(dir); } -static void t_reftable_stack_add_performs_auto_compaction(void) +void test_reftable_stack__add_performs_auto_compaction(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - int err; size_t i, n = 20; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); for (i = 0; i <= n; i++) { struct reftable_ref_record ref = { @@ -1138,8 +1079,8 @@ static void t_reftable_stack_add_performs_auto_compaction(void) snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i); ref.refname = buf; - err = reftable_stack_add(st, write_test_ref, &ref); - check(!err); + cl_assert_equal_i(reftable_stack_add(st, write_test_ref, + &ref, 0), 0); /* * The stack length should grow continuously for all runs where @@ -1147,16 +1088,16 @@ static void t_reftable_stack_add_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + cl_assert_equal_i(st->merged->tables_len, i + 1); else - check_int(st->merged->readers_len, ==, 1); + cl_assert_equal_i(st->merged->tables_len, 1); } reftable_stack_destroy(st); clear_dir(dir); } -static void t_reftable_stack_compaction_with_locked_tables(void) +void test_reftable_stack__compaction_with_locked_tables(void) { struct reftable_write_options opts = { .disable_auto_compact = 1, @@ -1166,17 +1107,16 @@ static void t_reftable_stack_compaction_with_locked_tables(void) char *dir = get_tmp_dir(__LINE__); int err; - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 3); - check_int(st->merged->readers_len, ==, 3); + cl_assert_equal_i(st->merged->tables_len, 3); /* Lock one of the tables that we're about to compact. */ - check(!reftable_buf_addstr(&buf, dir)); - check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[1]->name)); - check(!reftable_buf_addstr(&buf, ".lock")); + cl_assert(!reftable_buf_addstr(&buf, dir)); + cl_assert(!reftable_buf_addstr(&buf, "/")); + cl_assert(!reftable_buf_addstr(&buf, st->tables[1]->name)); + cl_assert(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); /* @@ -1184,74 +1124,61 @@ static void t_reftable_stack_compaction_with_locked_tables(void) * compact all tables. */ err = reftable_stack_compact_all(st, NULL); - check_int(err, ==, REFTABLE_LOCK_ERROR); - check_int(st->stats.failures, ==, 1); - check_int(st->merged->readers_len, ==, 3); + cl_assert_equal_i(err, REFTABLE_LOCK_ERROR); + cl_assert_equal_i(st->stats.failures, 1); + cl_assert_equal_i(st->merged->tables_len, 3); reftable_stack_destroy(st); reftable_buf_release(&buf); clear_dir(dir); } -static void t_reftable_stack_compaction_concurrent(void) +void test_reftable_stack__compaction_concurrent(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 3); - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_compact_all(st1, NULL); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0); reftable_stack_destroy(st1); reftable_stack_destroy(st2); - check_int(count_dir_entries(dir), ==, 2); + cl_assert_equal_i(count_dir_entries(dir), 2); clear_dir(dir); } static void unclean_stack_close(struct reftable_stack *st) { /* break abstraction boundary to simulate unclean shutdown. */ - for (size_t i = 0; i < st->readers_len; i++) - reftable_reader_decref(st->readers[i]); - st->readers_len = 0; - REFTABLE_FREE_AND_NULL(st->readers); + for (size_t i = 0; i < st->tables_len; i++) + reftable_table_decref(st->tables[i]); + st->tables_len = 0; + REFTABLE_FREE_AND_NULL(st->tables); } -static void t_reftable_stack_compaction_concurrent_clean(void) +void test_reftable_stack__compaction_concurrent_clean(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL; char *dir = get_tmp_dir(__LINE__); - int err; - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 3); - err = reftable_new_stack(&st2, dir, &opts); - check(!err); - - err = reftable_stack_compact_all(st1, NULL); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st2, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_compact_all(st1, NULL), 0); unclean_stack_close(st1); unclean_stack_close(st2); - err = reftable_new_stack(&st3, dir, &opts); - check(!err); - - err = reftable_stack_clean(st3); - check(!err); - check_int(count_dir_entries(dir), ==, 2); + cl_assert_equal_i(reftable_new_stack(&st3, dir, &opts), 0); + cl_assert_equal_i(reftable_stack_clean(st3), 0); + cl_assert_equal_i(count_dir_entries(dir), 2); reftable_stack_destroy(st1); reftable_stack_destroy(st2); @@ -1260,7 +1187,7 @@ static void t_reftable_stack_compaction_concurrent_clean(void) clear_dir(dir); } -static void t_reftable_stack_read_across_reload(void) +void test_reftable_stack__read_across_reload(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st1 = NULL, *st2 = NULL; @@ -1270,37 +1197,35 @@ static void t_reftable_stack_read_across_reload(void) int err; /* Create a first stack and set up an iterator for it. */ - err = reftable_new_stack(&st1, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st1, dir, &opts), 0); write_n_ref_tables(st1, 2); - check_int(st1->merged->readers_len, ==, 2); + cl_assert_equal_i(st1->merged->tables_len, 2); reftable_stack_init_ref_iterator(st1, &it); - err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0); /* Set up a second stack for the same directory and compact it. */ err = reftable_new_stack(&st2, dir, &opts); - check(!err); - check_int(st2->merged->readers_len, ==, 2); + cl_assert(!err); + cl_assert_equal_i(st2->merged->tables_len, 2); err = reftable_stack_compact_all(st2, NULL); - check(!err); - check_int(st2->merged->readers_len, ==, 1); + cl_assert(!err); + cl_assert_equal_i(st2->merged->tables_len, 1); /* * Verify that we can continue to use the old iterator even after we * have reloaded its stack. */ err = reftable_stack_reload(st1); - check(!err); - check_int(st1->merged->readers_len, ==, 1); + cl_assert(!err); + cl_assert_equal_i(st1->merged->tables_len, 1); err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0000"); + cl_assert(!err); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0000"); err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0001"); + cl_assert(!err); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0001"); err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert(err > 0); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); @@ -1309,7 +1234,7 @@ static void t_reftable_stack_read_across_reload(void) clear_dir(dir); } -static void t_reftable_stack_reload_with_missing_table(void) +void test_reftable_stack__reload_with_missing_table(void) { struct reftable_write_options opts = { 0 }; struct reftable_stack *st = NULL; @@ -1320,46 +1245,40 @@ static void t_reftable_stack_reload_with_missing_table(void) int err; /* Create a first stack and set up an iterator for it. */ - err = reftable_new_stack(&st, dir, &opts); - check(!err); + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); write_n_ref_tables(st, 2); - check_int(st->merged->readers_len, ==, 2); + cl_assert_equal_i(st->merged->tables_len, 2); reftable_stack_init_ref_iterator(st, &it); - err = reftable_iterator_seek_ref(&it, ""); - check(!err); + cl_assert_equal_i(reftable_iterator_seek_ref(&it, ""), 0); /* * Update the tables.list file with some garbage data, while reusing - * our old readers. This should trigger a partial reload of the stack, - * where we try to reuse our old readers. + * our old tables. This should trigger a partial reload of the stack, + * where we try to reuse our old tables. */ - check(!reftable_buf_addstr(&content, st->readers[0]->name)); - check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, st->readers[1]->name)); - check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, "garbage\n")); - check(!reftable_buf_addstr(&table_path, st->list_file)); - check(!reftable_buf_addstr(&table_path, ".lock")); + cl_assert(!reftable_buf_addstr(&content, st->tables[0]->name)); + cl_assert(!reftable_buf_addstr(&content, "\n")); + cl_assert(!reftable_buf_addstr(&content, st->tables[1]->name)); + cl_assert(!reftable_buf_addstr(&content, "\n")); + cl_assert(!reftable_buf_addstr(&content, "garbage\n")); + cl_assert(!reftable_buf_addstr(&table_path, st->list_file)); + cl_assert(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, content.buf, content.len); - err = rename(table_path.buf, st->list_file); - check(!err); + cl_assert_equal_i(rename(table_path.buf, st->list_file), 0); err = reftable_stack_reload(st); - check_int(err, ==, -4); - check_int(st->merged->readers_len, ==, 2); + cl_assert_equal_i(err, -4); + cl_assert_equal_i(st->merged->tables_len, 2); /* * Even though the reload has failed, we should be able to continue * using the iterator. */ - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0000"); - err = reftable_iterator_next_ref(&it, &rec); - check(!err); - check_str(rec.refname, "refs/heads/branch-0001"); - err = reftable_iterator_next_ref(&it, &rec); - check_int(err, >, 0); + cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0000"); + cl_assert_equal_i(reftable_iterator_next_ref(&it, &rec), 0); + cl_assert_equal_s(rec.refname, "refs/heads/branch-0001"); + cl_assert(reftable_iterator_next_ref(&it, &rec) > 0); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); @@ -1369,35 +1288,45 @@ static void t_reftable_stack_reload_with_missing_table(void) clear_dir(dir); } -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +static int write_limits_after_ref(struct reftable_writer *wr, void *arg) +{ + struct reftable_ref_record *ref = arg; + cl_assert_equal_i(reftable_writer_set_limits(wr, + ref->update_index, ref->update_index), 0); + cl_assert_equal_i(reftable_writer_add_ref(wr, ref), 0); + return reftable_writer_set_limits(wr, ref->update_index, ref->update_index); +} + +void test_reftable_stack__invalid_limit_updates(void) { - TEST(t_empty_add(), "empty addition to stack"); - TEST(t_read_file(), "read_lines works"); - TEST(t_reflog_expire(), "expire reflog entries"); - TEST(t_reftable_stack_add(), "add multiple refs and logs to stack"); - TEST(t_reftable_stack_add_one(), "add a single ref record to stack"); - TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction"); - TEST(t_reftable_stack_auto_compaction(), "stack must form geometric sequence after compaction"); - TEST(t_reftable_stack_auto_compaction_factor(), "auto-compaction with non-default geometric factor"); - TEST(t_reftable_stack_auto_compaction_fails_gracefully(), "failure on auto-compaction"); - TEST(t_reftable_stack_auto_compaction_with_locked_tables(), "auto compaction with locked tables"); - TEST(t_reftable_stack_compaction_concurrent(), "compaction with concurrent stack"); - TEST(t_reftable_stack_compaction_concurrent_clean(), "compaction with unclean stack shutdown"); - TEST(t_reftable_stack_compaction_with_locked_tables(), "compaction with locked tables"); - TEST(t_reftable_stack_hash_id(), "read stack with wrong hash ID"); - TEST(t_reftable_stack_iterator(), "log and ref iterator for reftable stack"); - TEST(t_reftable_stack_lock_failure(), "stack addition with lockfile failure"); - TEST(t_reftable_stack_log_normalize(), "log messages should be normalized"); - TEST(t_reftable_stack_read_across_reload(), "stack iterators work across reloads"); - TEST(t_reftable_stack_reload_with_missing_table(), "stack iteration with garbage tables"); - TEST(t_reftable_stack_tombstone(), "'tombstone' refs in stack"); - TEST(t_reftable_stack_transaction_api(), "update transaction to stack"); - TEST(t_reftable_stack_transaction_with_reload(), "transaction with reload"); - TEST(t_reftable_stack_transaction_api_performs_auto_compaction(), "update transaction triggers auto-compaction"); - TEST(t_reftable_stack_update_index_check(), "update transactions with equal update indices"); - TEST(t_reftable_stack_uptodate(), "stack must be reloaded before ref update"); - TEST(t_suggest_compaction_segment(), "suggest_compaction_segment with basic input"); - TEST(t_suggest_compaction_segment_nothing(), "suggest_compaction_segment with pre-compacted input"); - - return test_done(); + struct reftable_ref_record ref = { + .refname = (char *) "HEAD", + .update_index = 1, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *) "master", + }; + struct reftable_write_options opts = { + .default_permissions = 0660, + }; + struct reftable_addition *add = NULL; + char *dir = get_tmp_dir(__LINE__); + struct reftable_stack *st = NULL; + + cl_assert_equal_i(reftable_new_stack(&st, dir, &opts), 0); + + reftable_addition_destroy(add); + + cl_assert_equal_i(reftable_stack_new_addition(&add, st, 0), 0); + + /* + * write_limits_after_ref also updates the update indexes after adding + * the record. This should cause an err to be returned, since the limits + * must be set at the start. + */ + cl_assert_equal_i(reftable_addition_add(add, + write_limits_after_ref, &ref), REFTABLE_API_ERROR); + + reftable_addition_destroy(add); + reftable_stack_destroy(st); + clear_dir(dir); } diff --git a/t/unit-tests/u-reftable-table.c b/t/unit-tests/u-reftable-table.c new file mode 100644 index 0000000000..14fae8b199 --- /dev/null +++ b/t/unit-tests/u-reftable-table.c @@ -0,0 +1,201 @@ +#include "unit-test.h" +#include "lib-reftable.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/iter.h" +#include "reftable/table.h" +#include "strbuf.h" + +void test_reftable_table__seek_once(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + cl_assert(!ret); + + reftable_table_init_ref_iterator(table, &it); + ret = reftable_iterator_seek_ref(&it, ""); + cl_assert(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + cl_assert(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], + REFTABLE_HASH_SIZE_SHA1); + cl_assert_equal_i(ret, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + cl_assert_equal_i(ret, 1); + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); +} + +void test_reftable_table__reseek(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + cl_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), + NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + cl_assert(!ret); + + reftable_table_init_ref_iterator(table, &it); + + for (size_t i = 0; i < 5; i++) { + ret = reftable_iterator_seek_ref(&it, ""); + cl_assert(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + cl_assert(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + cl_assert_equal_i(ret, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + cl_assert_equal_i(ret, 1); + } + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); +} + +void test_reftable_table__block_iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct reftable_table_iterator it = { 0 }; + struct reftable_ref_record *records; + const struct reftable_block *block; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct { + uint8_t block_type; + uint16_t header_off; + uint16_t restart_count; + uint16_t record_count; + } expected_blocks[] = { + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .header_off = 24, + .restart_count = 10, + .record_count = 158, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 2, + .record_count = 24, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_INDEX, + .restart_count = 1, + .record_count = 4, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_OBJ, + .restart_count = 1, + .record_count = 1, + }, + }; + const size_t nrecords = 500; + int ret; + + REFTABLE_CALLOC_ARRAY(records, nrecords); + for (size_t i = 0; i < nrecords; i++) { + records[i].value_type = REFTABLE_REF_VAL1; + records[i].refname = xstrfmt("refs/heads/branch-%03"PRIuMAX, + (uintmax_t) i); + } + + cl_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + cl_assert(!ret); + + ret = reftable_table_iterator_init(&it, table); + cl_assert(!ret); + + for (size_t i = 0; i < ARRAY_SIZE(expected_blocks); i++) { + struct reftable_iterator record_it = { 0 }; + struct reftable_record record = { + .type = expected_blocks[i].block_type, + }; + + ret = reftable_table_iterator_next(&it, &block); + cl_assert(!ret); + + cl_assert_equal_i(block->block_type, + expected_blocks[i].block_type); + cl_assert_equal_i(block->header_off, + expected_blocks[i].header_off); + cl_assert_equal_i(block->restart_count, + expected_blocks[i].restart_count); + + ret = reftable_block_init_iterator(block, &record_it); + cl_assert(!ret); + + for (size_t j = 0; ; j++) { + ret = iterator_next(&record_it, &record); + if (ret > 0) { + cl_assert_equal_i(j, + expected_blocks[i].record_count); + break; + } + cl_assert(!ret); + } + + reftable_iterator_destroy(&record_it); + reftable_record_release(&record); + } + + ret = reftable_table_iterator_next(&it, &block); + cl_assert_equal_i(ret, 1); + + for (size_t i = 0; i < nrecords; i++) + reftable_free(records[i].refname); + reftable_table_iterator_release(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + reftable_free(records); +} diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/u-reftable-tree.c index 79b175a45a..bcf9061071 100644 --- a/t/unit-tests/t-reftable-tree.c +++ b/t/unit-tests/u-reftable-tree.c @@ -6,7 +6,7 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "test-lib.h" +#include "unit-test.h" #include "reftable/tree.h" static int t_compare(const void *a, const void *b) @@ -25,7 +25,7 @@ static void store(void *arg, void *key) c->arr[c->len++] = key; } -static void t_tree_search(void) +void test_reftable_tree__tree_search(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; @@ -38,20 +38,20 @@ static void t_tree_search(void) */ do { nodes[i] = tree_insert(&root, &values[i], &t_compare); - check(nodes[i] != NULL); + cl_assert(nodes[i] != NULL); i = (i * 7) % 11; } while (i != 1); for (i = 1; i < ARRAY_SIZE(nodes); i++) { - check_pointer_eq(&values[i], nodes[i]->key); - check_pointer_eq(nodes[i], tree_search(root, &values[i], &t_compare)); + cl_assert_equal_p(&values[i], nodes[i]->key); + cl_assert_equal_p(nodes[i], tree_search(root, &values[i], &t_compare)); } - check(!tree_search(root, values, t_compare)); + cl_assert(tree_search(root, values, t_compare) == NULL); tree_free(root); } -static void t_infix_walk(void) +void test_reftable_tree__infix_walk(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; @@ -64,23 +64,15 @@ static void t_infix_walk(void) do { struct tree_node *node = tree_insert(&root, &values[i], t_compare); - check(node != NULL); + cl_assert(node != NULL); i = (i * 7) % 11; count++; } while (i != 1); infix_walk(root, &store, &c); for (i = 1; i < ARRAY_SIZE(values); i++) - check_pointer_eq(&values[i], out[i - 1]); - check(!out[i - 1]); - check_int(c.len, ==, count); + cl_assert_equal_p(&values[i], out[i - 1]); + cl_assert(out[i - 1] == NULL); + cl_assert_equal_i(c.len, count); tree_free(root); } - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_tree_search(), "tree_search works"); - TEST(t_infix_walk(), "infix_walk works"); - - return test_done(); -} diff --git a/t/unit-tests/u-strbuf.c b/t/unit-tests/u-strbuf.c new file mode 100644 index 0000000000..caa5d78aa3 --- /dev/null +++ b/t/unit-tests/u-strbuf.c @@ -0,0 +1,119 @@ +#include "unit-test.h" +#include "strbuf.h" + +/* wrapper that supplies tests with an empty, initialized strbuf */ +static void setup(void (*f)(struct strbuf*, const void*), + const void *data) +{ + struct strbuf buf = STRBUF_INIT; + + f(&buf, data); + strbuf_release(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); +} + +/* wrapper that supplies tests with a populated, initialized strbuf */ +static void setup_populated(void (*f)(struct strbuf*, const void*), + const char *init_str, const void *data) +{ + struct strbuf buf = STRBUF_INIT; + + strbuf_addstr(&buf, init_str); + cl_assert_equal_i(buf.len, strlen(init_str)); + f(&buf, data); + strbuf_release(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); +} + +static void assert_sane_strbuf(struct strbuf *buf) +{ + /* Initialized strbufs should always have a non-NULL buffer */ + cl_assert(buf->buf != NULL); + /* Buffers should always be NUL-terminated */ + cl_assert(buf->buf[buf->len] == '\0'); + /* + * In case the buffer contains anything, `alloc` must alloc must + * be at least one byte larger than `len`. + */ + if (buf->len) + cl_assert(buf->len < buf->alloc); +} + +void test_strbuf__static_init(void) +{ + struct strbuf buf = STRBUF_INIT; + + cl_assert_equal_i(buf.len, 0); + cl_assert_equal_i(buf.alloc, 0); + cl_assert(buf.buf[0] == '\0'); +} + +void test_strbuf__dynamic_init(void) +{ + struct strbuf buf; + + strbuf_init(&buf, 1024); + assert_sane_strbuf(&buf); + cl_assert_equal_i(buf.len, 0); + cl_assert(buf.alloc >= 1024); + cl_assert(buf.buf[0] == '\0'); + strbuf_release(&buf); +} + +static void t_addch(struct strbuf *buf, const void *data) +{ + const char *p_ch = data; + const char ch = *p_ch; + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + assert_sane_strbuf(buf); + strbuf_addch(buf, ch); + assert_sane_strbuf(buf); + cl_assert_equal_i(buf->len, orig_len + 1); + cl_assert(buf->alloc >= orig_alloc); + cl_assert(buf->buf[buf->len] == '\0'); +} + +static void t_addstr(struct strbuf *buf, const void *data) +{ + const char *text = data; + size_t len = strlen(text); + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + assert_sane_strbuf(buf); + strbuf_addstr(buf, text); + assert_sane_strbuf(buf); + cl_assert_equal_i(buf->len, orig_len + len); + cl_assert(buf->alloc >= orig_alloc); + cl_assert(buf->buf[buf->len] == '\0'); + cl_assert_equal_s(buf->buf + orig_len, text); +} + +void test_strbuf__add_single_char(void) +{ + setup(t_addch, "a"); +} + +void test_strbuf__add_empty_char(void) +{ + setup(t_addch, ""); +} + +void test_strbuf__add_append_char(void) +{ + setup_populated(t_addch, "initial value", "a"); +} + +void test_strbuf__add_single_str(void) +{ + setup(t_addstr, "hello there"); +} + +void test_strbuf__add_append_str(void) +{ + setup_populated(t_addstr, "initial value", "hello there"); +} diff --git a/t/unit-tests/u-strcmp-offset.c b/t/unit-tests/u-strcmp-offset.c new file mode 100644 index 0000000000..7e8e9acf3c --- /dev/null +++ b/t/unit-tests/u-strcmp-offset.c @@ -0,0 +1,45 @@ +#include "unit-test.h" +#include "read-cache-ll.h" + +static void check_strcmp_offset(const char *string1, const char *string2, + int expect_result, uintmax_t expect_offset) +{ + size_t offset; + int result = strcmp_offset(string1, string2, &offset); + + /* + * Because different CRTs behave differently, only rely on signs of the + * result values. + */ + result = (result < 0 ? -1 : + result > 0 ? 1 : + 0); + + cl_assert_equal_i(result, expect_result); + cl_assert_equal_i((uintmax_t)offset, expect_offset); +} + +void test_strcmp_offset__empty(void) +{ + check_strcmp_offset("", "", 0, 0); +} + +void test_strcmp_offset__equal(void) +{ + check_strcmp_offset("abc", "abc", 0, 3); +} + +void test_strcmp_offset__different(void) +{ + check_strcmp_offset("abc", "def", -1, 0); +} + +void test_strcmp_offset__mismatch(void) +{ + check_strcmp_offset("abc", "abz", -1, 2); +} + +void test_strcmp_offset__different_length(void) +{ + check_strcmp_offset("abc", "abcdef", -1, 3); +} diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c new file mode 100644 index 0000000000..a2457d7b1e --- /dev/null +++ b/t/unit-tests/u-string-list.c @@ -0,0 +1,306 @@ +#include "unit-test.h" +#include "string-list.h" + +static void t_vcreate_string_list_dup(struct string_list *list, + int free_util, va_list ap) +{ + const char *arg; + + cl_assert(list->strdup_strings); + + string_list_clear(list, free_util); + while ((arg = va_arg(ap, const char *))) + string_list_append(list, arg); +} + +static void t_create_string_list_dup(struct string_list *list, int free_util, ...) +{ + va_list ap; + + cl_assert(list->strdup_strings); + + string_list_clear(list, free_util); + va_start(ap, free_util); + t_vcreate_string_list_dup(list, free_util, ap); + va_end(ap); +} + +static void t_string_list_clear(struct string_list *list, int free_util) +{ + string_list_clear(list, free_util); + cl_assert_equal_p(list->items, NULL); + cl_assert_equal_i(list->nr, 0); + cl_assert_equal_i(list->alloc, 0); +} + +static void t_string_list_equal(struct string_list *list, + struct string_list *expected_strings) +{ + cl_assert_equal_i(list->nr, expected_strings->nr); + cl_assert(list->nr <= list->alloc); + for (size_t i = 0; i < expected_strings->nr; i++) + cl_assert_equal_s(list->items[i].string, + expected_strings->items[i].string); +} + +static void t_string_list_split(const char *data, const char *delim, int maxsplit, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_DUP; + va_list ap; + int len; + + va_start(ap, maxsplit); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split(&list, data, delim, maxsplit); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +static void t_string_list_split_f(const char *data, const char *delim, + int maxsplit, unsigned flags, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_DUP; + va_list ap; + int len; + + va_start(ap, flags); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split_f(&list, data, delim, maxsplit, flags); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +void test_string_list__split_f(void) +{ + t_string_list_split_f("::foo:bar:baz:", ":", -1, 0, + "", "", "foo", "bar", "baz", "", NULL); + t_string_list_split_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM, + "foo", "bar", "baz", NULL); + t_string_list_split_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM, + "a", "b c", NULL); + t_string_list_split_f("::foo::bar:baz:", ":", -1, STRING_LIST_SPLIT_NONEMPTY, + "foo", "bar", "baz", NULL); + t_string_list_split_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY, + "foo", "baz", NULL); + t_string_list_split_f("foo :: : baz", ":", -1, + STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM, + "foo", "baz", NULL); +} + +static void t_string_list_split_in_place_f(const char *data_, const char *delim, + int maxsplit, unsigned flags, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_NODUP; + char *data = xstrdup(data_); + va_list ap; + int len; + + va_start(ap, flags); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split_in_place_f(&list, data, delim, maxsplit, flags); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + free(data); + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +void test_string_list__split_in_place_f(void) +{ + t_string_list_split_in_place_f("::foo:bar:baz:", ":", -1, 0, + "", "", "foo", "bar", "baz", "", NULL); + t_string_list_split_in_place_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM, + "foo", "bar", "baz", NULL); + t_string_list_split_in_place_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM, + "a", "b c", NULL); + t_string_list_split_in_place_f("::foo::bar:baz:", ":", -1, + STRING_LIST_SPLIT_NONEMPTY, + "foo", "bar", "baz", NULL); + t_string_list_split_in_place_f("foo:baz", ":", -1, STRING_LIST_SPLIT_NONEMPTY, + "foo", "baz", NULL); + t_string_list_split_in_place_f("foo :: : baz", ":", -1, + STRING_LIST_SPLIT_NONEMPTY | STRING_LIST_SPLIT_TRIM, + "foo", "baz", NULL); +} + +void test_string_list__split(void) +{ + t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL); + t_string_list_split("foo:bar:baz", ":", 0, "foo:bar:baz", NULL); + t_string_list_split("foo:bar:baz", ":", 1, "foo", "bar:baz", NULL); + t_string_list_split("foo:bar:baz", ":", 2, "foo", "bar", "baz", NULL); + t_string_list_split("foo:bar:", ":", -1, "foo", "bar", "", NULL); + t_string_list_split("", ":", -1, "", NULL); + t_string_list_split(":", ":", -1, "", "", NULL); +} + +static void t_string_list_split_in_place(const char *data, const char *delim, + int maxsplit, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + struct string_list list = STRING_LIST_INIT_NODUP; + char *string = xstrdup(data); + va_list ap; + int len; + + va_start(ap, maxsplit); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_clear(&list, 0); + len = string_list_split_in_place(&list, string, delim, maxsplit); + cl_assert_equal_i(len, expected_strings.nr); + t_string_list_equal(&list, &expected_strings); + + free(string); + string_list_clear(&expected_strings, 0); + string_list_clear(&list, 0); +} + +void test_string_list__split_in_place(void) +{ + t_string_list_split_in_place("foo:;:bar:;:baz:;:", ":;", -1, + "foo", "", "", "bar", "", "", "baz", "", "", "", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 0, + "foo:;:bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 1, + "foo", ";:bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 2, + "foo", "", ":bar:;:baz", NULL); + t_string_list_split_in_place("foo:;:bar:;:", ":;", -1, + "foo", "", "", "bar", "", "", "", NULL); +} + +static int prefix_cb(struct string_list_item *item, void *cb_data) +{ + const char *prefix = (const char *)cb_data; + return starts_with(item->string, prefix); +} + +static void t_string_list_filter(struct string_list *list, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + const char *prefix = "y"; + va_list ap; + + va_start(ap, list); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + filter_string_list(list, 0, prefix_cb, (void *)prefix); + t_string_list_equal(list, &expected_strings); + + string_list_clear(&expected_strings, 0); +} + +void test_string_list__filter(void) +{ + struct string_list list = STRING_LIST_INIT_DUP; + + t_create_string_list_dup(&list, 0, NULL); + t_string_list_filter(&list, NULL); + + t_create_string_list_dup(&list, 0, "no", NULL); + t_string_list_filter(&list, NULL); + + t_create_string_list_dup(&list, 0, "yes", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "no", "yes", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "yes", "no", NULL); + t_string_list_filter(&list, "yes", NULL); + + t_create_string_list_dup(&list, 0, "y1", "y2", NULL); + t_string_list_filter(&list, "y1", "y2", NULL); + + t_create_string_list_dup(&list, 0, "y2", "y1", NULL); + t_string_list_filter(&list, "y2", "y1", NULL); + + t_create_string_list_dup(&list, 0, "x1", "x2", NULL); + t_string_list_filter(&list, NULL); + + t_string_list_clear(&list, 0); +} + +static void t_string_list_remove_duplicates(struct string_list *list, ...) +{ + struct string_list expected_strings = STRING_LIST_INIT_DUP; + va_list ap; + + va_start(ap, list); + t_vcreate_string_list_dup(&expected_strings, 0, ap); + va_end(ap); + + string_list_remove_duplicates(list, 0); + t_string_list_equal(list, &expected_strings); + + string_list_clear(&expected_strings, 0); +} + +void test_string_list__remove_duplicates(void) +{ + struct string_list list = STRING_LIST_INIT_DUP; + + t_create_string_list_dup(&list, 0, NULL); + t_string_list_remove_duplicates(&list, NULL); + + t_create_string_list_dup(&list, 0, "", NULL); + t_string_list_remove_duplicates(&list, "", NULL); + + t_create_string_list_dup(&list, 0, "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "a", NULL); + t_string_list_remove_duplicates(&list, "a", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", NULL); + t_string_list_remove_duplicates(&list, "a", "b", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "b", NULL); + t_string_list_remove_duplicates(&list, "a", "b", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "b", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "b", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "b", "b", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_create_string_list_dup(&list, 0, "a", "a", "a", "b", "b", "b", + "c", "c", "c", NULL); + t_string_list_remove_duplicates(&list, "a", "b", "c", NULL); + + t_string_list_clear(&list, 0); +} diff --git a/t/unit-tests/u-trailer.c b/t/unit-tests/u-trailer.c new file mode 100644 index 0000000000..3d60ea1603 --- /dev/null +++ b/t/unit-tests/u-trailer.c @@ -0,0 +1,320 @@ +#define DISABLE_SIGN_COMPARE_WARNINGS + +#include "unit-test.h" +#include "trailer.h" + +struct contents { + const char *raw; + const char *key; + const char *val; +}; + +static void t_trailer_iterator(const char *msg, size_t num_expected, + struct contents *contents) +{ + struct trailer_iterator iter; + size_t i = 0; + + trailer_iterator_init(&iter, msg); + while (trailer_iterator_advance(&iter)) { + if (num_expected) { + cl_assert_equal_s(iter.raw, contents[i].raw); + cl_assert_equal_s(iter.key.buf, contents[i].key); + cl_assert_equal_s(iter.val.buf, contents[i].val); + } + i++; + } + trailer_iterator_release(&iter); + + cl_assert_equal_i(i, num_expected); +} + +void test_trailer__empty_input(void) +{ + struct contents expected_contents[] = { 0 }; + t_trailer_iterator("", 0, expected_contents); +} + +void test_trailer__no_newline_start(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 0, + expected_contents); +} + +void test_trailer__newline_start(void) +{ + struct contents expected_contents[] = { + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 3, + expected_contents); +} + +void test_trailer__no_body_text(void) +{ + struct contents expected_contents[] = { + + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 3, + expected_contents); +} + +void test_trailer__body_text_no_divider(void) +{ + struct contents expected_contents[] = { + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n" + "Signed-off-by: x\n", + 4, + expected_contents); +} + +void test_trailer__body_no_divider_2nd_block(void) +{ + struct contents expected_contents[] = { + { + .raw = "Helped-by: x\n", + .key = "Helped-by", + .val = "x", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n" + "Signed-off-by: x\n" + "\n" + /* + * Because this is the last trailer block, it takes + * precedence over the first one encountered above. + */ + "Helped-by: x\n" + "Signed-off-by: x\n", + 2, + expected_contents); +} + +void test_trailer__body_and_divider(void) +{ + struct contents expected_contents[] = { + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "---\n" + "\n" + /* + * This trailer still counts because the iterator + * always ignores the divider. + */ + "Signed-off-by: x\n", + 1, + expected_contents); +} + +void test_trailer__non_trailer_in_block(void) +{ + struct contents expected_contents[] = { + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * Even though this trailer block has a non-trailer line + * in it, it's still a valid trailer block because it's + * at least 25% trailers and is Git-generated (see + * git_generated_prefixes[] in trailer.c). + */ + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "Signed-off-by: x\n", + /* + * Even though there is only really 1 real "trailer" + * (Signed-off-by), we still have 4 trailer objects + * because we still want to iterate through the entire + * block. + */ + 4, + expected_contents); +} + +void test_trailer__too_many_non_trailers(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * This block has only 20% trailers, so it's below the + * 25% threshold. + */ + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "Signed-off-by: x\n", + 0, + expected_contents); +} + +void test_trailer__one_non_trailer_no_git_trailers(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * This block has only 1 non-trailer out of 10 (IOW, 90% + * trailers) but is not considered a trailer block + * because the 25% threshold only applies to cases where + * there was a Git-generated trailer. + */ + "Reviewed-by: x\n" + "Reviewed-by: x\n" + "Reviewed-by: x\n" + "Helped-by: x\n" + "Helped-by: x\n" + "Helped-by: x\n" + "Acked-by: x\n" + "Acked-by: x\n" + "Acked-by: x\n" + "not a trailer line\n", + 0, + expected_contents); +} diff --git a/t/unit-tests/t-urlmatch-normalization.c b/t/unit-tests/u-urlmatch-normalization.c index 1769c357b9..39f6e1ba26 100644 --- a/t/unit-tests/t-urlmatch-normalization.c +++ b/t/unit-tests/u-urlmatch-normalization.c @@ -1,12 +1,11 @@ -#include "test-lib.h" +#include "unit-test.h" #include "urlmatch.h" static void check_url_normalizable(const char *url, unsigned int normalizable) { char *url_norm = url_normalize(url, NULL); - if (!check_int(normalizable, ==, url_norm ? 1 : 0)) - test_msg("input url: %s", url); + cl_assert_equal_i(normalizable, url_norm ? 1 : 0); free(url_norm); } @@ -14,8 +13,7 @@ static void check_normalized_url(const char *url, const char *expect) { char *url_norm = url_normalize(url, NULL); - if (!check_str(url_norm, expect)) - test_msg("input url: %s", url); + cl_assert_equal_s(url_norm, expect); free(url_norm); } @@ -26,13 +24,9 @@ static void compare_normalized_urls(const char *url1, const char *url2, char *url2_norm = url_normalize(url2, NULL); if (equal) { - if (!check_str(url1_norm, url2_norm)) - test_msg("input url1: %s\n input url2: %s", url1, - url2); - } else if (!check_int(strcmp(url1_norm, url2_norm), !=, 0)) { - test_msg(" normalized url1: %s\n normalized url2: %s\n" - " input url1: %s\n input url2: %s", - url1_norm, url2_norm, url1, url2); + cl_assert_equal_s(url1_norm, url2_norm); + } else { + cl_assert(strcmp(url1_norm, url2_norm) != 0); } free(url1_norm); free(url2_norm); @@ -43,14 +37,12 @@ static void check_normalized_url_length(const char *url, size_t len) struct url_info info; char *url_norm = url_normalize(url, &info); - if (!check_int(info.url_len, ==, len)) - test_msg(" input url: %s\n normalized url: %s", url, - url_norm); + cl_assert_equal_i(info.url_len, len); free(url_norm); } /* Note that only "file:" URLs should be allowed without a host */ -static void t_url_scheme(void) +void test_urlmatch_normalization__scheme(void) { check_url_normalizable("", 0); check_url_normalizable("_", 0); @@ -73,7 +65,7 @@ static void t_url_scheme(void) check_normalized_url("AbCdeF://x.Y", "abcdef://x.y/"); } -static void t_url_authority(void) +void test_urlmatch_normalization__authority(void) { check_url_normalizable("scheme://user:pass@", 0); check_url_normalizable("scheme://?", 0); @@ -109,7 +101,7 @@ static void t_url_authority(void) check_url_normalizable("scheme://invalid....:[", 0); } -static void t_url_port(void) +void test_urlmatch_normalization__port(void) { check_url_normalizable("xyz://q@some.host:", 1); check_url_normalizable("xyz://q@some.host:456/", 1); @@ -139,7 +131,7 @@ static void t_url_port(void) check_url_normalizable("xyz://[::1]:030f/", 0); } -static void t_url_port_normalization(void) +void test_urlmatch_normalization__port_normalization(void) { check_normalized_url("http://x:800", "http://x:800/"); check_normalized_url("http://x:0800", "http://x:800/"); @@ -154,7 +146,7 @@ static void t_url_port_normalization(void) check_normalized_url("https://x:000000443", "https://x/"); } -static void t_url_general_escape(void) +void test_urlmatch_normalization__general_escape(void) { check_url_normalizable("http://x.y?%fg", 0); check_normalized_url("X://W/%7e%41^%3a", "x://w/~A%5E%3A"); @@ -164,7 +156,7 @@ static void t_url_general_escape(void) check_normalized_url("X://W?!", "x://w/?!"); } -static void t_url_high_bit(void) +void test_urlmatch_normalization__high_bit(void) { check_normalized_url( "x://q/\x01\x02\x03\x04\x05\x06\x07\x08\x0e\x0f\x10\x11\x12", @@ -198,26 +190,26 @@ static void t_url_high_bit(void) "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"); } -static void t_url_utf8_escape(void) +void test_urlmatch_normalization__utf8_escape(void) { check_normalized_url( "x://q/\xc2\x80\xdf\xbf\xe0\xa0\x80\xef\xbf\xbd\xf0\x90\x80\x80\xf0\xaf\xbf\xbd", "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"); } -static void t_url_username_pass(void) +void test_urlmatch_normalization__username_pass(void) { check_normalized_url("x://%41%62(^):%70+d@foo", "x://Ab(%5E):p+d@foo/"); } -static void t_url_length(void) +void test_urlmatch_normalization__length(void) { check_normalized_url_length("Http://%4d%65:%4d^%70@The.Host", 25); check_normalized_url_length("http://%41:%42@x.y/%61/", 17); check_normalized_url_length("http://@x.y/^", 15); } -static void t_url_dots(void) +void test_urlmatch_normalization__dots(void) { check_normalized_url("x://y/.", "x://y/"); check_normalized_url("x://y/./", "x://y/"); @@ -244,7 +236,7 @@ static void t_url_dots(void) * "http://foo" specifies neither a user name nor a password. * So they should not be equivalent. */ -static void t_url_equivalents(void) +void test_urlmatch_normalization__equivalents(void) { compare_normalized_urls("httP://x", "Http://X/", 1); compare_normalized_urls("Http://%4d%65:%4d^%70@The.Host", "hTTP://Me:%4D^p@the.HOST:80/", 1); @@ -253,19 +245,3 @@ static void t_url_equivalents(void) compare_normalized_urls("https://@x.y/^/../abc", "httpS://@x.y:0443/abc", 1); compare_normalized_urls("https://@x.y/^/..", "httpS://@x.y:0443/", 1); } - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(t_url_scheme(), "url scheme"); - TEST(t_url_authority(), "url authority"); - TEST(t_url_port(), "url port checks"); - TEST(t_url_port_normalization(), "url port normalization"); - TEST(t_url_general_escape(), "url general escapes"); - TEST(t_url_high_bit(), "url high-bit escapes"); - TEST(t_url_utf8_escape(), "url utf8 escapes"); - TEST(t_url_username_pass(), "url username/password escapes"); - TEST(t_url_length(), "url normalized lengths"); - TEST(t_url_dots(), "url . and .. segments"); - TEST(t_url_equivalents(), "url equivalents"); - return test_done(); -} diff --git a/t/unit-tests/unit-test.c b/t/unit-tests/unit-test.c index fa8818842a..5af645048a 100644 --- a/t/unit-tests/unit-test.c +++ b/t/unit-tests/unit-test.c @@ -1,5 +1,7 @@ #include "unit-test.h" +#include "hex.h" #include "parse-options.h" +#include "strbuf.h" #include "string-list.h" #include "strvec.h" diff --git a/t/unit-tests/unit-test.h b/t/unit-tests/unit-test.h index 85e5d6a948..39a0b72a05 100644 --- a/t/unit-tests/unit-test.h +++ b/t/unit-tests/unit-test.h @@ -1,8 +1,13 @@ #include "git-compat-util.h" #include "clar/clar.h" -#include "clar-decls.h" #include "strbuf.h" +#ifndef GIT_CLAR_DECLS_H +# include "clar-decls.h" +#else +# include GIT_CLAR_DECLS_H +#endif + #define cl_failf(fmt, ...) do { \ char desc[4096]; \ snprintf(desc, sizeof(desc), fmt, __VA_ARGS__); \ |
