dte test coverage


Directory: ./
File: test/history.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 184 184 100.0%
Functions: 4 4 100.0%
Branches: 2 2 100.0%

Line Branch Exec Source
1 #include <stdlib.h>
2 #include "test.h"
3 #include "file-history.h"
4 #include "history.h"
5 #include "util/numtostr.h"
6 #include "util/readfile.h"
7 #include "util/xmalloc.h"
8
9 1 static void test_history_append(TestContext *ctx)
10 {
11 1 History h = {.max_entries = 7};
12 1 history_append(&h, "A");
13 1 EXPECT_EQ(h.entries.count, 1);
14 1 EXPECT_STREQ(h.first->text, "A");
15 1 EXPECT_NULL(h.first->prev);
16 1 EXPECT_NULL(h.first->next);
17 1 EXPECT_PTREQ(h.first, h.last);
18
19 1 history_append(&h, "A");
20 1 EXPECT_EQ(h.entries.count, 1);
21 1 EXPECT_PTREQ(h.first, h.last);
22
23 1 history_append(&h, "B");
24 1 EXPECT_EQ(h.entries.count, 2);
25 1 EXPECT_STREQ(h.first->text, "A");
26 1 EXPECT_STREQ(h.last->text, "B");
27 1 EXPECT_NULL(h.first->prev);
28 1 EXPECT_NULL(h.last->next);
29 1 EXPECT_PTREQ(h.first->next, h.last);
30 1 EXPECT_PTREQ(h.last->prev, h.first);
31
32 1 history_append(&h, "C");
33 1 EXPECT_EQ(h.entries.count, 3);
34 1 EXPECT_STREQ(h.first->text, "A");
35 1 EXPECT_STREQ(h.first->next->text, "B");
36 1 EXPECT_STREQ(h.last->prev->text, "B");
37 1 EXPECT_STREQ(h.last->text, "C");
38 1 EXPECT_NULL(h.first->prev);
39 1 EXPECT_NULL(h.last->next);
40
41 1 history_append(&h, "A");
42 1 EXPECT_EQ(h.entries.count, 3);
43 1 EXPECT_STREQ(h.last->text, "A");
44 1 EXPECT_STREQ(h.first->text, "B");
45 1 EXPECT_NULL(h.first->prev);
46 1 EXPECT_NULL(h.last->next);
47 1 EXPECT_STREQ(h.first->next->text, "C");
48 1 EXPECT_STREQ(h.last->prev->text, "C");
49
50 1 history_append(&h, "C");
51 1 EXPECT_EQ(h.entries.count, 3);
52 1 EXPECT_STREQ(h.last->text, "C");
53 1 EXPECT_STREQ(h.first->text, "B");
54 1 EXPECT_NULL(h.first->prev);
55 1 EXPECT_NULL(h.last->next);
56 1 EXPECT_STREQ(h.first->next->text, "A");
57 1 EXPECT_STREQ(h.last->prev->text, "A");
58
59 1 history_append(&h, "B");
60 1 history_append(&h, "C");
61 1 EXPECT_EQ(h.entries.count, 3);
62 1 EXPECT_STREQ(h.first->text, "A");
63 1 EXPECT_STREQ(h.first->next->text, "B");
64 1 EXPECT_STREQ(h.last->prev->text, "B");
65 1 EXPECT_STREQ(h.last->text, "C");
66
67 1 history_append(&h, "D");
68 1 history_append(&h, "E");
69 1 history_append(&h, "F");
70 1 history_append(&h, "G");
71 1 EXPECT_EQ(h.entries.count, 7);
72 1 EXPECT_STREQ(h.last->text, "G");
73 1 EXPECT_STREQ(h.first->text, "A");
74 1 EXPECT_STREQ(h.last->prev->text, "F");
75
76 1 history_append(&h, "H");
77 1 EXPECT_EQ(h.entries.count, 7);
78 1 EXPECT_STREQ(h.last->text, "H");
79 1 EXPECT_STREQ(h.first->text, "B");
80 1 EXPECT_STREQ(h.last->prev->text, "G");
81
82 1 history_append(&h, "I");
83 1 EXPECT_EQ(h.entries.count, 7);
84 1 EXPECT_STREQ(h.last->text, "I");
85 1 EXPECT_STREQ(h.first->text, "C");
86 1 EXPECT_STREQ(h.last->prev->text, "H");
87
88 1 history_free(&h);
89 1 h = (History){.max_entries = 2};
90 1 EXPECT_EQ(h.entries.count, 0);
91
92 1 history_append(&h, "1");
93 1 EXPECT_EQ(h.entries.count, 1);
94 1 EXPECT_STREQ(h.last->text, "1");
95 1 EXPECT_STREQ(h.first->text, "1");
96
97 1 history_append(&h, "2");
98 1 EXPECT_EQ(h.entries.count, 2);
99 1 EXPECT_STREQ(h.last->text, "2");
100 1 EXPECT_STREQ(h.first->text, "1");
101
102 1 history_append(&h, "3");
103 1 EXPECT_EQ(h.entries.count, 2);
104 1 EXPECT_STREQ(h.last->text, "3");
105 1 EXPECT_STREQ(h.first->text, "2");
106
107 1 history_free(&h);
108 1 }
109
110 1 static void test_history_search(TestContext *ctx)
111 {
112 1 ErrorBuffer ebuf = {.print_to_stderr = false};
113 1 const char *filename = "test/data/history";
114 1 History h = {.max_entries = 64};
115 1 history_load(&h, &ebuf, xstrdup(filename), 4096);
116 1 EXPECT_EQ(h.entries.count, 3);
117 1 EXPECT_STREQ(h.filename, filename);
118 1 ASSERT_NONNULL(h.first);
119 1 EXPECT_STREQ(h.first->text, "one");
120 1 ASSERT_NONNULL(h.last);
121 1 EXPECT_STREQ(h.last->text, "three");
122 1 ASSERT_NONNULL(h.first->next);
123 1 EXPECT_STREQ(h.first->next->text, "two");
124 1 ASSERT_NONNULL(h.last->prev);
125 1 EXPECT_STREQ(h.last->prev->text, "two");
126 1 EXPECT_NULL(h.first->prev);
127 1 EXPECT_NULL(h.last->next);
128
129 1 const HistoryEntry *e = h.last;
130 1 EXPECT_STREQ(e->text, "three");
131 1 EXPECT_TRUE(history_search_forward(&h, &e, ""));
132 1 EXPECT_STREQ(e->text, "two");
133 1 EXPECT_TRUE(history_search_forward(&h, &e, ""));
134 1 EXPECT_STREQ(e->text, "one");
135 1 EXPECT_FALSE(history_search_forward(&h, &e, ""));
136
137 1 EXPECT_STREQ(e->text, "one");
138 1 EXPECT_TRUE(history_search_backward(&h, &e, ""));
139 1 EXPECT_STREQ(e->text, "two");
140 1 EXPECT_TRUE(history_search_backward(&h, &e, ""));
141 1 EXPECT_STREQ(e->text, "three");
142 1 EXPECT_FALSE(history_search_backward(&h, &e, ""));
143
144 1 EXPECT_STREQ(e->text, "three");
145 1 EXPECT_TRUE(history_search_forward(&h, &e, "o"));
146 1 EXPECT_STREQ(e->text, "one");
147 1 EXPECT_TRUE(history_search_backward(&h, &e, "th"));
148 1 EXPECT_STREQ(e->text, "three");
149
150 1 free(h.filename);
151 1 filename = "build/test/saved_history";
152 1 h.filename = xstrdup(filename);
153 1 history_save(&h, &ebuf);
154 1 history_free(&h);
155 1 char *buf = NULL;
156 1 ssize_t n = read_file(filename, &buf, 4096);
157 1 EXPECT_EQ(n, 14);
158 1 EXPECT_STREQ(buf, "one\ntwo\nthree\n");
159 1 free(buf);
160 1 }
161
162 // This test is done to ensure the HashMap can handle the constant
163 // churn from insertions and removals (i.e. that it rehashes the
164 // table to clean out tombstones, even when the number of real
165 // entries stops growing).
166 1 static void test_history_tombstones(TestContext *ctx)
167 {
168 1 History h = {.max_entries = 512};
169
2/2
✓ Branch 0 (6→3) taken 12000 times.
✓ Branch 1 (6→7) taken 1 times.
12001 for (unsigned int i = 0; i < 12000; i++) {
170 12000 history_append(&h, uint_to_str(i));
171 }
172
173 1 EXPECT_EQ(h.entries.count, h.max_entries);
174 1 EXPECT_TRUE(h.entries.mask + 1 <= 2048);
175 1 history_free(&h);
176 1 }
177
178 1 static void test_file_history_find(TestContext *ctx)
179 {
180 1 ErrorBuffer ebuf = {.print_to_stderr = false};
181 1 const char fh_filename[] = "test/data/file-history";
182 1 FileHistory h = {.filename = NULL};
183 1 file_history_load(&h, &ebuf, xstrdup(fh_filename), 4096);
184 1 EXPECT_STREQ(h.filename, fh_filename);
185 1 EXPECT_EQ(h.entries.count, 3);
186
187 1 const FileHistoryEntry *first = h.first;
188 1 ASSERT_NONNULL(first);
189 1 ASSERT_NONNULL(first->next);
190 1 EXPECT_NULL(first->prev);
191 1 EXPECT_STREQ(first->filename, "/etc/hosts");
192 1 EXPECT_EQ(first->row, 3);
193 1 EXPECT_EQ(first->col, 42);
194
195 1 const FileHistoryEntry *last = h.last;
196 1 ASSERT_NONNULL(last);
197 1 ASSERT_NONNULL(last->prev);
198 1 EXPECT_NULL(last->next);
199 1 EXPECT_STREQ(last->filename, "/home/user/file.txt");
200 1 EXPECT_EQ(last->row, 4521);
201 1 EXPECT_EQ(last->col, 1);
202
203 1 const FileHistoryEntry *mid = first->next;
204 1 ASSERT_NONNULL(mid);
205 1 EXPECT_PTREQ(mid, last->prev);
206 1 EXPECT_PTREQ(mid->prev, first);
207 1 EXPECT_PTREQ(mid->next, last);
208 1 EXPECT_STREQ(mid->filename, "/tmp/foo");
209 1 EXPECT_EQ(mid->row, 123);
210 1 EXPECT_EQ(mid->col, 456);
211
212 1 unsigned long row = 0, col = 0;
213 1 EXPECT_TRUE(file_history_find(&h, first->filename, &row, &col));
214 1 EXPECT_EQ(row, first->row);
215 1 EXPECT_EQ(col, first->col);
216 1 EXPECT_TRUE(file_history_find(&h, mid->filename, &row, &col));
217 1 EXPECT_EQ(row, mid->row);
218 1 EXPECT_EQ(col, mid->col);
219 1 EXPECT_TRUE(file_history_find(&h, last->filename, &row, &col));
220 1 EXPECT_EQ(row, last->row);
221 1 EXPECT_EQ(col, last->col);
222
223 1 row = col = 99;
224 1 EXPECT_FALSE(file_history_find(&h, "/tmp/_", &row, &col));
225 1 EXPECT_EQ(row, 99);
226 1 EXPECT_EQ(col, 99);
227
228 1 file_history_free(&h);
229 1 }
230
231 static const TestEntry tests[] = {
232 TEST(test_history_append),
233 TEST(test_history_search),
234 TEST(test_history_tombstones),
235 TEST(test_file_history_find),
236 };
237
238 const TestGroup history_tests = TEST_GROUP(tests);
239