| 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 = strview(NULL); | |
| 98 | 1 | prefix = strview("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 |