u-string-list: move "test_split" into "u-string-list.c"

We rely on "test-tool string-list" command to test the functionality of the "string-list". However, as we have introduced clar test framework, we'd better move the shell script into C program to improve speed and readability. Create a new file "u-string-list.c" under "t/unit-tests", then update the Makefile and "meson.build" to build the file. And let's first move "test_split" into unit test and gradually convert the shell script into C program. In order to create `string_list` easily by simply specifying strings in the function call, create "t_vcreate_string_list_dup" function to do this. Then port the shell script tests to C program and remove unused "test-tool" code and tests. Signed-off-by: shejialuo <shejialuo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

shejialuo committed Jun 29, 2025 at 12:28 UTC 07d90fda58c79af661016137cbbafab169eeb329
5 files changed +57 -67
Makefile
+1
@@ -1367,6 +1367,7 @@ CLAR_TEST_SUITES += u-prio-queue
1367 CLAR_TEST_SUITES += u-reftable-tree
1368 CLAR_TEST_SUITES += u-strbuf
1369 CLAR_TEST_SUITES += u-strcmp-offset
1370 +CLAR_TEST_SUITES += u-string-list
1371 CLAR_TEST_SUITES += u-strvec
1372 CLAR_TEST_SUITES += u-trailer
1373 CLAR_TEST_SUITES += u-urlmatch-normalization
t/helper/test-string-list.c
-14
@@ -46,20 +46,6 @@ static int prefix_cb(struct string_list_item *item, void *cb_data)
46
47 int cmd__string_list(int argc, const char **argv)
48 {
49 - if (argc == 5 && !strcmp(argv[1], "split")) {
50 - struct string_list list = STRING_LIST_INIT_DUP;
51 - int i;
52 - const char *s = argv[2];
53 - int delim = *argv[3];
54 - int maxsplit = atoi(argv[4]);
55 -
56 - i = string_list_split(&list, s, delim, maxsplit);
57 - printf("%d\n", i);
58 - write_list(&list);
59 - string_list_clear(&list, 0);
60 - return 0;
61 - }
62 -
49 if (argc == 5 && !strcmp(argv[1], "split_in_place")) {
50 struct string_list list = STRING_LIST_INIT_NODUP;
51 int i;
t/meson.build
+1
@@ -11,6 +11,7 @@ clar_test_suites = [
11 'unit-tests/u-reftable-tree.c',
12 'unit-tests/u-strbuf.c',
13 'unit-tests/u-strcmp-offset.c',
14 + 'unit-tests/u-string-list.c',
15 'unit-tests/u-strvec.c',
16 'unit-tests/u-trailer.c',
17 'unit-tests/u-urlmatch-normalization.c',
t/t0063-string-list.sh
-53
@@ -7,16 +7,6 @@ test_description='Test string list functionality'
7
8 . ./test-lib.sh
9
10 -test_split () {
11 - cat >expected &&
12 - test_expect_success "split $1 at $2, max $3" "
13 - test-tool string-list split '$1' '$2' '$3' >actual &&
14 - test_cmp expected actual &&
15 - test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
16 - test_cmp expected actual
17 - "
18 -}
19 -
10 test_split_in_place() {
11 cat >expected &&
12 test_expect_success "split (in place) $1 at $2, max $3" "
@@ -25,49 +15,6 @@ test_split_in_place() {
15 "
16 }
17
28 -test_split "foo:bar:baz" ":" "-1" <<EOF
29 -3
30 -[0]: "foo"
31 -[1]: "bar"
32 -[2]: "baz"
33 -EOF
34 -
35 -test_split "foo:bar:baz" ":" "0" <<EOF
36 -1
37 -[0]: "foo:bar:baz"
38 -EOF
39 -
40 -test_split "foo:bar:baz" ":" "1" <<EOF
41 -2
42 -[0]: "foo"
43 -[1]: "bar:baz"
44 -EOF
45 -
46 -test_split "foo:bar:baz" ":" "2" <<EOF
47 -3
48 -[0]: "foo"
49 -[1]: "bar"
50 -[2]: "baz"
51 -EOF
52 -
53 -test_split "foo:bar:" ":" "-1" <<EOF
54 -3
55 -[0]: "foo"
56 -[1]: "bar"
57 -[2]: ""
58 -EOF
59 -
60 -test_split "" ":" "-1" <<EOF
61 -1
62 -[0]: ""
63 -EOF
64 -
65 -test_split ":" ":" "-1" <<EOF
66 -2
67 -[0]: ""
68 -[1]: ""
69 -EOF
70 -
18 test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
19 10
20 [0]: "foo"
t/unit-tests/u-string-list.c new
+55
@@ -0,0 +1,55 @@
1 +#include "unit-test.h"
2 +#include "string-list.h"
3 +
4 +static void t_vcreate_string_list_dup(struct string_list *list,
5 + int free_util, va_list ap)
6 +{
7 + const char *arg;
8 +
9 + cl_assert(list->strdup_strings);
10 +
11 + string_list_clear(list, free_util);
12 + while ((arg = va_arg(ap, const char *)))
13 + string_list_append(list, arg);
14 +}
15 +
16 +static void t_string_list_equal(struct string_list *list,
17 + struct string_list *expected_strings)
18 +{
19 + cl_assert_equal_i(list->nr, expected_strings->nr);
20 + cl_assert(list->nr <= list->alloc);
21 + for (size_t i = 0; i < expected_strings->nr; i++)
22 + cl_assert_equal_s(list->items[i].string,
23 + expected_strings->items[i].string);
24 +}
25 +
26 +static void t_string_list_split(const char *data, int delim, int maxsplit, ...)
27 +{
28 + struct string_list expected_strings = STRING_LIST_INIT_DUP;
29 + struct string_list list = STRING_LIST_INIT_DUP;
30 + va_list ap;
31 + int len;
32 +
33 + va_start(ap, maxsplit);
34 + t_vcreate_string_list_dup(&expected_strings, 0, ap);
35 + va_end(ap);
36 +
37 + string_list_clear(&list, 0);
38 + len = string_list_split(&list, data, delim, maxsplit);
39 + cl_assert_equal_i(len, expected_strings.nr);
40 + t_string_list_equal(&list, &expected_strings);
41 +
42 + string_list_clear(&expected_strings, 0);
43 + string_list_clear(&list, 0);
44 +}
45 +
46 +void test_string_list__split(void)
47 +{
48 + t_string_list_split("foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL);
49 + t_string_list_split("foo:bar:baz", ':', 0, "foo:bar:baz", NULL);
50 + t_string_list_split("foo:bar:baz", ':', 1, "foo", "bar:baz", NULL);
51 + t_string_list_split("foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL);
52 + t_string_list_split("foo:bar:", ':', -1, "foo", "bar", "", NULL);
53 + t_string_list_split("", ':', -1, "", NULL);
54 + t_string_list_split(":", ':', -1, "", "", NULL);
55 +}