t: port helper/test-oid-array.c to unit-tests/t-oid-array.c

helper/test-oid-array.c along with t0064-oid-array.sh test the oid-array.h API, which provides storage and processing efficiency over large lists of object identifiers. Migrate them to the unit testing framework for better runtime performance and efficiency. As we don't initialize a repository in these tests, the hash algo that functions like oid_array_lookup() use is not initialized, therefore call repo_set_hash_algo() to initialize it. And init_hash_algo():lib-oid.c can aid in this process, so make it public. Mentored-by: Christian Couder <chriscool@tuxfamily.org> Mentored-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ghanshyam Thakkar committed Sep 2, 2024 at 02:56 UTC a680635e05848f4428b4867b7e7ad0e07c94ae8b
8 files changed +136 -175
Makefile
+1 -1
@@ -808,7 +808,6 @@ TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
808 TEST_BUILTINS_OBJS += test-match-trees.o
809 TEST_BUILTINS_OBJS += test-mergesort.o
810 TEST_BUILTINS_OBJS += test-mktemp.o
811 -TEST_BUILTINS_OBJS += test-oid-array.o
811 TEST_BUILTINS_OBJS += test-online-cpus.o
812 TEST_BUILTINS_OBJS += test-pack-mtimes.o
813 TEST_BUILTINS_OBJS += test-parse-options.o
@@ -1337,6 +1336,7 @@ UNIT_TEST_PROGRAMS += t-example-decorate
1336 UNIT_TEST_PROGRAMS += t-hash
1337 UNIT_TEST_PROGRAMS += t-hashmap
1338 UNIT_TEST_PROGRAMS += t-mem-pool
1339 +UNIT_TEST_PROGRAMS += t-oid-array
1340 UNIT_TEST_PROGRAMS += t-oidmap
1341 UNIT_TEST_PROGRAMS += t-oidtree
1342 UNIT_TEST_PROGRAMS += t-prio-queue
t/helper/test-oid-array.c deleted
-49
@@ -1,49 +0,0 @@
1 -#define USE_THE_REPOSITORY_VARIABLE
2 -
3 -#include "test-tool.h"
4 -#include "hex.h"
5 -#include "oid-array.h"
6 -#include "setup.h"
7 -#include "strbuf.h"
8 -
9 -static int print_oid(const struct object_id *oid, void *data UNUSED)
10 -{
11 - puts(oid_to_hex(oid));
12 - return 0;
13 -}
14 -
15 -int cmd__oid_array(int argc UNUSED, const char **argv UNUSED)
16 -{
17 - struct oid_array array = OID_ARRAY_INIT;
18 - struct strbuf line = STRBUF_INIT;
19 - int nongit_ok;
20 -
21 - setup_git_directory_gently(&nongit_ok);
22 - if (nongit_ok)
23 - repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
24 -
25 - while (strbuf_getline(&line, stdin) != EOF) {
26 - const char *arg;
27 - struct object_id oid;
28 -
29 - if (skip_prefix(line.buf, "append ", &arg)) {
30 - if (get_oid_hex(arg, &oid))
31 - die("not a hexadecimal oid: %s", arg);
32 - oid_array_append(&array, &oid);
33 - } else if (skip_prefix(line.buf, "lookup ", &arg)) {
34 - if (get_oid_hex(arg, &oid))
35 - die("not a hexadecimal oid: %s", arg);
36 - printf("%d\n", oid_array_lookup(&array, &oid));
37 - } else if (!strcmp(line.buf, "clear"))
38 - oid_array_clear(&array);
39 - else if (!strcmp(line.buf, "for_each_unique"))
40 - oid_array_for_each_unique(&array, print_oid, NULL);
41 - else
42 - die("unknown command: %s", line.buf);
43 - }
44 -
45 - strbuf_release(&line);
46 - oid_array_clear(&array);
47 -
48 - return 0;
49 -}
t/helper/test-tool.c
-1
@@ -43,7 +43,6 @@ static struct test_cmd cmds[] = {
43 { "match-trees", cmd__match_trees },
44 { "mergesort", cmd__mergesort },
45 { "mktemp", cmd__mktemp },
46 - { "oid-array", cmd__oid_array },
46 { "online-cpus", cmd__online_cpus },
47 { "pack-mtimes", cmd__pack_mtimes },
48 { "parse-options", cmd__parse_options },
t/helper/test-tool.h
-1
@@ -64,7 +64,6 @@ int cmd__scrap_cache_tree(int argc, const char **argv);
64 int cmd__serve_v2(int argc, const char **argv);
65 int cmd__sha1(int argc, const char **argv);
66 int cmd__sha1_is_sha1dc(int argc, const char **argv);
67 -int cmd__oid_array(int argc, const char **argv);
67 int cmd__sha256(int argc, const char **argv);
68 int cmd__sigchain(int argc, const char **argv);
69 int cmd__simple_ipc(int argc, const char **argv);
t/t0064-oid-array.sh deleted
-122
@@ -1,122 +0,0 @@
1 -#!/bin/sh
2 -
3 -test_description='basic tests for the oid array implementation'
4 -
5 -TEST_PASSES_SANITIZE_LEAK=true
6 -. ./test-lib.sh
7 -
8 -echoid () {
9 - prefix="${1:+$1 }"
10 - shift
11 - while test $# -gt 0
12 - do
13 - echo "$prefix$ZERO_OID" | sed -e "s/00/$1/g"
14 - shift
15 - done
16 -}
17 -
18 -test_expect_success 'without repository' '
19 - cat >expect <<-EOF &&
20 - 4444444444444444444444444444444444444444
21 - 5555555555555555555555555555555555555555
22 - 8888888888888888888888888888888888888888
23 - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
24 - EOF
25 - cat >input <<-EOF &&
26 - append 4444444444444444444444444444444444444444
27 - append 5555555555555555555555555555555555555555
28 - append 8888888888888888888888888888888888888888
29 - append aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
30 - for_each_unique
31 - EOF
32 - nongit test-tool oid-array <input >actual &&
33 - test_cmp expect actual
34 -'
35 -
36 -test_expect_success 'ordered enumeration' '
37 - echoid "" 44 55 88 aa >expect &&
38 - {
39 - echoid append 88 44 aa 55 &&
40 - echo for_each_unique
41 - } | test-tool oid-array >actual &&
42 - test_cmp expect actual
43 -'
44 -
45 -test_expect_success 'ordered enumeration with duplicate suppression' '
46 - echoid "" 44 55 88 aa >expect &&
47 - {
48 - echoid append 88 44 aa 55 &&
49 - echoid append 88 44 aa 55 &&
50 - echoid append 88 44 aa 55 &&
51 - echo for_each_unique
52 - } | test-tool oid-array >actual &&
53 - test_cmp expect actual
54 -'
55 -
56 -test_expect_success 'lookup' '
57 - {
58 - echoid append 88 44 aa 55 &&
59 - echoid lookup 55
60 - } | test-tool oid-array >actual &&
61 - n=$(cat actual) &&
62 - test "$n" -eq 1
63 -'
64 -
65 -test_expect_success 'lookup non-existing entry' '
66 - {
67 - echoid append 88 44 aa 55 &&
68 - echoid lookup 33
69 - } | test-tool oid-array >actual &&
70 - n=$(cat actual) &&
71 - test "$n" -lt 0
72 -'
73 -
74 -test_expect_success 'lookup with duplicates' '
75 - {
76 - echoid append 88 44 aa 55 &&
77 - echoid append 88 44 aa 55 &&
78 - echoid append 88 44 aa 55 &&
79 - echoid lookup 55
80 - } | test-tool oid-array >actual &&
81 - n=$(cat actual) &&
82 - test "$n" -ge 3 &&
83 - test "$n" -le 5
84 -'
85 -
86 -test_expect_success 'lookup non-existing entry with duplicates' '
87 - {
88 - echoid append 88 44 aa 55 &&
89 - echoid append 88 44 aa 55 &&
90 - echoid append 88 44 aa 55 &&
91 - echoid lookup 66
92 - } | test-tool oid-array >actual &&
93 - n=$(cat actual) &&
94 - test "$n" -lt 0
95 -'
96 -
97 -test_expect_success 'lookup with almost duplicate values' '
98 - # n-1 5s
99 - root=$(echoid "" 55) &&
100 - root=${root%5} &&
101 - {
102 - id1="${root}5" &&
103 - id2="${root}f" &&
104 - echo "append $id1" &&
105 - echo "append $id2" &&
106 - echoid lookup 55
107 - } | test-tool oid-array >actual &&
108 - n=$(cat actual) &&
109 - test "$n" -eq 0
110 -'
111 -
112 -test_expect_success 'lookup with single duplicate value' '
113 - {
114 - echoid append 55 55 &&
115 - echoid lookup 55
116 - } | test-tool oid-array >actual &&
117 - n=$(cat actual) &&
118 - test "$n" -ge 0 &&
119 - test "$n" -le 1
120 -'
121 -
122 -test_done
t/unit-tests/lib-oid.c
+1 -1
@@ -3,7 +3,7 @@
3 #include "strbuf.h"
4 #include "hex.h"
5
6 -static int init_hash_algo(void)
6 +int init_hash_algo(void)
7 {
8 static int algo = -1;
9
t/unit-tests/lib-oid.h
+8
@@ -13,5 +13,13 @@
13 * environment variable.
14 */
15 int get_oid_arbitrary_hex(const char *s, struct object_id *oid);
16 +/*
17 + * Returns one of GIT_HASH_{SHA1, SHA256, UNKNOWN} based on the value of
18 + * GIT_TEST_DEFAULT_HASH environment variable. The fallback value in the
19 + * absence of GIT_TEST_DEFAULT_HASH is GIT_HASH_SHA1. It also uses
20 + * check(algo != GIT_HASH_UNKNOWN) before returning to verify if the
21 + * GIT_TEST_DEFAULT_HASH's value is valid or not.
22 + */
23 +int init_hash_algo(void);
24
25 #endif /* LIB_OID_H */
t/unit-tests/t-oid-array.c new
+126
@@ -0,0 +1,126 @@
1 +#define USE_THE_REPOSITORY_VARIABLE
2 +
3 +#include "test-lib.h"
4 +#include "lib-oid.h"
5 +#include "oid-array.h"
6 +#include "hex.h"
7 +
8 +static int fill_array(struct oid_array *array, const char *hexes[], size_t n)
9 +{
10 + for (size_t i = 0; i < n; i++) {
11 + struct object_id oid;
12 +
13 + if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0))
14 + return -1;
15 + oid_array_append(array, &oid);
16 + }
17 + if (!check_uint(array->nr, ==, n))
18 + return -1;
19 + return 0;
20 +}
21 +
22 +static int add_to_oid_array(const struct object_id *oid, void *data)
23 +{
24 + struct oid_array *array = data;
25 +
26 + oid_array_append(array, oid);
27 + return 0;
28 +}
29 +
30 +static void t_enumeration(const char **input_args, size_t input_sz,
31 + const char **expect_args, size_t expect_sz)
32 +{
33 + struct oid_array input = OID_ARRAY_INIT, expect = OID_ARRAY_INIT,
34 + actual = OID_ARRAY_INIT;
35 + size_t i;
36 +
37 + if (fill_array(&input, input_args, input_sz))
38 + return;
39 + if (fill_array(&expect, expect_args, expect_sz))
40 + return;
41 +
42 + oid_array_for_each_unique(&input, add_to_oid_array, &actual);
43 + if (!check_uint(actual.nr, ==, expect.nr))
44 + return;
45 +
46 + for (i = 0; i < actual.nr; i++) {
47 + if (!check(oideq(&actual.oid[i], &expect.oid[i])))
48 + test_msg("expected: %s\n got: %s\n index: %" PRIuMAX,
49 + oid_to_hex(&expect.oid[i]), oid_to_hex(&actual.oid[i]),
50 + (uintmax_t)i);
51 + }
52 +
53 + oid_array_clear(&actual);
54 + oid_array_clear(&input);
55 + oid_array_clear(&expect);
56 +}
57 +
58 +#define TEST_ENUMERATION(input, expect, desc) \
59 + TEST(t_enumeration(input, ARRAY_SIZE(input), expect, ARRAY_SIZE(expect)), \
60 + desc " works")
61 +
62 +static void t_lookup(const char **input_hexes, size_t n, const char *query_hex,
63 + int lower_bound, int upper_bound)
64 +{
65 + struct oid_array array = OID_ARRAY_INIT;
66 + struct object_id oid_query;
67 + int ret;
68 +
69 + if (!check_int(get_oid_arbitrary_hex(query_hex, &oid_query), ==, 0))
70 + return;
71 + if (fill_array(&array, input_hexes, n))
72 + return;
73 + ret = oid_array_lookup(&array, &oid_query);
74 +
75 + if (!check_int(ret, <=, upper_bound) ||
76 + !check_int(ret, >=, lower_bound))
77 + test_msg("oid query for lookup: %s", oid_to_hex(&oid_query));
78 +
79 + oid_array_clear(&array);
80 +}
81 +
82 +#define TEST_LOOKUP(input_hexes, query, lower_bound, upper_bound, desc) \
83 + TEST(t_lookup(input_hexes, ARRAY_SIZE(input_hexes), query, \
84 + lower_bound, upper_bound), \
85 + desc " works")
86 +
87 +static void setup(void)
88 +{
89 + /* The hash algo is used by oid_array_lookup() internally */
90 + int algo = init_hash_algo();
91 + if (check_int(algo, !=, GIT_HASH_UNKNOWN))
92 + repo_set_hash_algo(the_repository, algo);
93 +}
94 +
95 +int cmd_main(int argc UNUSED, const char **argv UNUSED)
96 +{
97 + const char *arr_input[] = { "88", "44", "aa", "55" };
98 + const char *arr_input_dup[] = { "88", "44", "aa", "55",
99 + "88", "44", "aa", "55",
100 + "88", "44", "aa", "55" };
101 + const char *res_sorted[] = { "44", "55", "88", "aa" };
102 + const char *nearly_55;
103 +
104 + if (!TEST(setup(), "setup"))
105 + test_skip_all("hash algo initialization failed");
106 +
107 + TEST_ENUMERATION(arr_input, res_sorted, "ordered enumeration");
108 + TEST_ENUMERATION(arr_input_dup, res_sorted,
109 + "ordered enumeration with duplicate suppression");
110 +
111 + TEST_LOOKUP(arr_input, "55", 1, 1, "lookup");
112 + TEST_LOOKUP(arr_input, "33", INT_MIN, -1, "lookup non-existent entry");
113 + TEST_LOOKUP(arr_input_dup, "55", 3, 5, "lookup with duplicates");
114 + TEST_LOOKUP(arr_input_dup, "66", INT_MIN, -1,
115 + "lookup non-existent entry with duplicates");
116 +
117 + nearly_55 = init_hash_algo() == GIT_HASH_SHA1 ?
118 + "5500000000000000000000000000000000000001" :
119 + "5500000000000000000000000000000000000000000000000000000000000001";
120 + TEST_LOOKUP(((const char *[]){ "55", nearly_55 }), "55", 0, 0,
121 + "lookup with almost duplicate values");
122 + TEST_LOOKUP(((const char *[]){ "55", "55" }), "55", 0, 1,
123 + "lookup with single duplicate value");
124 +
125 + return test_done();
126 +}