dte test coverage


Directory: ./
File: test/ctags.c
Date: 2025-07-19 20:13:10
Exec Total Coverage
Lines: 72 72 100.0%
Functions: 2 2 100.0%
Branches: 2 2 100.0%

Line Branch Exec Source
1 #include "test.h"
2 #include "ctags.h"
3 #include "util/readfile.h"
4
5 1 static void test_parse_ctags_line(TestContext *ctx)
6 {
7 1 const char *line = "foo\tfile.c\t/^int foo(char *s)$/;\"\tf\tfile:";
8 1 Tag tag = {.pattern = NULL};
9 1 EXPECT_TRUE(parse_ctags_line(&tag, line, strlen(line)));
10 1 EXPECT_EQ(tag.name.length, 3);
11 1 EXPECT_PTREQ(tag.name.data, line);
12 1 EXPECT_EQ(tag.filename.length, 6);
13 1 EXPECT_PTREQ(tag.filename.data, line + 4);
14 1 EXPECT_STREQ(tag.pattern, "^int foo(char \\*s)$");
15 1 EXPECT_EQ(tag.lineno, 0);
16 1 EXPECT_EQ(tag.kind, 'f');
17 1 EXPECT_EQ(tag.local, true);
18 1 free_tag(&tag);
19
20 1 line = "abc\t123.py\t/^backslashes \\\\ in \\ \\: pattern$/";
21 1 tag = (Tag){.pattern = NULL};
22 1 EXPECT_TRUE(parse_ctags_line(&tag, line, strlen(line)));
23 1 EXPECT_EQ(tag.filename.length, 6);
24 1 EXPECT_STREQ(tag.pattern, "^backslashes \\\\ in : pattern$");
25 1 EXPECT_EQ(tag.lineno, 0);
26 1 EXPECT_EQ(tag.kind, 0);
27 1 free_tag(&tag);
28
29 1 line = "example\tsrc/xyz.c\t488;\"\tk";
30 1 tag = (Tag){.pattern = NULL};
31 1 EXPECT_TRUE(parse_ctags_line(&tag, line, strlen(line)));
32 1 EXPECT_EQ(tag.filename.length, 9);
33 1 EXPECT_NULL(tag.pattern);
34 1 EXPECT_EQ(tag.lineno, 488);
35 1 EXPECT_EQ(tag.kind, 'k');
36 1 free_tag(&tag);
37
38 1 line = "x\tstr.c\t12495\tz";
39 1 tag = (Tag){.pattern = NULL};
40 1 EXPECT_TRUE(parse_ctags_line(&tag, line, strlen(line)));
41 1 EXPECT_NULL(tag.pattern);
42 1 EXPECT_EQ(tag.lineno, 12495);
43 1 EXPECT_EQ(tag.kind, 'z');
44 1 free_tag(&tag);
45
46 1 line = "name\tfile.c\t/^char after pattern with no tab delimiter/t";
47 1 tag = (Tag){.pattern = NULL};
48 1 EXPECT_FALSE(parse_ctags_line(&tag, line, strlen(line)));
49 1 free_tag(&tag);
50
51 1 line = "bar\tsource.c\t/^unterminated pattern\tf";
52 1 EXPECT_FALSE(parse_ctags_line(&tag, line, strlen(line)));
53 1 free_tag(&tag);
54
55 1 StringView sv = STRING_VIEW("tag-name\tfile.txt\t/^embedded NUL \0 char/\tf");
56 1 EXPECT_FALSE(parse_ctags_line(&tag, sv.data, sv.length));
57 1 free_tag(&tag);
58 1 }
59
60 1 static void test_next_tag(TestContext *ctx)
61 {
62 1 static const struct {
63 const char *name;
64 char kind;
65 bool local;
66 } expected[] = {
67 {"MIN_SIZE", 'e', true},
68 {"TOMBSTONE", 'e', true},
69 {"hashmap_clear", 'f', false},
70 {"hashmap_do_init", 'f', true},
71 {"hashmap_do_insert", 'f', true},
72 {"hashmap_find", 'f', false},
73 {"hashmap_free", 'f', false},
74 {"hashmap_init", 'f', false},
75 {"hashmap_insert", 'f', false},
76 {"hashmap_insert_or_replace", 'f', false},
77 {"hashmap_remove", 'f', false},
78 {"hashmap_resize", 'f', true},
79 };
80
81 1 char *buf;
82 1 ssize_t len = read_file("test/data/ctags.txt", &buf, 8192);
83 1 ASSERT_TRUE(len >= 64);
84
85 1 StringView prefix = STRING_VIEW("");
86 1 Tag t;
87
2/2
✓ Branch 0 (13→5) taken 12 times.
✓ Branch 1 (13→14) taken 1 times.
13 for (size_t i = 0, pos = 0; next_tag(buf, len, &pos, &prefix, false, &t); i++) {
88 12 EXPECT_STRVIEW_EQ_CSTRING(&t.name, expected[i].name);
89 12 IEXPECT_EQ(t.kind, expected[i].kind);
90 12 IEXPECT_EQ(t.local, expected[i].local);
91 12 EXPECT_STRVIEW_EQ_CSTRING(&t.filename, "src/util/hashmap.c");
92 12 IEXPECT_EQ(t.lineno, 0);
93 12 free_tag(&t);
94 }
95
96 1 size_t pos = 0;
97 1 t.name = string_view(NULL, 0);
98 1 prefix = strview_from_cstring("hashmap_res");
99 1 EXPECT_TRUE(next_tag(buf, len, &pos, &prefix, false, &t));
100 1 EXPECT_STRVIEW_EQ_CSTRING(&t.name, "hashmap_resize");
101 1 free_tag(&t);
102 1 EXPECT_FALSE(next_tag(buf, len, &pos, &prefix, false, &t));
103 1 pos = 0;
104 1 EXPECT_FALSE(next_tag(buf, len, &pos, &prefix, true, &t));
105
106 1 free(buf);
107 1 }
108
109 static const TestEntry tests[] = {
110 TEST(test_parse_ctags_line),
111 TEST(test_next_tag),
112 };
113
114 const TestGroup ctags_tests = TEST_GROUP(tests);
115