Merge branch 'sk/unit-test-oid'
Convert a few unit tests to the clar framework. * sk/unit-test-oid: t/unit-tests: convert oidtree test to use clar test framework t/unit-tests: convert oidmap test to use clar test framework t/unit-tests: convert oid-array test to use clar test framework t/unit-tests: implement clar specific oid helper functions
This commit is contained in:
8
Makefile
8
Makefile
@ -1356,6 +1356,9 @@ CLAR_TEST_SUITES += u-example-decorate
|
||||
CLAR_TEST_SUITES += u-hash
|
||||
CLAR_TEST_SUITES += u-hashmap
|
||||
CLAR_TEST_SUITES += u-mem-pool
|
||||
CLAR_TEST_SUITES += u-oid-array
|
||||
CLAR_TEST_SUITES += u-oidmap
|
||||
CLAR_TEST_SUITES += u-oidtree
|
||||
CLAR_TEST_SUITES += u-prio-queue
|
||||
CLAR_TEST_SUITES += u-reftable-tree
|
||||
CLAR_TEST_SUITES += u-strbuf
|
||||
@ -1365,10 +1368,8 @@ CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X)
|
||||
CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES))
|
||||
CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o
|
||||
CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o
|
||||
CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o
|
||||
|
||||
UNIT_TEST_PROGRAMS += t-oid-array
|
||||
UNIT_TEST_PROGRAMS += t-oidmap
|
||||
UNIT_TEST_PROGRAMS += t-oidtree
|
||||
UNIT_TEST_PROGRAMS += t-reftable-basics
|
||||
UNIT_TEST_PROGRAMS += t-reftable-block
|
||||
UNIT_TEST_PROGRAMS += t-reftable-merged
|
||||
@ -1381,7 +1382,6 @@ UNIT_TEST_PROGRAMS += t-trailer
|
||||
UNIT_TEST_PROGRAMS += t-urlmatch-normalization
|
||||
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
|
||||
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
|
||||
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o
|
||||
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o
|
||||
|
||||
# xdiff and reftable libs may in turn depend on what is in libgit.a
|
||||
|
@ -4,6 +4,9 @@ clar_test_suites = [
|
||||
'unit-tests/u-hash.c',
|
||||
'unit-tests/u-hashmap.c',
|
||||
'unit-tests/u-mem-pool.c',
|
||||
'unit-tests/u-oid-array.c',
|
||||
'unit-tests/u-oidmap.c',
|
||||
'unit-tests/u-oidtree.c',
|
||||
'unit-tests/u-prio-queue.c',
|
||||
'unit-tests/u-reftable-tree.c',
|
||||
'unit-tests/u-strbuf.c',
|
||||
@ -14,6 +17,7 @@ clar_test_suites = [
|
||||
clar_sources = [
|
||||
'unit-tests/clar/clar.c',
|
||||
'unit-tests/unit-test.c',
|
||||
'unit-tests/lib-oid.c'
|
||||
]
|
||||
|
||||
clar_decls_h = custom_target(
|
||||
@ -48,9 +52,6 @@ clar_unit_tests = executable('unit-tests',
|
||||
test('unit-tests', clar_unit_tests)
|
||||
|
||||
unit_test_programs = [
|
||||
'unit-tests/t-oid-array.c',
|
||||
'unit-tests/t-oidmap.c',
|
||||
'unit-tests/t-oidtree.c',
|
||||
'unit-tests/t-reftable-basics.c',
|
||||
'unit-tests/t-reftable-block.c',
|
||||
'unit-tests/t-reftable-merged.c',
|
||||
@ -68,7 +69,6 @@ foreach unit_test_program : unit_test_programs
|
||||
unit_test = executable(unit_test_name,
|
||||
sources: [
|
||||
'unit-tests/test-lib.c',
|
||||
'unit-tests/lib-oid.c',
|
||||
'unit-tests/lib-reftable.c',
|
||||
unit_test_program,
|
||||
],
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
129
t/unit-tests/u-oid-array.c
Normal file
129
t/unit-tests/u-oid-array.c
Normal file
@ -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);
|
||||
}
|
136
t/unit-tests/u-oidmap.c
Normal file
136
t/unit-tests/u-oidmap.c
Normal file
@ -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));
|
||||
}
|
107
t/unit-tests/u-oidtree.c
Normal file
107
t/unit-tests/u-oidtree.c
Normal file
@ -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);
|
||||
}
|
@ -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"
|
||||
|
||||
|
Reference in New Issue
Block a user