diff options
Diffstat (limited to 't/unit-tests')
| -rw-r--r-- | t/unit-tests/lib-oid.c | 32 | ||||
| -rw-r--r-- | t/unit-tests/lib-oid.h | 9 | ||||
| -rw-r--r-- | t/unit-tests/t-example-decorate.c | 74 | ||||
| -rw-r--r-- | t/unit-tests/t-oid-array.c | 126 | ||||
| -rw-r--r-- | t/unit-tests/t-oidmap.c | 181 | ||||
| -rw-r--r-- | t/unit-tests/t-oidtree.c | 122 | ||||
| -rw-r--r-- | t/unit-tests/t-reftable-stack.c | 54 | ||||
| -rw-r--r-- | t/unit-tests/t-strbuf.c | 122 | ||||
| -rw-r--r-- | t/unit-tests/t-strcmp-offset.c | 35 | ||||
| -rw-r--r-- | t/unit-tests/u-example-decorate.c | 64 | ||||
| -rw-r--r-- | t/unit-tests/u-hashmap.c (renamed from t/unit-tests/t-hashmap.c) | 226 | ||||
| -rw-r--r-- | t/unit-tests/u-oid-array.c | 129 | ||||
| -rw-r--r-- | t/unit-tests/u-oidmap.c | 136 | ||||
| -rw-r--r-- | t/unit-tests/u-oidtree.c | 107 | ||||
| -rw-r--r-- | t/unit-tests/u-strbuf.c | 119 | ||||
| -rw-r--r-- | t/unit-tests/u-strcmp-offset.c | 45 | ||||
| -rw-r--r-- | t/unit-tests/unit-test.c | 2 |
17 files changed, 782 insertions, 801 deletions
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/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-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-reftable-stack.c b/t/unit-tests/t-reftable-stack.c index aeec195b2b..c3f0059c34 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/t-reftable-stack.c @@ -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); + check(!reftable_writer_set_limits(wr, ref->update_index, + ref->update_index)); return reftable_writer_add_ref(wr, ref); } @@ -143,7 +144,8 @@ 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); + check(!reftable_writer_set_limits(wr, wla->update_index, + wla->update_index)); return reftable_writer_add_log(wr, wla->log); } @@ -961,7 +963,7 @@ static void t_reflog_expire(void) static int write_nothing(struct reftable_writer *wr, void *arg UNUSED) { - reftable_writer_set_limits(wr, 1, 1); + check(!reftable_writer_set_limits(wr, 1, 1)); return 0; } @@ -1369,11 +1371,57 @@ static void t_reftable_stack_reload_with_missing_table(void) clear_dir(dir); } +static int write_limits_after_ref(struct reftable_writer *wr, void *arg) +{ + struct reftable_ref_record *ref = arg; + check(!reftable_writer_set_limits(wr, ref->update_index, ref->update_index)); + check(!reftable_writer_add_ref(wr, ref)); + return reftable_writer_set_limits(wr, ref->update_index, ref->update_index); +} + +static void t_reftable_invalid_limit_updates(void) +{ + 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; + int err; + + err = reftable_new_stack(&st, dir, &opts); + check(!err); + + reftable_addition_destroy(add); + + err = reftable_stack_new_addition(&add, st, 0); + check(!err); + + /* + * 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. + */ + err = reftable_addition_add(add, write_limits_after_ref, &ref); + check_int(err, ==, REFTABLE_API_ERROR); + + reftable_addition_destroy(add); + reftable_stack_destroy(st); + clear_dir(dir); +} + int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { 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_invalid_limit_updates(), "prevent limit updates after adding records"); 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"); 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/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-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-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..dc805b7e3c --- /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_free(&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-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/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" |
