dte test coverage


Directory: ./
File: test/history.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 182 182 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 const char *filename = "test/data/history";
113 1 History h = {.max_entries = 64};
114 1 history_load(&h, xstrdup(filename), 4096);
115 1 EXPECT_EQ(h.entries.count, 3);
116 1 EXPECT_STREQ(h.filename, filename);
117 1 ASSERT_NONNULL(h.first);
118 1 EXPECT_STREQ(h.first->text, "one");
119 1 ASSERT_NONNULL(h.last);
120 1 EXPECT_STREQ(h.last->text, "three");
121 1 ASSERT_NONNULL(h.first->next);
122 1 EXPECT_STREQ(h.first->next->text, "two");
123 1 ASSERT_NONNULL(h.last->prev);
124 1 EXPECT_STREQ(h.last->prev->text, "two");
125 1 EXPECT_NULL(h.first->prev);
126 1 EXPECT_NULL(h.last->next);
127
128 1 const HistoryEntry *e = h.last;
129 1 EXPECT_STREQ(e->text, "three");
130 1 EXPECT_TRUE(history_search_forward(&h, &e, ""));
131 1 EXPECT_STREQ(e->text, "two");
132 1 EXPECT_TRUE(history_search_forward(&h, &e, ""));
133 1 EXPECT_STREQ(e->text, "one");
134 1 EXPECT_FALSE(history_search_forward(&h, &e, ""));
135
136 1 EXPECT_STREQ(e->text, "one");
137 1 EXPECT_TRUE(history_search_backward(&h, &e, ""));
138 1 EXPECT_STREQ(e->text, "two");
139 1 EXPECT_TRUE(history_search_backward(&h, &e, ""));
140 1 EXPECT_STREQ(e->text, "three");
141 1 EXPECT_FALSE(history_search_backward(&h, &e, ""));
142
143 1 EXPECT_STREQ(e->text, "three");
144 1 EXPECT_TRUE(history_search_forward(&h, &e, "o"));
145 1 EXPECT_STREQ(e->text, "one");
146 1 EXPECT_TRUE(history_search_backward(&h, &e, "th"));
147 1 EXPECT_STREQ(e->text, "three");
148
149 1 free(h.filename);
150 1 filename = "build/test/saved_history";
151 1 h.filename = xstrdup(filename);
152 1 history_save(&h);
153 1 history_free(&h);
154 1 char *buf = NULL;
155 1 ssize_t n = read_file(filename, &buf, 4096);
156 1 EXPECT_EQ(n, 14);
157 1 EXPECT_STREQ(buf, "one\ntwo\nthree\n");
158 1 free(buf);
159 1 }
160
161 // This test is done to ensure the HashMap can handle the constant
162 // churn from insertions and removals (i.e. that it rehashes the
163 // table to clean out tombstones, even when the number of real
164 // entries stops growing).
165 1 static void test_history_tombstone_pressure(TestContext *ctx)
166 {
167 1 History h = {.max_entries = 512};
168
2/2
✓ Branch 0 taken 12000 times.
✓ Branch 1 taken 1 times.
12001 for (unsigned int i = 0; i < 12000; i++) {
169 12000 history_append(&h, uint_to_str(i));
170 }
171
172 1 EXPECT_EQ(h.entries.count, h.max_entries);
173 1 EXPECT_TRUE(h.entries.mask + 1 <= 2048);
174 1 history_free(&h);
175 1 }
176
177 1 static void test_file_history_find(TestContext *ctx)
178 {
179 1 const char fh_filename[] = "test/data/file-history";
180 1 FileHistory h = {.filename = NULL};
181 1 file_history_load(&h, xstrdup(fh_filename), 4096);
182 1 EXPECT_STREQ(h.filename, fh_filename);
183 1 EXPECT_EQ(h.entries.count, 3);
184
185 1 const FileHistoryEntry *first = h.first;
186 1 ASSERT_NONNULL(first);
187 1 ASSERT_NONNULL(first->next);
188 1 EXPECT_NULL(first->prev);
189 1 EXPECT_STREQ(first->filename, "/etc/hosts");
190 1 EXPECT_EQ(first->row, 3);
191 1 EXPECT_EQ(first->col, 42);
192
193 1 const FileHistoryEntry *last = h.last;
194 1 ASSERT_NONNULL(last);
195 1 ASSERT_NONNULL(last->prev);
196 1 EXPECT_NULL(last->next);
197 1 EXPECT_STREQ(last->filename, "/home/user/file.txt");
198 1 EXPECT_EQ(last->row, 4521);
199 1 EXPECT_EQ(last->col, 1);
200
201 1 const FileHistoryEntry *mid = first->next;
202 1 ASSERT_NONNULL(mid);
203 1 EXPECT_PTREQ(mid, last->prev);
204 1 EXPECT_PTREQ(mid->prev, first);
205 1 EXPECT_PTREQ(mid->next, last);
206 1 EXPECT_STREQ(mid->filename, "/tmp/foo");
207 1 EXPECT_EQ(mid->row, 123);
208 1 EXPECT_EQ(mid->col, 456);
209
210 1 unsigned long row = 0, col = 0;
211 1 EXPECT_TRUE(file_history_find(&h, first->filename, &row, &col));
212 1 EXPECT_EQ(row, first->row);
213 1 EXPECT_EQ(col, first->col);
214 1 EXPECT_TRUE(file_history_find(&h, mid->filename, &row, &col));
215 1 EXPECT_EQ(row, mid->row);
216 1 EXPECT_EQ(col, mid->col);
217 1 EXPECT_TRUE(file_history_find(&h, last->filename, &row, &col));
218 1 EXPECT_EQ(row, last->row);
219 1 EXPECT_EQ(col, last->col);
220
221 1 row = col = 99;
222 1 EXPECT_FALSE(file_history_find(&h, "/tmp/_", &row, &col));
223 1 EXPECT_EQ(row, 99);
224 1 EXPECT_EQ(col, 99);
225
226 1 file_history_free(&h);
227 1 }
228
229 static const TestEntry tests[] = {
230 TEST(test_history_append),
231 TEST(test_history_search),
232 TEST(test_history_tombstone_pressure),
233 TEST(test_file_history_find),
234 };
235
236 const TestGroup history_tests = TEST_GROUP(tests);
237