t/unit-tests: convert strvec tests to use clar

Convert the strvec tests to use the new clar unit testing framework. This is a first test balloon that demonstrates how the testing infra for clar-based tests looks like. The tests are part of the "t/unit-tests/bin/unit-tests" binary. When running that binary with an injected error, it generates TAP output: # ./t/unit-tests/bin/unit-tests TAP version 13 # start of suite 1: strvec ok 1 - strvec::init ok 2 - strvec::dynamic_init ok 3 - strvec::clear not ok 4 - strvec::push --- reason: | String mismatch: (&vec)->v[i] != expect[i] 'foo' != 'fo' (at byte 2) at: file: 't/unit-tests/strvec.c' line: 48 function: 'test_strvec__push' --- ok 5 - strvec::pushf ok 6 - strvec::pushl ok 7 - strvec::pushv ok 8 - strvec::replace_at_head ok 9 - strvec::replace_at_tail ok 10 - strvec::replace_in_between ok 11 - strvec::replace_with_substring ok 12 - strvec::remove_at_head ok 13 - strvec::remove_at_tail ok 14 - strvec::remove_in_between ok 15 - strvec::pop_empty_array ok 16 - strvec::pop_non_empty_array ok 17 - strvec::split_empty_string ok 18 - strvec::split_single_item ok 19 - strvec::split_multiple_items ok 20 - strvec::split_whitespace_only ok 21 - strvec::split_multiple_consecutive_whitespaces ok 22 - strvec::detach 1..22 The binary also supports some parameters that allow us to run only a subset of unit tests or alter the output: $ ./t/unit-tests/bin/unit-tests -h Usage: ./t/unit-tests/bin/unit-tests [options] Options: -sname Run only the suite with `name` (can go to individual test name) -iname Include the suite with `name` -xname Exclude the suite with `name` -v Increase verbosity (show suite names) -q Only report tests that had an error -Q Quit as soon as a test fails -t Display results in tap format -l Print suite names -r[filename] Write summary file (to the optional filename) Furthermore, running `make unit-tests` runs the binary along with all the other unit tests we have. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Sep 4, 2024 at 16:17 UTC d7f0c47964adc7ec6b6f5ef211c91be822587fb0
3 files changed +242 -212
Makefile
+1 -1
@@ -1336,6 +1336,7 @@ THIRD_PARTY_SOURCES += sha1dc/%
1336 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/%
1337 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/%
1338
1339 +UNIT_TESTS_SUITES += strvec
1340 UNIT_TESTS_PROG = $(UNIT_TEST_BIN)/unit-tests$(X)
1341 UNIT_TESTS_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TESTS_SUITES))
1342 UNIT_TESTS_OBJS += $(UNIT_TEST_DIR)/clar/clar.o
@@ -1356,7 +1357,6 @@ UNIT_TEST_PROGRAMS += t-reftable-record
1357 UNIT_TEST_PROGRAMS += t-reftable-tree
1358 UNIT_TEST_PROGRAMS += t-strbuf
1359 UNIT_TEST_PROGRAMS += t-strcmp-offset
1359 -UNIT_TEST_PROGRAMS += t-strvec
1360 UNIT_TEST_PROGRAMS += t-trailer
1361 UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
1362 UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
t/unit-tests/strvec.c new
+241
@@ -0,0 +1,241 @@
1 +#include "unit-test.h"
2 +#include "strbuf.h"
3 +#include "strvec.h"
4 +
5 +#define check_strvec(vec, ...) \
6 + do { \
7 + const char *expect[] = { __VA_ARGS__ }; \
8 + size_t expect_len = ARRAY_SIZE(expect); \
9 + cl_assert(expect_len > 0); \
10 + cl_assert_equal_p(expect[expect_len - 1], NULL); \
11 + cl_assert_equal_i((vec)->nr, expect_len - 1); \
12 + cl_assert((vec)->nr <= (vec)->alloc); \
13 + for (size_t i = 0; i < expect_len; i++) \
14 + cl_assert_equal_s((vec)->v[i], expect[i]); \
15 + } while (0)
16 +
17 +void test_strvec__init(void)
18 +{
19 + struct strvec vec = STRVEC_INIT;
20 +
21 + cl_assert_equal_p(vec.v, empty_strvec);
22 + cl_assert_equal_i(vec.nr, 0);
23 + cl_assert_equal_i(vec.alloc, 0);
24 +}
25 +
26 +void test_strvec__dynamic_init(void)
27 +{
28 + struct strvec vec;
29 +
30 + strvec_init(&vec);
31 + cl_assert_equal_p(vec.v, empty_strvec);
32 + cl_assert_equal_i(vec.nr, 0);
33 + cl_assert_equal_i(vec.alloc, 0);
34 +}
35 +
36 +void test_strvec__clear(void)
37 +{
38 + struct strvec vec = STRVEC_INIT;
39 +
40 + strvec_push(&vec, "foo");
41 + strvec_clear(&vec);
42 + cl_assert_equal_p(vec.v, empty_strvec);
43 + cl_assert_equal_i(vec.nr, 0);
44 + cl_assert_equal_i(vec.alloc, 0);
45 +}
46 +
47 +void test_strvec__push(void)
48 +{
49 + struct strvec vec = STRVEC_INIT;
50 +
51 + strvec_push(&vec, "foo");
52 + check_strvec(&vec, "foo", NULL);
53 +
54 + strvec_push(&vec, "bar");
55 + check_strvec(&vec, "foo", "bar", NULL);
56 +
57 + strvec_clear(&vec);
58 +}
59 +
60 +void test_strvec__pushf(void)
61 +{
62 + struct strvec vec = STRVEC_INIT;
63 +
64 + strvec_pushf(&vec, "foo: %d", 1);
65 + check_strvec(&vec, "foo: 1", NULL);
66 + strvec_clear(&vec);
67 +}
68 +
69 +void test_strvec__pushl(void)
70 +{
71 + struct strvec vec = STRVEC_INIT;
72 +
73 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
74 + check_strvec(&vec, "foo", "bar", "baz", NULL);
75 + strvec_clear(&vec);
76 +}
77 +
78 +void test_strvec__pushv(void)
79 +{
80 + const char *strings[] = {
81 + "foo", "bar", "baz", NULL,
82 + };
83 + struct strvec vec = STRVEC_INIT;
84 +
85 + strvec_pushv(&vec, strings);
86 + check_strvec(&vec, "foo", "bar", "baz", NULL);
87 +
88 + strvec_clear(&vec);
89 +}
90 +
91 +void test_strvec__replace_at_head(void)
92 +{
93 + struct strvec vec = STRVEC_INIT;
94 +
95 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
96 + strvec_replace(&vec, 0, "replaced");
97 + check_strvec(&vec, "replaced", "bar", "baz", NULL);
98 + strvec_clear(&vec);
99 +}
100 +
101 +void test_strvec__replace_at_tail(void)
102 +{
103 + struct strvec vec = STRVEC_INIT;
104 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
105 + strvec_replace(&vec, 2, "replaced");
106 + check_strvec(&vec, "foo", "bar", "replaced", NULL);
107 + strvec_clear(&vec);
108 +}
109 +
110 +void test_strvec__replace_in_between(void)
111 +{
112 + struct strvec vec = STRVEC_INIT;
113 +
114 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
115 + strvec_replace(&vec, 1, "replaced");
116 + check_strvec(&vec, "foo", "replaced", "baz", NULL);
117 + strvec_clear(&vec);
118 +}
119 +
120 +void test_strvec__replace_with_substring(void)
121 +{
122 + struct strvec vec = STRVEC_INIT;
123 +
124 + strvec_pushl(&vec, "foo", NULL);
125 + strvec_replace(&vec, 0, vec.v[0] + 1);
126 + check_strvec(&vec, "oo", NULL);
127 + strvec_clear(&vec);
128 +}
129 +
130 +void test_strvec__remove_at_head(void)
131 +{
132 + struct strvec vec = STRVEC_INIT;
133 +
134 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
135 + strvec_remove(&vec, 0);
136 + check_strvec(&vec, "bar", "baz", NULL);
137 + strvec_clear(&vec);
138 +}
139 +
140 +void test_strvec__remove_at_tail(void)
141 +{
142 + struct strvec vec = STRVEC_INIT;
143 +
144 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
145 + strvec_remove(&vec, 2);
146 + check_strvec(&vec, "foo", "bar", NULL);
147 + strvec_clear(&vec);
148 +}
149 +
150 +void test_strvec__remove_in_between(void)
151 +{
152 + struct strvec vec = STRVEC_INIT;
153 +
154 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
155 + strvec_remove(&vec, 1);
156 + check_strvec(&vec, "foo", "baz", NULL);
157 + strvec_clear(&vec);
158 +}
159 +
160 +void test_strvec__pop_empty_array(void)
161 +{
162 + struct strvec vec = STRVEC_INIT;
163 +
164 + strvec_pop(&vec);
165 + check_strvec(&vec, NULL);
166 + strvec_clear(&vec);
167 +}
168 +
169 +void test_strvec__pop_non_empty_array(void)
170 +{
171 + struct strvec vec = STRVEC_INIT;
172 +
173 + strvec_pushl(&vec, "foo", "bar", "baz", NULL);
174 + strvec_pop(&vec);
175 + check_strvec(&vec, "foo", "bar", NULL);
176 + strvec_clear(&vec);
177 +}
178 +
179 +void test_strvec__split_empty_string(void)
180 +{
181 + struct strvec vec = STRVEC_INIT;
182 +
183 + strvec_split(&vec, "");
184 + check_strvec(&vec, NULL);
185 + strvec_clear(&vec);
186 +}
187 +
188 +void test_strvec__split_single_item(void)
189 +{
190 + struct strvec vec = STRVEC_INIT;
191 +
192 + strvec_split(&vec, "foo");
193 + check_strvec(&vec, "foo", NULL);
194 + strvec_clear(&vec);
195 +}
196 +
197 +void test_strvec__split_multiple_items(void)
198 +{
199 + struct strvec vec = STRVEC_INIT;
200 +
201 + strvec_split(&vec, "foo bar baz");
202 + check_strvec(&vec, "foo", "bar", "baz", NULL);
203 + strvec_clear(&vec);
204 +}
205 +
206 +void test_strvec__split_whitespace_only(void)
207 +{
208 + struct strvec vec = STRVEC_INIT;
209 +
210 + strvec_split(&vec, " \t\n");
211 + check_strvec(&vec, NULL);
212 + strvec_clear(&vec);
213 +}
214 +
215 +void test_strvec__split_multiple_consecutive_whitespaces(void)
216 +{
217 + struct strvec vec = STRVEC_INIT;
218 +
219 + strvec_split(&vec, "foo\n\t bar");
220 + check_strvec(&vec, "foo", "bar", NULL);
221 + strvec_clear(&vec);
222 +}
223 +
224 +void test_strvec__detach(void)
225 +{
226 + struct strvec vec = STRVEC_INIT;
227 + const char **detached;
228 +
229 + strvec_push(&vec, "foo");
230 +
231 + detached = strvec_detach(&vec);
232 + cl_assert_equal_s(detached[0], "foo");
233 + cl_assert_equal_p(detached[1], NULL);
234 +
235 + cl_assert_equal_p(vec.v, empty_strvec);
236 + cl_assert_equal_i(vec.nr, 0);
237 + cl_assert_equal_i(vec.alloc, 0);
238 +
239 + free((char *) detached[0]);
240 + free(detached);
241 +}
t/unit-tests/t-strvec.c deleted
-211
@@ -1,211 +0,0 @@
1 -#include "test-lib.h"
2 -#include "strbuf.h"
3 -#include "strvec.h"
4 -
5 -#define check_strvec(vec, ...) \
6 - do { \
7 - const char *expect[] = { __VA_ARGS__ }; \
8 - if (check_uint(ARRAY_SIZE(expect), >, 0) && \
9 - check_pointer_eq(expect[ARRAY_SIZE(expect) - 1], NULL) && \
10 - check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \
11 - check_uint((vec)->nr, <=, (vec)->alloc)) { \
12 - for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
13 - if (!check_str((vec)->v[i], expect[i])) { \
14 - test_msg(" i: %"PRIuMAX, \
15 - (uintmax_t)i); \
16 - break; \
17 - } \
18 - } \
19 - } \
20 - } while (0)
21 -
22 -int cmd_main(int argc, const char **argv)
23 -{
24 - if_test ("static initialization") {
25 - struct strvec vec = STRVEC_INIT;
26 - check_pointer_eq(vec.v, empty_strvec);
27 - check_uint(vec.nr, ==, 0);
28 - check_uint(vec.alloc, ==, 0);
29 - }
30 -
31 - if_test ("dynamic initialization") {
32 - struct strvec vec;
33 - strvec_init(&vec);
34 - check_pointer_eq(vec.v, empty_strvec);
35 - check_uint(vec.nr, ==, 0);
36 - check_uint(vec.alloc, ==, 0);
37 - }
38 -
39 - if_test ("clear") {
40 - struct strvec vec = STRVEC_INIT;
41 - strvec_push(&vec, "foo");
42 - strvec_clear(&vec);
43 - check_pointer_eq(vec.v, empty_strvec);
44 - check_uint(vec.nr, ==, 0);
45 - check_uint(vec.alloc, ==, 0);
46 - }
47 -
48 - if_test ("push") {
49 - struct strvec vec = STRVEC_INIT;
50 -
51 - strvec_push(&vec, "foo");
52 - check_strvec(&vec, "foo", NULL);
53 -
54 - strvec_push(&vec, "bar");
55 - check_strvec(&vec, "foo", "bar", NULL);
56 -
57 - strvec_clear(&vec);
58 - }
59 -
60 - if_test ("pushf") {
61 - struct strvec vec = STRVEC_INIT;
62 - strvec_pushf(&vec, "foo: %d", 1);
63 - check_strvec(&vec, "foo: 1", NULL);
64 - strvec_clear(&vec);
65 - }
66 -
67 - if_test ("pushl") {
68 - struct strvec vec = STRVEC_INIT;
69 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
70 - check_strvec(&vec, "foo", "bar", "baz", NULL);
71 - strvec_clear(&vec);
72 - }
73 -
74 - if_test ("pushv") {
75 - const char *strings[] = {
76 - "foo", "bar", "baz", NULL,
77 - };
78 - struct strvec vec = STRVEC_INIT;
79 -
80 - strvec_pushv(&vec, strings);
81 - check_strvec(&vec, "foo", "bar", "baz", NULL);
82 -
83 - strvec_clear(&vec);
84 - }
85 -
86 - if_test ("replace at head") {
87 - struct strvec vec = STRVEC_INIT;
88 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
89 - strvec_replace(&vec, 0, "replaced");
90 - check_strvec(&vec, "replaced", "bar", "baz", NULL);
91 - strvec_clear(&vec);
92 - }
93 -
94 - if_test ("replace at tail") {
95 - struct strvec vec = STRVEC_INIT;
96 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
97 - strvec_replace(&vec, 2, "replaced");
98 - check_strvec(&vec, "foo", "bar", "replaced", NULL);
99 - strvec_clear(&vec);
100 - }
101 -
102 - if_test ("replace in between") {
103 - struct strvec vec = STRVEC_INIT;
104 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
105 - strvec_replace(&vec, 1, "replaced");
106 - check_strvec(&vec, "foo", "replaced", "baz", NULL);
107 - strvec_clear(&vec);
108 - }
109 -
110 - if_test ("replace with substring") {
111 - struct strvec vec = STRVEC_INIT;
112 - strvec_pushl(&vec, "foo", NULL);
113 - strvec_replace(&vec, 0, vec.v[0] + 1);
114 - check_strvec(&vec, "oo", NULL);
115 - strvec_clear(&vec);
116 - }
117 -
118 - if_test ("remove at head") {
119 - struct strvec vec = STRVEC_INIT;
120 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
121 - strvec_remove(&vec, 0);
122 - check_strvec(&vec, "bar", "baz", NULL);
123 - strvec_clear(&vec);
124 - }
125 -
126 - if_test ("remove at tail") {
127 - struct strvec vec = STRVEC_INIT;
128 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
129 - strvec_remove(&vec, 2);
130 - check_strvec(&vec, "foo", "bar", NULL);
131 - strvec_clear(&vec);
132 - }
133 -
134 - if_test ("remove in between") {
135 - struct strvec vec = STRVEC_INIT;
136 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
137 - strvec_remove(&vec, 1);
138 - check_strvec(&vec, "foo", "baz", NULL);
139 - strvec_clear(&vec);
140 - }
141 -
142 - if_test ("pop with empty array") {
143 - struct strvec vec = STRVEC_INIT;
144 - strvec_pop(&vec);
145 - check_strvec(&vec, NULL);
146 - strvec_clear(&vec);
147 - }
148 -
149 - if_test ("pop with non-empty array") {
150 - struct strvec vec = STRVEC_INIT;
151 - strvec_pushl(&vec, "foo", "bar", "baz", NULL);
152 - strvec_pop(&vec);
153 - check_strvec(&vec, "foo", "bar", NULL);
154 - strvec_clear(&vec);
155 - }
156 -
157 - if_test ("split empty string") {
158 - struct strvec vec = STRVEC_INIT;
159 - strvec_split(&vec, "");
160 - check_strvec(&vec, NULL);
161 - strvec_clear(&vec);
162 - }
163 -
164 - if_test ("split single item") {
165 - struct strvec vec = STRVEC_INIT;
166 - strvec_split(&vec, "foo");
167 - check_strvec(&vec, "foo", NULL);
168 - strvec_clear(&vec);
169 - }
170 -
171 - if_test ("split multiple items") {
172 - struct strvec vec = STRVEC_INIT;
173 - strvec_split(&vec, "foo bar baz");
174 - check_strvec(&vec, "foo", "bar", "baz", NULL);
175 - strvec_clear(&vec);
176 - }
177 -
178 - if_test ("split whitespace only") {
179 - struct strvec vec = STRVEC_INIT;
180 - strvec_split(&vec, " \t\n");
181 - check_strvec(&vec, NULL);
182 - strvec_clear(&vec);
183 - }
184 -
185 - if_test ("split multiple consecutive whitespaces") {
186 - struct strvec vec = STRVEC_INIT;
187 - strvec_split(&vec, "foo\n\t bar");
188 - check_strvec(&vec, "foo", "bar", NULL);
189 - strvec_clear(&vec);
190 - }
191 -
192 - if_test ("detach") {
193 - struct strvec vec = STRVEC_INIT;
194 - const char **detached;
195 -
196 - strvec_push(&vec, "foo");
197 -
198 - detached = strvec_detach(&vec);
199 - check_str(detached[0], "foo");
200 - check_pointer_eq(detached[1], NULL);
201 -
202 - check_pointer_eq(vec.v, empty_strvec);
203 - check_uint(vec.nr, ==, 0);
204 - check_uint(vec.alloc, ==, 0);
205 -
206 - free((char *) detached[0]);
207 - free(detached);
208 - }
209 -
210 - return test_done();
211 -}