Skip to content

Commit ed54840

Browse files
spectre10gitster
authored andcommitted
t/: migrate helper/test-oidtree.c to unit-tests/t-oidtree.c
helper/test-oidtree.c along with t0069-oidtree.sh test the oidtree.h library, which is a wrapper around crit-bit tree. Migrate them to the unit testing framework for better debugging and runtime performance. Along with the migration, add an extra check for oidtree_each() test, which showcases how multiple expected matches can be given to check_each() helper. To achieve this, introduce a new library called 'lib-oid.h' exclusively for the unit tests to use. It currently mainly includes utility to generate object_id from an arbitrary hex string (i.e. '12a' -> '12a0000000000000000000000000000000000000'). This also handles the hash algo selection based on GIT_TEST_DEFAULT_HASH. This library will also be helpful when we port other unit tests such as oid-array, oidset etc. Helped-by: Junio C Hamano <[email protected]> Mentored-by: Christian Couder <[email protected]> Mentored-by: Kaartic Sivaraam <[email protected]> Signed-off-by: Ghanshyam Thakkar <[email protected]> [jc: small fixlets squashed in] Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1b76f06 commit ed54840

File tree

8 files changed

+197
-108
lines changed

8 files changed

+197
-108
lines changed

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,6 @@ TEST_BUILTINS_OBJS += test-mergesort.o
811811
TEST_BUILTINS_OBJS += test-mktemp.o
812812
TEST_BUILTINS_OBJS += test-oid-array.o
813813
TEST_BUILTINS_OBJS += test-oidmap.o
814-
TEST_BUILTINS_OBJS += test-oidtree.o
815814
TEST_BUILTINS_OBJS += test-online-cpus.o
816815
TEST_BUILTINS_OBJS += test-pack-mtimes.o
817816
TEST_BUILTINS_OBJS += test-parse-options.o
@@ -1335,6 +1334,7 @@ THIRD_PARTY_SOURCES += sha1dc/%
13351334

13361335
UNIT_TEST_PROGRAMS += t-ctype
13371336
UNIT_TEST_PROGRAMS += t-mem-pool
1337+
UNIT_TEST_PROGRAMS += t-oidtree
13381338
UNIT_TEST_PROGRAMS += t-prio-queue
13391339
UNIT_TEST_PROGRAMS += t-strbuf
13401340
UNIT_TEST_PROGRAMS += t-strcmp-offset
@@ -1343,6 +1343,7 @@ UNIT_TEST_PROGRAMS += t-trailer
13431343
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
13441344
UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
13451345
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
1346+
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o
13461347

13471348
# xdiff and reftable libs may in turn depend on what is in libgit.a
13481349
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
@@ -3883,7 +3884,10 @@ $(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS
38833884
-Wl,--allow-multiple-definition \
38843885
$(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE)
38853886

3886-
$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS
3887+
$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \
3888+
$(UNIT_TEST_DIR)/test-lib.o \
3889+
$(UNIT_TEST_DIR)/lib-oid.o \
3890+
$(GITLIBS) GIT-LDFLAGS
38873891
$(call mkdir_p_parent_template)
38883892
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
38893893
$(filter %.o,$^) $(filter %.a,$^) $(LIBS)

t/helper/test-oidtree.c

Lines changed: 0 additions & 54 deletions
This file was deleted.

t/helper/test-tool.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ static struct test_cmd cmds[] = {
4646
{ "mktemp", cmd__mktemp },
4747
{ "oid-array", cmd__oid_array },
4848
{ "oidmap", cmd__oidmap },
49-
{ "oidtree", cmd__oidtree },
5049
{ "online-cpus", cmd__online_cpus },
5150
{ "pack-mtimes", cmd__pack_mtimes },
5251
{ "parse-options", cmd__parse_options },

t/helper/test-tool.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ int cmd__match_trees(int argc, const char **argv);
3939
int cmd__mergesort(int argc, const char **argv);
4040
int cmd__mktemp(int argc, const char **argv);
4141
int cmd__oidmap(int argc, const char **argv);
42-
int cmd__oidtree(int argc, const char **argv);
4342
int cmd__online_cpus(int argc, const char **argv);
4443
int cmd__pack_mtimes(int argc, const char **argv);
4544
int cmd__parse_options(int argc, const char **argv);

t/t0069-oidtree.sh

Lines changed: 0 additions & 50 deletions
This file was deleted.

t/unit-tests/lib-oid.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include "test-lib.h"
2+
#include "lib-oid.h"
3+
#include "strbuf.h"
4+
#include "hex.h"
5+
6+
static int init_hash_algo(void)
7+
{
8+
static int algo = -1;
9+
10+
if (algo < 0) {
11+
const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH");
12+
algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1;
13+
14+
if (!check(algo != GIT_HASH_UNKNOWN))
15+
test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')",
16+
algo_name);
17+
}
18+
return algo;
19+
}
20+
21+
static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid,
22+
const struct git_hash_algo *algop)
23+
{
24+
int ret;
25+
size_t sz = strlen(hex);
26+
struct strbuf buf = STRBUF_INIT;
27+
28+
if (!check(sz <= algop->hexsz)) {
29+
test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)",
30+
hex, (unsigned long)algop->hexsz);
31+
return -1;
32+
}
33+
34+
strbuf_add(&buf, hex, sz);
35+
strbuf_addchars(&buf, '0', algop->hexsz - sz);
36+
37+
ret = get_oid_hex_algop(buf.buf, oid, algop);
38+
if (!check_int(ret, ==, 0))
39+
test_msg("BUG: invalid hex input (%s) provided", hex);
40+
41+
strbuf_release(&buf);
42+
return ret;
43+
}
44+
45+
int get_oid_arbitrary_hex(const char *hex, struct object_id *oid)
46+
{
47+
int hash_algo = init_hash_algo();
48+
49+
if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN))
50+
return -1;
51+
return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]);
52+
}

t/unit-tests/lib-oid.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef LIB_OID_H
2+
#define LIB_OID_H
3+
4+
#include "hash-ll.h"
5+
6+
/*
7+
* Convert arbitrary hex string to object_id.
8+
* For example, passing "abc12" will generate
9+
* "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and
10+
* create object_id with that.
11+
* WARNING: passing a string of length more than the hexsz of respective hash
12+
* algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH
13+
* environment variable.
14+
*/
15+
int get_oid_arbitrary_hex(const char *s, struct object_id *oid);
16+
17+
#endif /* LIB_OID_H */

t/unit-tests/t-oidtree.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include "test-lib.h"
2+
#include "lib-oid.h"
3+
#include "oidtree.h"
4+
#include "hash.h"
5+
#include "hex.h"
6+
#include "strvec.h"
7+
8+
#define FILL_TREE(tree, ...) \
9+
do { \
10+
const char *hexes[] = { __VA_ARGS__ }; \
11+
if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \
12+
return; \
13+
} while (0)
14+
15+
static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n)
16+
{
17+
for (size_t i = 0; i < n; i++) {
18+
struct object_id oid;
19+
if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0))
20+
return -1;
21+
oidtree_insert(ot, &oid);
22+
}
23+
return 0;
24+
}
25+
26+
static void check_contains(struct oidtree *ot, const char *hex, int expected)
27+
{
28+
struct object_id oid;
29+
30+
if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0))
31+
return;
32+
if (!check_int(oidtree_contains(ot, &oid), ==, expected))
33+
test_msg("oid: %s", oid_to_hex(&oid));
34+
}
35+
36+
struct expected_hex_iter {
37+
size_t i;
38+
struct strvec expected_hexes;
39+
const char *query;
40+
};
41+
42+
static enum cb_next check_each_cb(const struct object_id *oid, void *data)
43+
{
44+
struct expected_hex_iter *hex_iter = data;
45+
struct object_id expected;
46+
47+
if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) {
48+
test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')",
49+
hex_iter->query, oid_to_hex(oid));
50+
return CB_BREAK;
51+
}
52+
53+
if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i],
54+
&expected), ==, 0))
55+
; /* the data is bogus and cannot be used */
56+
else if (!check(oideq(oid, &expected)))
57+
test_msg("expected: %s\n got: %s\n query: %s",
58+
oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query);
59+
60+
hex_iter->i += 1;
61+
return CB_CONTINUE;
62+
}
63+
64+
LAST_ARG_MUST_BE_NULL
65+
static void check_each(struct oidtree *ot, const char *query, ...)
66+
{
67+
struct object_id oid;
68+
struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT,
69+
.query = query };
70+
const char *arg;
71+
va_list hex_args;
72+
73+
va_start(hex_args, query);
74+
while ((arg = va_arg(hex_args, const char *)))
75+
strvec_push(&hex_iter.expected_hexes, arg);
76+
va_end(hex_args);
77+
78+
if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0))
79+
return;
80+
oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter);
81+
82+
if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr))
83+
test_msg("error: could not find some 'object_id's for query ('%s')", query);
84+
strvec_clear(&hex_iter.expected_hexes);
85+
}
86+
87+
static void setup(void (*f)(struct oidtree *ot))
88+
{
89+
struct oidtree ot;
90+
91+
oidtree_init(&ot);
92+
f(&ot);
93+
oidtree_clear(&ot);
94+
}
95+
96+
static void t_contains(struct oidtree *ot)
97+
{
98+
FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e");
99+
check_contains(ot, "44", 0);
100+
check_contains(ot, "441", 0);
101+
check_contains(ot, "440", 0);
102+
check_contains(ot, "444", 1);
103+
check_contains(ot, "4440", 1);
104+
check_contains(ot, "4444", 0);
105+
}
106+
107+
static void t_each(struct oidtree *ot)
108+
{
109+
FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e");
110+
check_each(ot, "12300", "123", NULL);
111+
check_each(ot, "3211", NULL); /* should not reach callback */
112+
check_each(ot, "3210", "321", NULL);
113+
check_each(ot, "32100", "321", NULL);
114+
check_each(ot, "32", "320", "321", NULL);
115+
}
116+
117+
int cmd_main(int argc UNUSED, const char **argv UNUSED)
118+
{
119+
TEST(setup(t_contains), "oidtree insert and contains works");
120+
TEST(setup(t_each), "oidtree each works");
121+
return test_done();
122+
}

0 commit comments

Comments
 (0)