dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 99.9% 3082 / 1 / 3084
Functions: 100.0% 117 / 0 / 117
Branches: 99.1% 107 / 42 / 150

test/util.c
Line Branch Exec Source
1 #include <ctype.h>
2 #include <fcntl.h>
3 #include <limits.h>
4 #include <locale.h>
5 #include <signal.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include "test.h"
11 #include "util/arith.h"
12 #include "util/array.h"
13 #include "util/ascii.h"
14 #include "util/base64.h"
15 #include "util/bit.h"
16 #include "util/fd.h"
17 #include "util/fork-exec.h"
18 #include "util/hashmap.h"
19 #include "util/hashset.h"
20 #include "util/intern.h"
21 #include "util/intmap.h"
22 #include "util/list.h"
23 #include "util/log.h"
24 #include "util/numtostr.h"
25 #include "util/path.h"
26 #include "util/progname.h"
27 #include "util/ptr-array.h"
28 #include "util/readfile.h"
29 #include "util/str-array.h"
30 #include "util/str-util.h"
31 #include "util/string-view.h"
32 #include "util/string.h"
33 #include "util/strtonum.h"
34 #include "util/time-util.h"
35 #include "util/unicode.h"
36 #include "util/utf8.h"
37 #include "util/xmalloc.h"
38 #include "util/xmemmem.h"
39 #include "util/xmemrchr.h"
40 #include "util/xreadwrite.h"
41 #include "util/xsnprintf.h"
42 #include "util/xstdio.h"
43
44 1 static void test_util_macros(TestContext *ctx)
45 {
46 1 EXPECT_EQ(STRLEN(""), 0);
47 1 EXPECT_EQ(STRLEN("a"), 1);
48 1 EXPECT_EQ(STRLEN("123456789"), 9);
49
50 1 EXPECT_EQ(BITSIZE(char), 8);
51 1 EXPECT_EQ(BITSIZE(uint16_t), 16);
52 1 EXPECT_EQ(BITSIZE(uint32_t), 32);
53 1 EXPECT_EQ(BITSIZE(uint64_t), 64);
54 1 EXPECT_EQ(BITSIZE("123456789"), sizeof("123456789") * 8);
55
56 1 EXPECT_EQ(HEX_STR_MAX(char), sizeof("FF") + 1);
57 1 EXPECT_EQ(HEX_STR_MAX(uint16_t), sizeof("FFFF") + 1);
58 1 EXPECT_EQ(HEX_STR_MAX(uint32_t), sizeof("FFFFFFFF") + 1);
59 1 EXPECT_EQ(HEX_STR_MAX(uint64_t), sizeof("FFFFFFFFFFFFFFFF") + 1);
60
61 1 EXPECT_TRUE(DECIMAL_STR_MAX(char) >= sizeof("255"));
62 1 EXPECT_TRUE(DECIMAL_STR_MAX(uint16_t) >= sizeof("65535"));
63 1 EXPECT_TRUE(DECIMAL_STR_MAX(uint32_t) >= sizeof("4294967295"));
64 1 EXPECT_TRUE(DECIMAL_STR_MAX(uint64_t) >= sizeof("18446744073709551615"));
65
66 1 EXPECT_EQ(ARRAYLEN(""), 1);
67 1 EXPECT_EQ(ARRAYLEN("a"), 2);
68 1 EXPECT_EQ(ARRAYLEN("123456789"), 10);
69
70 1 UNUSED const char a2[] = {1, 2};
71 1 UNUSED const int a3[] = {1, 2, 3};
72 1 UNUSED const long long a4[] = {1, 2, 3, 4};
73 1 EXPECT_EQ(ARRAYLEN(a2), 2);
74 1 EXPECT_EQ(ARRAYLEN(a3), 3);
75 1 EXPECT_EQ(ARRAYLEN(a4), 4);
76
77 1 EXPECT_EQ(MIN(0, 1), 0);
78 1 EXPECT_EQ(MIN(99, 100), 99);
79 1 EXPECT_EQ(MIN(-10, 10), -10);
80
81 1 EXPECT_EQ(MIN3(2, 1, 0), 0);
82 1 EXPECT_EQ(MIN3(10, 20, 30), 10);
83 1 EXPECT_EQ(MIN3(10, 20, -10), -10);
84
85 1 EXPECT_EQ(MAX(0, 1), 1);
86 1 EXPECT_EQ(MAX(99, 100), 100);
87 1 EXPECT_EQ(MAX(-10, 10), 10);
88
89 1 EXPECT_EQ(MAX4(1, 2, 3, 4), 4);
90 1 EXPECT_EQ(MAX4(4, 3, 2, 1), 4);
91 1 EXPECT_EQ(MAX4(-10, 10, 0, -20), 10);
92 1 EXPECT_EQ(MAX4(40, 41, 42, 41), 42);
93 1 EXPECT_EQ(MAX4(-10, -20, -50, -80), -10);
94
95 1 EXPECT_EQ(CLAMP(1, 50, 100), 50);
96 1 EXPECT_EQ(CLAMP(200, 50, 100), 100);
97 1 EXPECT_EQ(CLAMP(200, 100, 50), 50); // Invalid edge case (lo > hi)
98 1 EXPECT_EQ(CLAMP(-55, 50, 100), 50);
99 1 EXPECT_EQ(CLAMP(10, -10, -20), -20); // lo > hi
100 1 EXPECT_EQ(CLAMP(10, -20, -10), -10);
101 1 EXPECT_EQ(CLAMP(-15, -10, -20), -20); // lo > hi
102 1 EXPECT_EQ(CLAMP(-15, -20, -10), -15);
103
104 1 EXPECT_TRUE(VERSION_GE(0, 0, 0, 0));
105 1 EXPECT_TRUE(VERSION_GE(1, 0, 0, 0));
106 1 EXPECT_TRUE(VERSION_GE(4, 1, 4, 1));
107 1 EXPECT_TRUE(VERSION_GE(4, 2, 4, 1));
108 1 EXPECT_FALSE(VERSION_GE(0, 1, 1, 0));
109 1 EXPECT_FALSE(VERSION_GE(0, 9, 1, 0));
110 1 EXPECT_FALSE(VERSION_GE(4, 0, 4, 1));
111
112 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(123U), UINT_MAX);
113 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(456UL), ULONG_MAX);
114 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE(789ULL), ULLONG_MAX);
115 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE((size_t)123), SIZE_MAX);
116 1 EXPECT_UINT_EQ(UNSIGNED_MAX_VALUE((uintmax_t)456), UINTMAX_MAX);
117
118 1 int n = snprintf(NULL, 0, "%d", INT_MIN);
119 1 EXPECT_TRUE(n >= STRLEN("-2147483647"));
120 1 EXPECT_TRUE(DECIMAL_STR_MAX(int) > n);
121 1 n = snprintf(NULL, 0, "%llu", ULLONG_MAX);
122 1 EXPECT_TRUE(n >= STRLEN("18446744073709551615"));
123 1 EXPECT_TRUE(DECIMAL_STR_MAX(unsigned long long) > n);
124 1 }
125
126 1 static void test_is_power_of_2(TestContext *ctx)
127 {
128 1 EXPECT_TRUE(IS_POWER_OF_2(1));
129 1 EXPECT_TRUE(IS_POWER_OF_2(2));
130 1 EXPECT_TRUE(IS_POWER_OF_2(4));
131 1 EXPECT_TRUE(IS_POWER_OF_2(8));
132 1 EXPECT_TRUE(IS_POWER_OF_2(4096));
133 1 EXPECT_TRUE(IS_POWER_OF_2(8192));
134 1 EXPECT_TRUE(IS_POWER_OF_2(1ULL << 63));
135
136 1 EXPECT_FALSE(IS_POWER_OF_2(0));
137 1 EXPECT_FALSE(IS_POWER_OF_2(3));
138 1 EXPECT_FALSE(IS_POWER_OF_2(5));
139 1 EXPECT_FALSE(IS_POWER_OF_2(6));
140 1 EXPECT_FALSE(IS_POWER_OF_2(7));
141 1 EXPECT_FALSE(IS_POWER_OF_2(12));
142 1 EXPECT_FALSE(IS_POWER_OF_2(15));
143 1 EXPECT_FALSE(IS_POWER_OF_2(-2));
144 1 EXPECT_FALSE(IS_POWER_OF_2(-10));
145
146 1 const uintmax_t max_pow2 = ~(UINTMAX_MAX >> 1);
147 1 EXPECT_TRUE(max_pow2 >= 1ULL << 63);
148 1 EXPECT_TRUE(IS_POWER_OF_2(max_pow2));
149 1 EXPECT_UINT_EQ(max_pow2 << 1, 0);
150
151
2/2
✓ Branch 37 → 22 taken 61 times.
✓ Branch 37 → 38 taken 1 time.
63 for (uintmax_t i = max_pow2; i > 4; i >>= 1) {
152 61 EXPECT_TRUE(IS_POWER_OF_2(i));
153
2/2
✓ Branch 35 → 26 taken 183 times.
✓ Branch 35 → 36 taken 61 times.
305 for (uintmax_t j = 1; j < 4; j++) {
154 366 EXPECT_FALSE(IS_POWER_OF_2(i + j));
155 366 EXPECT_FALSE(IS_POWER_OF_2(i - j));
156 }
157 }
158 1 }
159
160 // Note: some of these tests are more for the sake of AddressSanitizer
161 // coverage than making actual assertions about the code
162 1 static void test_xmalloc(TestContext *ctx)
163 {
164 1 char *str = xmalloc(8);
165 1 ASSERT_NONNULL(str);
166 1 memcpy(str, "1234567", 8);
167 1 EXPECT_STREQ(str, "1234567");
168 1 free(str);
169
170 1 str = xstrdup("foobar");
171 1 EXPECT_STREQ(str, "foobar");
172 1 free(str);
173
174 1 str = xasprintf("%s %d", "xyz", 12340);
175 1 EXPECT_STREQ(str, "xyz 12340");
176 1 free(str);
177
178 1 str = xcalloc(4, 1);
179 1 ASSERT_NONNULL(str);
180 1 EXPECT_MEMEQ(str, 4, "\0\0\0\0", 4);
181 1 free(str);
182
183 1 str = xcalloc1(4);
184 1 ASSERT_NONNULL(str);
185 1 EXPECT_MEMEQ(str, 4, "\0\0\0\0", 4);
186 1 free(str);
187
188 1 str = xstrslice("one two three", 4, 7);
189 1 EXPECT_STREQ(str, "two");
190 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice("one two three", 4, 7), str);
191 1 free(str);
192
193 1 str = xmemjoin3(STRN("123"), STRN("::"), STRN("456") + 1);
194 1 EXPECT_STREQ(str, "123::456");
195 1 free(str);
196
197 1 str = xmemjoin4(STRN("AA"), STRN("BB"), STRN("CC"), STRN("DD") + 1);
198 1 EXPECT_STREQ(str, "AABBCCDD");
199 1 free(str);
200
201 // All xmemjoin*() functions allow NULL pointers when the corresponding
202 // length argument is 0, but the sum of all lengths must be at least 1,
203 // otherwise the BUG_ON() assertion in xmalloc() will fail
204 1 str = xmemjoin4(NULL, 0, NULL, 0, NULL, 0, "", 1);
205 1 EXPECT_STREQ(str, "");
206 1 free(str);
207
208 1 str = xcalloc(4, sizeof(str[0]));
209 1 ASSERT_NONNULL(str);
210 1 EXPECT_EQ(str[3], 0);
211 1 str = xrenew(str, 64);
212 1 ASSERT_NONNULL(str);
213 1 str[63] = 'p';
214 1 EXPECT_EQ(str[63], 'p');
215 1 free(str);
216 1 }
217
218 1 static void test_xstreq(TestContext *ctx)
219 {
220 1 EXPECT_TRUE(xstreq("foo", "foo"));
221 1 EXPECT_TRUE(xstreq("foo\0\n", "foo\0\0"));
222 1 EXPECT_TRUE(xstreq("\0foo", "\0bar"));
223 1 EXPECT_TRUE(xstreq(NULL, NULL));
224 1 EXPECT_FALSE(xstreq("foo", "bar"));
225 1 EXPECT_FALSE(xstreq("abc", "abcd"));
226 1 EXPECT_FALSE(xstreq("abcd", "abc"));
227 1 EXPECT_FALSE(xstreq(NULL, ""));
228 1 EXPECT_FALSE(xstreq("", NULL));
229 1 }
230
231 1 static void test_xstrrchr(TestContext *ctx)
232 {
233 1 static const char str[] = "12345432";
234 1 EXPECT_PTREQ(xstrrchr(str, '1'), str);
235 1 EXPECT_PTREQ(xstrrchr(str, '2'), str + 7);
236 1 EXPECT_PTREQ(xstrrchr(str, '5'), str + 4);
237 1 EXPECT_PTREQ(xstrrchr(str, '\0'), str + sizeof(str) - 1);
238 1 }
239
240 1 static void test_xmempcpy(TestContext *ctx)
241 {
242 1 char buf[16] = "12345678";
243 1 EXPECT_PTREQ(xmempcpy4(buf, NULL, 0, NULL, 0, NULL, 0, NULL, 0), buf);
244 1 EXPECT_STREQ(buf, "12345678");
245
246 1 EXPECT_PTREQ(xmempcpy4(buf, "a", 1, "b", 1, "c", 1, "d", 2), buf + 5);
247 1 EXPECT_STREQ(buf, "abcd");
248 1 }
249
250 1 static void test_str_has_sv_prefix(TestContext *ctx)
251 {
252 1 EXPECT_TRUE(str_has_sv_prefix("xyz", strview("xyz")));
253 1 EXPECT_FALSE(str_has_sv_prefix("xyz", strview("x.z")));
254 1 EXPECT_TRUE(str_has_sv_prefix("12345678", string_view("1234..", 4)));
255 1 EXPECT_FALSE(str_has_sv_prefix("12345678", string_view("1234..", 5)));
256 1 EXPECT_TRUE(str_has_sv_prefix("x", strview("")));
257 1 EXPECT_TRUE(str_has_sv_prefix("", strview("")));
258 1 EXPECT_TRUE(str_has_sv_prefix("foo", string_view("bar", 0)));
259 1 EXPECT_FALSE(str_has_sv_prefix("foo", string_view("bar", 3)));
260 1 EXPECT_FALSE(str_has_sv_prefix("aaa", string_view("aaa", 4)));
261 1 }
262
263 1 static void test_str_has_prefix(TestContext *ctx)
264 {
265 1 EXPECT_TRUE(str_has_prefix("foo", "foo"));
266 1 EXPECT_TRUE(str_has_prefix("foobar", "foo"));
267 1 EXPECT_TRUE(str_has_prefix("xyz", "xy"));
268 1 EXPECT_TRUE(str_has_prefix("a", "a"));
269 1 EXPECT_FALSE(str_has_prefix("foobar", "bar"));
270 1 EXPECT_FALSE(str_has_prefix("foo", "foobar"));
271 1 EXPECT_FALSE(str_has_prefix("xyz", "xyz."));
272 1 EXPECT_FALSE(str_has_prefix("ab", "b"));
273 1 EXPECT_FALSE(str_has_prefix("123", "xyz"));
274 1 }
275
276 1 static void test_hex_decode(TestContext *ctx)
277 {
278 1 EXPECT_EQ(hex_decode('0'), 0);
279 1 EXPECT_EQ(hex_decode('1'), 1);
280 1 EXPECT_EQ(hex_decode('9'), 9);
281 1 EXPECT_EQ(hex_decode('a'), 10);
282 1 EXPECT_EQ(hex_decode('A'), 10);
283 1 EXPECT_EQ(hex_decode('f'), 15);
284 1 EXPECT_EQ(hex_decode('F'), 15);
285 1 EXPECT_EQ(hex_decode('g'), HEX_INVALID);
286 1 EXPECT_EQ(hex_decode('G'), HEX_INVALID);
287 1 EXPECT_EQ(hex_decode('o'), HEX_INVALID);
288 1 EXPECT_EQ(hex_decode('p'), HEX_INVALID);
289 1 EXPECT_EQ(hex_decode('q'), HEX_INVALID);
290 1 EXPECT_EQ(hex_decode('`'), HEX_INVALID);
291 1 EXPECT_EQ(hex_decode('@'), HEX_INVALID);
292 1 EXPECT_EQ(hex_decode('/'), HEX_INVALID);
293 1 EXPECT_EQ(hex_decode(':'), HEX_INVALID);
294 1 EXPECT_EQ(hex_decode(' '), HEX_INVALID);
295 1 EXPECT_EQ(hex_decode('~'), HEX_INVALID);
296 1 EXPECT_EQ(hex_decode('\0'), HEX_INVALID);
297 1 EXPECT_EQ(hex_decode(0xFF), HEX_INVALID);
298
299
2/2
✓ Branch 25 → 23 taken 10 times.
✓ Branch 25 → 29 taken 1 time.
12 for (unsigned int i = '0'; i <= '9'; i++) {
300 10 IEXPECT_EQ(hex_decode(i), i - '0');
301 }
302
303
2/2
✓ Branch 29 → 26 taken 6 times.
✓ Branch 29 → 35 taken 1 time.
7 for (unsigned int i = 'A'; i <= 'F'; i++) {
304 6 unsigned int expected = 10 + (i - 'A');
305 6 IEXPECT_EQ(hex_decode(i), expected);
306 6 IEXPECT_EQ(hex_decode(ascii_tolower(i)), expected);
307 }
308
309
2/2
✓ Branch 35 → 30 taken 256 times.
✓ Branch 35 → 36 taken 1 time.
257 for (unsigned int i = 0; i < 256; i++) {
310 256 unsigned int decoded = hex_decode(i);
311
4/4
✓ Branch 30 → 31 taken 62 times.
✓ Branch 30 → 33 taken 194 times.
✓ Branch 31 → 32 taken 22 times.
✓ Branch 31 → 33 taken 40 times.
256 bool is_hex = ascii_isalnum(i) && ascii_toupper(i) <= 'F';
312 256 IEXPECT_EQ(decoded, is_hex ? (decoded & 0xF) : HEX_INVALID);
313 }
314 1 }
315
316 1 static void test_hex_encode_byte(TestContext *ctx)
317 {
318 1 char buf[4] = "";
319 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0x00), "00", 2);
320 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0x05), "05", 2);
321 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0x10), "10", 2);
322 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0x1b), "1b", 2);
323 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0xee), "ee", 2);
324 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0xfe), "fe", 2);
325 1 EXPECT_MEMEQ(buf, hex_encode_byte(buf, 0xff), "ff", 2);
326 1 }
327
328 1 static void test_ascii(TestContext *ctx)
329 {
330 1 EXPECT_EQ(ascii_tolower('A'), 'a');
331 1 EXPECT_EQ(ascii_tolower('F'), 'f');
332 1 EXPECT_EQ(ascii_tolower('Z'), 'z');
333 1 EXPECT_EQ(ascii_tolower('a'), 'a');
334 1 EXPECT_EQ(ascii_tolower('f'), 'f');
335 1 EXPECT_EQ(ascii_tolower('z'), 'z');
336 1 EXPECT_EQ(ascii_tolower('9'), '9');
337 1 EXPECT_EQ(ascii_tolower('~'), '~');
338 1 EXPECT_EQ(ascii_tolower('\0'), '\0');
339
340 1 EXPECT_EQ(ascii_toupper('a'), 'A');
341 1 EXPECT_EQ(ascii_toupper('f'), 'F');
342 1 EXPECT_EQ(ascii_toupper('z'), 'Z');
343 1 EXPECT_EQ(ascii_toupper('A'), 'A');
344 1 EXPECT_EQ(ascii_toupper('F'), 'F');
345 1 EXPECT_EQ(ascii_toupper('Z'), 'Z');
346 1 EXPECT_EQ(ascii_toupper('9'), '9');
347 1 EXPECT_EQ(ascii_toupper('~'), '~');
348 1 EXPECT_EQ(ascii_toupper('\0'), '\0');
349
350 1 EXPECT_TRUE(ascii_isspace(' '));
351 1 EXPECT_TRUE(ascii_isspace('\t'));
352 1 EXPECT_TRUE(ascii_isspace('\r'));
353 1 EXPECT_TRUE(ascii_isspace('\n'));
354 1 EXPECT_FALSE(ascii_isspace('\v')); // (differs from POSIX)
355 1 EXPECT_FALSE(ascii_isspace('\f')); // (differs from POSIX)
356 1 EXPECT_FALSE(ascii_isspace('\0'));
357 1 EXPECT_FALSE(ascii_isspace('a'));
358 1 EXPECT_FALSE(ascii_isspace(0x7F));
359 1 EXPECT_FALSE(ascii_isspace(0x80));
360
361 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=cntrl,-%3Calert
362 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=may%20add%20additional%20characters
363 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap06.html
364 1 EXPECT_TRUE(ascii_iscntrl('\0')); // <NUL>
365 1 EXPECT_TRUE(ascii_iscntrl('\a')); // <alert>, <BEL>
366 1 EXPECT_TRUE(ascii_iscntrl('\b')); // <backspace>, <BS>
367 1 EXPECT_TRUE(ascii_iscntrl('\t')); // <tab>, <HT>
368 1 EXPECT_TRUE(ascii_iscntrl('\n')); // <newline>, <LF>
369 1 EXPECT_TRUE(ascii_iscntrl('\v')); // <vertical-tab>, <VT>
370 1 EXPECT_TRUE(ascii_iscntrl('\f')); // <form-feed>, <FF>
371 1 EXPECT_TRUE(ascii_iscntrl('\r')); // <carriage-return>, <CR>
372 1 EXPECT_TRUE(ascii_iscntrl(0x0E)); // <SO>
373 1 EXPECT_TRUE(ascii_iscntrl(0x1F)); // <IS1>, <US>
374 1 EXPECT_TRUE(ascii_iscntrl(0x7F)); // <DEL>
375 1 EXPECT_FALSE(ascii_iscntrl(' ')); // <space>
376 1 EXPECT_FALSE(ascii_iscntrl('a')); // <a>
377 1 EXPECT_FALSE(ascii_iscntrl('~')); // <tilde>
378 1 EXPECT_FALSE(ascii_iscntrl(0x80));
379 1 EXPECT_FALSE(ascii_iscntrl(0xFF));
380
381 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=cntrl,-%3Calert
382 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=space,-%3Ctab
383 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=may%20add%20additional%20characters
384 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap06.html
385 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\0')); // <NUL>
386 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\a')); // <alert>, <BEL>
387 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\b')); // <backspace>, <BS>
388 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x0E)); // <SO>
389 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x1F)); // <IS1>, <US>
390 1 EXPECT_TRUE(ascii_is_nonspace_cntrl(0x7F)); // <DEL>
391 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\v')); // <vertical-tab>, <VT> (differs from POSIX)
392 1 EXPECT_TRUE(ascii_is_nonspace_cntrl('\f')); // <form-feed>, <FF> (differs from POSIX)
393 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\t')); // <tab>, <HT>
394 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\n')); // <newline>, <LF>
395 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('\r')); // <carriage-return>, <CR>
396 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(' ')); // <space>
397 1 EXPECT_FALSE(ascii_is_nonspace_cntrl('a'));
398 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0x7E));
399 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0x80));
400 1 EXPECT_FALSE(ascii_is_nonspace_cntrl(0xFF));
401
402 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=punct,-%3Cexclamation
403 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01:~:text=may%20add%20additional%20characters
404 1 EXPECT_TRUE(ascii_ispunct('!'));
405 1 EXPECT_TRUE(ascii_ispunct('"'));
406 1 EXPECT_TRUE(ascii_ispunct('#'));
407 1 EXPECT_TRUE(ascii_ispunct('$'));
408 1 EXPECT_TRUE(ascii_ispunct('%'));
409 1 EXPECT_TRUE(ascii_ispunct('&'));
410 1 EXPECT_TRUE(ascii_ispunct('\''));
411 1 EXPECT_TRUE(ascii_ispunct('('));
412 1 EXPECT_TRUE(ascii_ispunct(')'));
413 1 EXPECT_TRUE(ascii_ispunct('*'));
414 1 EXPECT_TRUE(ascii_ispunct('+'));
415 1 EXPECT_TRUE(ascii_ispunct(','));
416 1 EXPECT_TRUE(ascii_ispunct('-'));
417 1 EXPECT_TRUE(ascii_ispunct('.'));
418 1 EXPECT_TRUE(ascii_ispunct('/'));
419 1 EXPECT_TRUE(ascii_ispunct(':'));
420 1 EXPECT_TRUE(ascii_ispunct(';'));
421 1 EXPECT_TRUE(ascii_ispunct('<'));
422 1 EXPECT_TRUE(ascii_ispunct('='));
423 1 EXPECT_TRUE(ascii_ispunct('>'));
424 1 EXPECT_TRUE(ascii_ispunct('?'));
425 1 EXPECT_TRUE(ascii_ispunct('@'));
426 1 EXPECT_TRUE(ascii_ispunct('['));
427 1 EXPECT_TRUE(ascii_ispunct('\\'));
428 1 EXPECT_TRUE(ascii_ispunct(']'));
429 1 EXPECT_TRUE(ascii_ispunct('^'));
430 1 EXPECT_TRUE(ascii_ispunct('_'));
431 1 EXPECT_TRUE(ascii_ispunct('`'));
432 1 EXPECT_TRUE(ascii_ispunct('{'));
433 1 EXPECT_TRUE(ascii_ispunct('|'));
434 1 EXPECT_TRUE(ascii_ispunct('}'));
435 1 EXPECT_TRUE(ascii_ispunct('~'));
436 1 EXPECT_FALSE(ascii_ispunct(' '));
437 1 EXPECT_FALSE(ascii_ispunct('0'));
438 1 EXPECT_FALSE(ascii_ispunct('9'));
439 1 EXPECT_FALSE(ascii_ispunct('A'));
440 1 EXPECT_FALSE(ascii_ispunct('Z'));
441 1 EXPECT_FALSE(ascii_ispunct('a'));
442 1 EXPECT_FALSE(ascii_ispunct('z'));
443 1 EXPECT_FALSE(ascii_ispunct(0x00));
444 1 EXPECT_FALSE(ascii_ispunct(0x7F));
445 1 EXPECT_FALSE(ascii_ispunct(0xFF));
446
447 1 EXPECT_TRUE(ascii_isdigit('0'));
448 1 EXPECT_TRUE(ascii_isdigit('1'));
449 1 EXPECT_TRUE(ascii_isdigit('9'));
450 1 EXPECT_FALSE(ascii_isdigit('a'));
451 1 EXPECT_FALSE(ascii_isdigit('f'));
452 1 EXPECT_FALSE(ascii_isdigit('/'));
453 1 EXPECT_FALSE(ascii_isdigit(':'));
454 1 EXPECT_FALSE(ascii_isdigit('\0'));
455 1 EXPECT_FALSE(ascii_isdigit(0xFF));
456
457 1 EXPECT_TRUE(ascii_isprint(' '));
458 1 EXPECT_TRUE(ascii_isprint('!'));
459 1 EXPECT_TRUE(ascii_isprint('/'));
460 1 EXPECT_TRUE(ascii_isprint('a'));
461 1 EXPECT_TRUE(ascii_isprint('z'));
462 1 EXPECT_TRUE(ascii_isprint('0'));
463 1 EXPECT_TRUE(ascii_isprint('_'));
464 1 EXPECT_TRUE(ascii_isprint('~'));
465 1 EXPECT_FALSE(ascii_isprint('\0'));
466 1 EXPECT_FALSE(ascii_isprint('\t'));
467 1 EXPECT_FALSE(ascii_isprint('\n'));
468 1 EXPECT_FALSE(ascii_isprint('\r'));
469 1 EXPECT_FALSE(ascii_isprint(0x1F));
470 1 EXPECT_FALSE(ascii_isprint(0x7F));
471 1 EXPECT_FALSE(ascii_isprint(0x80));
472 1 EXPECT_FALSE(ascii_isprint(0xFF));
473
474 1 EXPECT_TRUE(is_word_byte('a'));
475 1 EXPECT_TRUE(is_word_byte('z'));
476 1 EXPECT_TRUE(is_word_byte('A'));
477 1 EXPECT_TRUE(is_word_byte('Z'));
478 1 EXPECT_TRUE(is_word_byte('0'));
479 1 EXPECT_TRUE(is_word_byte('9'));
480 1 EXPECT_TRUE(is_word_byte('_'));
481 1 EXPECT_TRUE(is_word_byte(0x80));
482 1 EXPECT_TRUE(is_word_byte(0xFF));
483 1 EXPECT_FALSE(is_word_byte('-'));
484 1 EXPECT_FALSE(is_word_byte('.'));
485 1 EXPECT_FALSE(is_word_byte(0x7F));
486 1 EXPECT_FALSE(is_word_byte(0x00));
487
488 1 EXPECT_TRUE(is_regex_special_char('$'));
489 1 EXPECT_TRUE(is_regex_special_char('('));
490 1 EXPECT_TRUE(is_regex_special_char(')'));
491 1 EXPECT_TRUE(is_regex_special_char('*'));
492 1 EXPECT_TRUE(is_regex_special_char('+'));
493 1 EXPECT_TRUE(is_regex_special_char('.'));
494 1 EXPECT_TRUE(is_regex_special_char('?'));
495 1 EXPECT_TRUE(is_regex_special_char('['));
496 1 EXPECT_TRUE(is_regex_special_char('^'));
497 1 EXPECT_TRUE(is_regex_special_char('{'));
498 1 EXPECT_TRUE(is_regex_special_char('|'));
499 1 EXPECT_TRUE(is_regex_special_char('\\'));
500 1 EXPECT_FALSE(is_regex_special_char('"'));
501 1 EXPECT_FALSE(is_regex_special_char('&'));
502 1 EXPECT_FALSE(is_regex_special_char(','));
503 1 EXPECT_FALSE(is_regex_special_char('0'));
504 1 EXPECT_FALSE(is_regex_special_char('@'));
505 1 EXPECT_FALSE(is_regex_special_char('A'));
506 1 EXPECT_FALSE(is_regex_special_char('\''));
507 1 EXPECT_FALSE(is_regex_special_char(']'));
508 1 EXPECT_FALSE(is_regex_special_char('_'));
509 1 EXPECT_FALSE(is_regex_special_char('z'));
510 1 EXPECT_FALSE(is_regex_special_char('}'));
511 1 EXPECT_FALSE(is_regex_special_char('~'));
512 1 EXPECT_FALSE(is_regex_special_char(0x00));
513 1 EXPECT_FALSE(is_regex_special_char(0x80));
514 1 EXPECT_FALSE(is_regex_special_char(0xFF));
515
516 1 EXPECT_TRUE(ascii_streq_icase("", ""));
517 1 EXPECT_TRUE(ascii_streq_icase("a", "a"));
518 1 EXPECT_TRUE(ascii_streq_icase("a", "A"));
519 1 EXPECT_TRUE(ascii_streq_icase("z", "Z"));
520 1 EXPECT_TRUE(ascii_streq_icase("cx", "CX"));
521 1 EXPECT_TRUE(ascii_streq_icase("ABC..XYZ", "abc..xyz"));
522 1 EXPECT_TRUE(ascii_streq_icase("Ctrl", "CTRL"));
523 1 EXPECT_FALSE(ascii_streq_icase("a", ""));
524 1 EXPECT_FALSE(ascii_streq_icase("", "a"));
525 1 EXPECT_FALSE(ascii_streq_icase("Ctrl+", "CTRL"));
526 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "CTRL+"));
527 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "Ctr"));
528 1 EXPECT_FALSE(ascii_streq_icase("Ctrl", "CtrM"));
529
530 1 EXPECT_EQ(ascii_strcmp_icase("", ""), 0);
531 1 EXPECT_EQ(ascii_strcmp_icase("A", "A"), 0);
532 1 EXPECT_EQ(ascii_strcmp_icase("xyz", ""), 'x');
533 1 EXPECT_EQ(ascii_strcmp_icase("", "xyz"), -'x');
534 1 EXPECT_EQ(ascii_strcmp_icase("xyz", "xy"), 'z');
535 1 EXPECT_EQ(ascii_strcmp_icase("xy", "xyz"), -'z');
536 1 EXPECT_EQ(ascii_strcmp_icase("\xFF", "\xFE"), 1);
537 1 EXPECT_EQ(ascii_strcmp_icase("\xFE", "\xFF"), -1);
538 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\xC1", "\x80\xFF\x01"), 0xC0);
539 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\x01", "\x80\xFF\xC1"), -0xC0);
540 1 EXPECT_EQ(ascii_strcmp_icase("\x80\xFF\x01", "\x80"), 0xFF);
541 1 EXPECT_EQ(ascii_strcmp_icase("\x80", "\x80\xFF\x01"), -0xFF);
542
543 // Query the current locale
544 1 const char *locale = setlocale(LC_CTYPE, NULL);
545 1 ASSERT_NONNULL(locale);
546
547 // Copy the locale string (which may be in static storage)
548 1 char *saved_locale = xstrdup(locale);
549
550 // Check that the ascii_is*() functions behave like their corresponding
551 // <ctype.h> macros, when in the standard C/POSIX locale.
552 // See also: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01_01
553 1 ASSERT_NONNULL(setlocale(LC_CTYPE, "C"));
554
2/2
✓ Branch 260 → 225 taken 257 times.
✓ Branch 260 → 261 taken 1 time.
259 for (int i = -1; i < 256; i++) {
555 257 EXPECT_EQ(ascii_isalpha(i), !!isalpha(i));
556 257 EXPECT_EQ(ascii_isalnum(i), !!isalnum(i));
557 257 EXPECT_EQ(ascii_islower(i), !!islower(i));
558 257 EXPECT_EQ(ascii_isupper(i), !!isupper(i));
559 257 EXPECT_EQ(ascii_isdigit(i), !!isdigit(i));
560 257 EXPECT_EQ(ascii_isblank(i), !!isblank(i));
561 257 EXPECT_EQ(ascii_isprint(i), !!isprint(i));
562 257 EXPECT_EQ(ascii_isxdigit(i), !!isxdigit(i));
563 257 EXPECT_EQ(u_is_ascii_upper(i), !!isupper(i));
564 461 EXPECT_EQ(is_alpha_or_underscore(i), !!isalpha(i) || i == '_');
565 451 EXPECT_EQ(is_alnum_or_underscore(i), !!isalnum(i) || i == '_');
566
2/2
✓ Branch 242 → 243 taken 255 times.
✓ Branch 242 → 245 taken 2 times.
257 if (i != '\v' && i != '\f') {
567 255 EXPECT_EQ(ascii_isspace(i), !!isspace(i));
568 }
569
2/2
✓ Branch 244 → 245 taken 254 times.
✓ Branch 244 → 259 taken 1 time.
255 if (i != -1) {
570 321 EXPECT_EQ(is_word_byte(i), !!isalnum(i) || i == '_' || i >= 0x80);
571 256 EXPECT_EQ(ascii_tolower(i), tolower(i));
572 256 EXPECT_EQ(ascii_toupper(i), toupper(i));
573 }
574 }
575
576 // Restore the original locale
577 1 ASSERT_NONNULL(setlocale(LC_CTYPE, saved_locale));
578 1 free(saved_locale);
579 1 }
580
581 1 static void test_mem_equal(TestContext *ctx)
582 {
583 1 static const char s1[] = "abcxyz";
584 1 static const char s2[] = "abcXYZ";
585 1 EXPECT_TRUE(mem_equal(NULL, NULL, 0));
586 1 EXPECT_TRUE(mem_equal(s1, s2, 0));
587 1 EXPECT_TRUE(mem_equal(s1, s2, 1));
588 1 EXPECT_TRUE(mem_equal(s1, s2, 2));
589 1 EXPECT_TRUE(mem_equal(s1, s2, 3));
590 1 EXPECT_TRUE(mem_equal(s1 + 1, s2 + 1, 2));
591 1 EXPECT_TRUE(mem_equal(s1 + 6, s2 + 6, 1));
592 1 EXPECT_FALSE(mem_equal(s1, s2, 4));
593 1 EXPECT_FALSE(mem_equal(s1, s2, 5));
594 1 EXPECT_FALSE(mem_equal(s1, s2, 6));
595 1 EXPECT_FALSE(mem_equal(s1, s2, 7));
596 1 }
597
598 1 static void test_mem_equal_icase(TestContext *ctx)
599 {
600 1 static const char s1[8] = "Ctrl+Up";
601 1 static const char s2[8] = "CTRL+U_";
602 1 EXPECT_TRUE(mem_equal_icase(NULL, NULL, 0));
603 1 EXPECT_TRUE(mem_equal_icase(NULL, s1, 0));
604 1 EXPECT_TRUE(mem_equal_icase(s1, NULL, 0));
605 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 0));
606 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 1));
607 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 2));
608 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 3));
609 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 4));
610 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 5));
611 1 EXPECT_TRUE(mem_equal_icase(s1, s2, 6));
612 1 EXPECT_FALSE(mem_equal_icase(s1, s2, 7));
613 1 EXPECT_FALSE(mem_equal_icase(s1, s2, 8));
614 1 }
615
616 1 static void test_base64_decode(TestContext *ctx)
617 {
618 1 EXPECT_EQ(base64_decode('A'), 0);
619 1 EXPECT_EQ(base64_decode('Z'), 25);
620 1 EXPECT_EQ(base64_decode('a'), 26);
621 1 EXPECT_EQ(base64_decode('z'), 51);
622 1 EXPECT_EQ(base64_decode('0'), 52);
623 1 EXPECT_EQ(base64_decode('9'), 61);
624 1 EXPECT_EQ(base64_decode('+'), 62);
625 1 EXPECT_EQ(base64_decode('/'), 63);
626
627 1 EXPECT_EQ(base64_encode_table[0], 'A');
628 1 EXPECT_EQ(base64_encode_table[25], 'Z');
629 1 EXPECT_EQ(base64_encode_table[26], 'a');
630 1 EXPECT_EQ(base64_encode_table[51], 'z');
631 1 EXPECT_EQ(base64_encode_table[52], '0');
632 1 EXPECT_EQ(base64_encode_table[61], '9');
633 1 EXPECT_EQ(base64_encode_table[62], '+');
634 1 EXPECT_EQ(base64_encode_table[63], '/');
635
636 1 EXPECT_EQ(base64_decode('='), BASE64_PADDING);
637 1 EXPECT_EQ(base64_decode(' '), BASE64_INVALID);
638 1 EXPECT_EQ(base64_decode('*'), BASE64_INVALID);
639 1 EXPECT_EQ(base64_decode(','), BASE64_INVALID);
640 1 EXPECT_EQ(base64_decode(':'), BASE64_INVALID);
641 1 EXPECT_EQ(base64_decode('?'), BASE64_INVALID);
642 1 EXPECT_EQ(base64_decode('@'), BASE64_INVALID);
643 1 EXPECT_EQ(base64_decode('['), BASE64_INVALID);
644 1 EXPECT_EQ(base64_decode('`'), BASE64_INVALID);
645 1 EXPECT_EQ(base64_decode('{'), BASE64_INVALID);
646 1 EXPECT_EQ(base64_decode('~'), BASE64_INVALID);
647 1 EXPECT_EQ(base64_decode('}'), BASE64_INVALID);
648 1 EXPECT_EQ(base64_decode(0), BASE64_INVALID);
649 1 EXPECT_EQ(base64_decode(127), BASE64_INVALID);
650 1 EXPECT_EQ(base64_decode(128), BASE64_INVALID);
651 1 EXPECT_EQ(base64_decode(255), BASE64_INVALID);
652
653
2/2
✓ Branch 37 → 35 taken 26 times.
✓ Branch 37 → 40 taken 1 time.
28 for (unsigned int i = 'A'; i <= 'Z'; i++) {
654 26 IEXPECT_EQ(base64_decode(i), i - 'A');
655 }
656
657
2/2
✓ Branch 40 → 38 taken 26 times.
✓ Branch 40 → 43 taken 1 time.
27 for (unsigned int i = 'a'; i <= 'z'; i++) {
658 26 IEXPECT_EQ(base64_decode(i), (i - 'a') + 26);
659 }
660
661
2/2
✓ Branch 43 → 41 taken 10 times.
✓ Branch 43 → 51 taken 1 time.
11 for (unsigned int i = '0'; i <= '9'; i++) {
662 10 IEXPECT_EQ(base64_decode(i), (i - '0') + 52);
663 }
664
665
2/2
✓ Branch 51 → 44 taken 256 times.
✓ Branch 51 → 52 taken 1 time.
257 for (unsigned int i = 0; i < 256; i++) {
666 256 unsigned int val = base64_decode(i);
667
4/4
✓ Branch 44 → 45 taken 194 times.
✓ Branch 44 → 46 taken 62 times.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 48 taken 192 times.
256 if (ascii_isalnum(i) || i == '+' || i == '/') {
668 64 IEXPECT_EQ(val, val & 63);
669 64 IEXPECT_EQ(i, base64_encode_table[val & 63]);
670 } else {
671 192 IEXPECT_EQ(val, val & 192);
672 }
673 256 IEXPECT_EQ(val, base64_decode_branchy(i));
674 }
675 1 }
676
677 1 static void test_base64_encode_block(TestContext *ctx)
678 {
679 1 char buf[16];
680 1 size_t n = base64_encode_block(STRN("xyz"), buf, sizeof(buf));
681 1 EXPECT_MEMEQ(buf, n, "eHl6", 4);
682
683 1 n = base64_encode_block(STRN("123456"), buf, sizeof(buf));
684 1 EXPECT_MEMEQ(buf, n, "MTIzNDU2", 8);
685
686 1 n = base64_encode_block(STRN("a == *x++"), buf, sizeof(buf));
687 1 EXPECT_MEMEQ(buf, n, "YSA9PSAqeCsr", 12);
688 1 }
689
690 1 static void test_base64_encode_final(TestContext *ctx)
691 {
692 1 char buf[4];
693 1 base64_encode_final(STRN("+"), buf);
694 1 EXPECT_MEMEQ(buf, 4, "Kw==", 4);
695
696 1 base64_encode_final(STRN(".."), buf);
697 1 EXPECT_MEMEQ(buf, 4, "Li4=", 4);
698
699 1 base64_encode_final(STRN("~."), buf);
700 1 EXPECT_MEMEQ(buf, 4, "fi4=", 4);
701
702 1 base64_encode_final(STRN("\xC2\xA9"), buf);
703 1 EXPECT_MEMEQ(buf, 4, "wqk=", 4);
704 1 }
705
706 1 static void test_string(TestContext *ctx)
707 {
708 1 String s = string_new(0);
709 1 EXPECT_EQ(s.len, 0);
710 1 EXPECT_EQ(s.alloc, 0);
711 1 EXPECT_NULL(s.buffer);
712 1 EXPECT_STRING_EQ_CSTRING(&s, "");
713
714 1 char *cstr = string_clone_cstring(&s);
715 1 EXPECT_STREQ(cstr, "");
716 1 free(cstr);
717 1 EXPECT_EQ(s.len, 0);
718 1 EXPECT_EQ(s.alloc, 0);
719 1 EXPECT_NULL(s.buffer);
720
721 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 0x1F4AF), 4);
722 1 EXPECT_STRING_EQ_CSTRING(&s, "\xF0\x9F\x92\xAF");
723 1 EXPECT_STREQ(string_borrow_cstring(&s), "\xF0\x9F\x92\xAF");
724
725 1 EXPECT_EQ(string_append_cstring(&s, "test"), 4);
726 1 EXPECT_STRING_EQ_CSTRING(&s, "\xF0\x9F\x92\xAFtest");
727
728 1 string_remove(&s, 0, 5);
729 1 EXPECT_EQ(s.len, 3);
730 1 EXPECT_STRING_EQ_CSTRING(&s, "est");
731
732 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 't'), 1);
733 1 EXPECT_STRING_EQ_CSTRING(&s, "test");
734
735 1 EXPECT_EQ(string_clear(&s), 4);
736 1 EXPECT_EQ(s.len, 0);
737 1 EXPECT_EQ(string_insert_codepoint(&s, 0, 0x0E01), 3);
738 1 EXPECT_STRING_EQ_CSTRING(&s, "\xE0\xB8\x81");
739
740 1 EXPECT_EQ(string_clear(&s), 3);
741 1 string_sprintf(&s, "%d %s\n", 88, "test");
742 1 EXPECT_STRING_EQ_CSTRING(&s, "88 test\n");
743
744 1 string_free(&s);
745 1 EXPECT_EQ(s.len, 0);
746 1 EXPECT_EQ(s.alloc, 0);
747 1 EXPECT_NULL(s.buffer);
748
749
2/2
✓ Branch 43 → 41 taken 40 times.
✓ Branch 43 → 44 taken 1 time.
42 for (size_t i = 0; i < 40; i++) {
750 40 string_append_byte(&s, 'a');
751 }
752
753 1 EXPECT_EQ(s.len, 40);
754 1 cstr = string_steal_cstring(&s);
755 1 EXPECT_EQ(s.len, 0);
756 1 EXPECT_EQ(s.alloc, 0);
757 1 EXPECT_NULL(s.buffer);
758 1 EXPECT_STREQ(cstr, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
759 1 free(cstr);
760
761 1 s = string_new(12);
762 1 EXPECT_EQ(s.len, 0);
763 1 EXPECT_EQ3(s.alloc, 16, STRING_ALLOC_MULTIPLE);
764 1 ASSERT_NONNULL(s.buffer);
765
766 1 EXPECT_EQ(string_append_cstring(&s, "123"), 3);
767 1 EXPECT_STRING_EQ_CSTRING(&s, "123");
768
769 1 EXPECT_EQ(string_append_string(&s, &s), 3);
770 1 EXPECT_STRING_EQ_CSTRING(&s, "123123");
771
772 1 EXPECT_EQ(string_insert_buf(&s, 2, STRN("foo")), 3);
773 1 EXPECT_STRING_EQ_CSTRING(&s, "12foo3123");
774
775 1 cstr = string_clone_cstring(&s);
776 1 EXPECT_STREQ(cstr, "12foo3123");
777
778 1 EXPECT_EQ(string_insert_codepoint(&s, 0, '>'), 1);
779 1 EXPECT_STRING_EQ_CSTRING(&s, ">12foo3123");
780
781 1 string_replace_byte(&s, '1', '_');
782 1 EXPECT_STRING_EQ_CSTRING(&s, ">_2foo3_23");
783 1 string_replace_byte(&s, '_', '.');
784 1 string_replace_byte(&s, '2', '+');
785 1 string_replace_byte(&s, '3', '$');
786 1 EXPECT_STRING_EQ_CSTRING(&s, ">.+foo$.+$");
787
788 1 string_free(&s);
789 1 EXPECT_NULL(s.buffer);
790 1 EXPECT_EQ(s.len, 0);
791 1 EXPECT_EQ(s.alloc, 0);
792 1 EXPECT_STREQ(cstr, "12foo3123");
793 1 free(cstr);
794
795 1 EXPECT_STREQ(string_borrow_cstring(&s), "");
796 1 EXPECT_EQ(s.len, 0);
797 1 EXPECT_EQ3(s.alloc, 16, STRING_ALLOC_MULTIPLE);
798 1 EXPECT_NONNULL(s.buffer);
799 1 string_free(&s);
800
801 // This is mostly for UBSan coverage
802 // See also: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf
803 1 s = string_new(0);
804 1 EXPECT_NULL(s.buffer);
805 1 EXPECT_EQ(s.len, 0);
806 1 EXPECT_EQ(s.alloc, 0);
807 1 EXPECT_STRING_EQ_CSTRING(&s, "");
808 1 EXPECT_EQ(string_append_buf(&s, NULL, 0), 0);
809 1 EXPECT_EQ(string_insert_buf(&s, 0, NULL, 0), 0);
810 1 EXPECT_EQ(string_append_memset(&s, 'q', 0), 0);
811 1 string_replace_byte(&s, 'q', 'z');
812 1 string_remove(&s, 0, 0);
813 1 EXPECT_NULL(s.buffer);
814 1 EXPECT_EQ(s.len, 0);
815 1 EXPECT_EQ(s.alloc, 0);
816 1 string_free(&s);
817
818 // string_sprintf() always reserves and writes at least 1 byte,
819 // for null-termination. This isn't strictly necessary and is only
820 // tested here for completeness.
821 1 string_sprintf(&s, "%s", "");
822 1 EXPECT_EQ3(s.alloc, 16, STRING_ALLOC_MULTIPLE);
823 1 string_free(&s);
824
825 1 s = string_new_from_buf(STRN("1234567"));
826 1 EXPECT_STRING_EQ_CSTRING(&s, "1234567");
827 1 EXPECT_EQ3(s.alloc, 16, STRING_ALLOC_MULTIPLE);
828 1 string_free(&s);
829 1 EXPECT_NULL(s.buffer);
830 1 EXPECT_EQ(s.len, 0);
831 1 EXPECT_EQ(s.alloc, 0);
832 1 }
833
834 1 static void test_string_next_alloc_size(TestContext *ctx)
835 {
836 1 static const size_t expected_alloc_sizes[] = {
837 0, 16, 32, 64,
838 112, 176, 272, 416,
839 640, 976, 1472, 2224,
840 3344, 5024, 7552, 11344,
841 17024, 25552, 38336, 57520,
842 };
843
844 1 EXPECT_TRUE(IS_POWER_OF_2(STRING_ALLOC_MULTIPLE));
845 1 size_t remainder_mask = STRING_ALLOC_MULTIPLE - 1;
846
847
2/2
✓ Branch 8 → 4 taken 19 times.
✓ Branch 8 → 9 taken 1 time.
21 for (size_t i = 1, size = 0; i < ARRAYLEN(expected_alloc_sizes); i++) {
848 19 size_t expected = expected_alloc_sizes[i];
849 19 EXPECT_EQ(expected & remainder_mask, 0);
850 19 size = string_next_alloc_size(size, size + 1);
851 19 EXPECT_EQ(size, expected);
852 }
853 1 }
854
855 1 static void test_string_view(TestContext *ctx)
856 {
857 1 StringView sv = strview("testing");
858 1 EXPECT_TRUE(strview_equal_cstring(sv, "testing"));
859 1 EXPECT_FALSE(strview_equal_cstring(sv, "testin"));
860 1 EXPECT_FALSE(strview_equal_cstring(sv, "TESTING"));
861 1 EXPECT_TRUE(strview_has_prefix(sv, "test"));
862 1 EXPECT_TRUE(strview_has_prefix_icase(sv, "TEst"));
863 1 EXPECT_FALSE(strview_has_prefix(sv, "TEst"));
864 1 EXPECT_FALSE(strview_has_prefix_icase(sv, "TEst_"));
865
866 1 sv = string_view(sv.data, sv.length);
867 1 EXPECT_TRUE(strview_equal(sv, sv));
868
869 1 sv = strview("foobar");
870 1 EXPECT_TRUE(strview_equal_cstring(sv, "foobar"));
871 1 EXPECT_TRUE(strview_has_prefix(sv, "foo"));
872 1 EXPECT_FALSE(strview_equal_cstring(sv, "foo"));
873
874 1 sv = strview("\t \t\t ");
875 1 EXPECT_TRUE(strview_isblank(sv));
876 1 sv.length = 0;
877 1 EXPECT_TRUE(strview_isblank(sv));
878 1 sv = strview(" \t . ");
879 1 EXPECT_FALSE(strview_isblank(sv));
880 1 sv = strview("\n");
881 1 EXPECT_FALSE(strview_isblank(sv));
882 1 sv = strview(" \r ");
883 1 EXPECT_FALSE(strview_isblank(sv));
884
885 1 sv = strview(" \t\t \ttrim test \t\t");
886 1 EXPECT_EQ(strview_trim(&sv), 9);
887 1 EXPECT_TRUE(strview_equal_cstring(sv, "trim test"));
888
889 1 sv = strview(NULL);
890 1 EXPECT_NULL(strview_memrchr(sv, '.'));
891 1 EXPECT_NULL(strview_memchr(sv, '.'));
892 1 EXPECT_TRUE(strview_equal(sv, sv));
893 1 EXPECT_TRUE(strview_equal_icase(sv, sv));
894 1 EXPECT_FALSE(strview_contains_char_type(sv, ASCII_DIGIT));
895 1 EXPECT_TRUE(strview_isblank(sv));
896 1 EXPECT_EQ(strview_trim_left(&sv), 0);
897 1 EXPECT_EQ(strview_trim_right(&sv), 0);
898 1 EXPECT_EQ(strview_trim(&sv), 0);
899 1 EXPECT_TRUE(strview_equal_cstring(sv, ""));
900 1 EXPECT_TRUE(strview_equal_icase(sv, strview("")));
901 1 EXPECT_TRUE(strview_has_prefix(sv, ""));
902 1 EXPECT_TRUE(strview_has_suffix(sv, ""));
903 1 EXPECT_TRUE(strview_has_prefix_icase(sv, ""));
904 1 EXPECT_EQ(strview_remove_prefix(&sv, 0), 0);
905 1 EXPECT_EQ(strview_remove_suffix(&sv, 0), 0);
906 1 EXPECT_NULL(sv.data);
907 1 EXPECT_EQ(sv.length, 0);
908
909 1 sv = strview("prefix - suffix");
910 1 EXPECT_PTREQ(strview_memchr(sv, '-'), strview_memrchr(sv, '-'));
911 1 EXPECT_PTREQ(strview_memchr(sv, 'x'), sv.data + 5);
912 1 EXPECT_PTREQ(strview_memrchr(sv, 'x'), sv.data + 14);
913 1 EXPECT_PTREQ(strview_memrchr(sv, '@'), NULL);
914 1 EXPECT_EQ(strview_memrchr_idx(sv, 'p'), 0);
915 1 EXPECT_EQ(strview_memrchr_idx(sv, 'x'), 14);
916 1 EXPECT_EQ(strview_memrchr_idx(sv, '@'), -1);
917 1 }
918
919 1 static void test_strview_has_suffix(TestContext *ctx)
920 {
921 1 EXPECT_TRUE(strview_has_suffix(strview("foo"), "foo"));
922 1 EXPECT_TRUE(strview_has_suffix(strview("foobar"), "bar"));
923 1 EXPECT_TRUE(strview_has_suffix(strview("1234"), "234"));
924 1 EXPECT_TRUE(strview_has_suffix(strview("x"), "x"));
925 1 EXPECT_TRUE(strview_has_suffix(strview("aa"), "a"));
926 1 EXPECT_FALSE(strview_has_suffix(strview("foobar."), "bar"));
927 1 EXPECT_FALSE(strview_has_suffix(strview("foo"), "foobar"));
928 1 EXPECT_FALSE(strview_has_suffix(strview("bar"), "foobar"));
929 1 EXPECT_FALSE(strview_has_suffix(strview("foo"), "bar"));
930 1 EXPECT_FALSE(strview_has_suffix(strview("bar"), "foo"));
931 1 EXPECT_FALSE(strview_has_suffix(strview("123"), "1234"));
932 1 EXPECT_FALSE(strview_has_suffix(strview("a"), "aa"));
933
934 1 StringView sv = strview("foobar");
935 1 EXPECT_TRUE(strview_has_suffix(sv, "foobar"));
936 1 EXPECT_TRUE(strview_has_suffix(sv, "bar"));
937 1 EXPECT_TRUE(strview_has_suffix(sv, "r"));
938 1 EXPECT_TRUE(strview_has_suffix(sv, ""));
939 1 EXPECT_FALSE(strview_has_suffix(sv, "foo"));
940 1 EXPECT_FALSE(strview_has_suffix(sv, "foobars"));
941
942 1 const StringView suffix = strview(NULL);
943 1 EXPECT_TRUE(strview_has_sv_suffix(sv, suffix));
944 1 EXPECT_TRUE(strview_has_sv_suffix(suffix, suffix));
945
946 1 sv.length--;
947 1 EXPECT_FALSE(strview_has_suffix(sv, "bar"));
948 1 EXPECT_TRUE(strview_has_suffix(sv, "ba"));
949 1 EXPECT_TRUE(strview_has_sv_suffix(sv, suffix));
950
951 1 sv.length = 0;
952 1 EXPECT_TRUE(strview_has_suffix(sv, ""));
953 1 EXPECT_FALSE(strview_has_suffix(sv, "f"));
954 1 EXPECT_TRUE(strview_has_sv_suffix(sv, suffix));
955
956 1 sv.data = NULL;
957 1 EXPECT_TRUE(strview_has_suffix(sv, ""));
958 1 EXPECT_FALSE(strview_has_suffix(sv, "f"));
959 1 EXPECT_TRUE(strview_has_sv_suffix(sv, suffix));
960 1 }
961
962 1 static void test_strview_suffix_length(TestContext *ctx)
963 {
964 1 EXPECT_EQ(strview_blank_suffix_length(strview(NULL)), 0);
965 1 EXPECT_EQ(strview_blank_suffix_length(strview("")), 0);
966 1 EXPECT_EQ(strview_blank_suffix_length(strview("...")), 0);
967 1 EXPECT_EQ(strview_blank_suffix_length(strview(" ")), 1);
968 1 EXPECT_EQ(strview_blank_suffix_length(strview("...\t")), 1);
969 1 EXPECT_EQ(strview_blank_suffix_length(strview("... \t")), 2);
970 1 EXPECT_EQ(strview_blank_suffix_length(strview("\t... \t\t ")), 4);
971 1 EXPECT_EQ(strview_blank_suffix_length(strview(" \t ... \t\t\t\t")), 5);
972
973 1 EXPECT_EQ(strview_char_suffix_length(strview(NULL), 'a'), 0);
974 1 EXPECT_EQ(strview_char_suffix_length(strview(""), 'a'), 0);
975 1 EXPECT_EQ(strview_char_suffix_length(strview("b"), 'a'), 0);
976 1 EXPECT_EQ(strview_char_suffix_length(strview("1 a"), 'a'), 1);
977 1 EXPECT_EQ(strview_char_suffix_length(strview("2 aa"), 'a'), 2);
978 1 EXPECT_EQ(strview_char_suffix_length(strview("3 abaaa"), 'a'), 3);
979 1 EXPECT_EQ(strview_char_suffix_length(strview("4 abcaaaa"), 'a'), 4);
980 1 }
981
982 1 static void test_strview_remove_matching(TestContext *ctx)
983 {
984 1 StringView sv = strview("ABCDEFGHIJKLMN");
985 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, "ABC"));
986 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "DEFGHIJKLMN");
987
988 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, "KLMN"));
989 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "DEFGHIJ");
990
991 1 EXPECT_FALSE(strview_remove_matching_prefix(&sv, "A"));
992 1 EXPECT_FALSE(strview_remove_matching_suffix(&sv, "K"));
993 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "DEFGHIJ");
994
995 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, ""));
996 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "DEFGHIJ");
997
998 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, ""));
999 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "DEFGHIJ");
1000
1001 1 sv.length = 0;
1002 1 sv.data = NULL;
1003 1 EXPECT_TRUE(strview_remove_matching_prefix(&sv, ""));
1004 1 EXPECT_TRUE(strview_remove_matching_suffix(&sv, ""));
1005 1 EXPECT_FALSE(strview_remove_matching_prefix(&sv, "pre"));
1006 1 EXPECT_FALSE(strview_remove_matching_suffix(&sv, "suf"));
1007 1 EXPECT_EQ(sv.length, 0);
1008 1 EXPECT_NULL(sv.data);
1009 1 EXPECT_STRVIEW_EQ_CSTRING(sv, "");
1010 1 }
1011
1012 1 static void test_strview_from_slice(TestContext *ctx)
1013 {
1014 1 static const char src[] = "01234567890";
1015 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(NULL, 0, 0), "");
1016 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(src, 0, 0), "");
1017 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(src, 1, 1), "");
1018 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(src, 2, 3), "2");
1019 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(src, 3, 7), "3456");
1020 1 EXPECT_STRVIEW_EQ_CSTRING(strview_from_slice(src, 0, sizeof(src) - 1), src);
1021
1022 1 static const StringView sv = STRING_VIEW("0123456789");
1023 1 EXPECT_STRVIEW_EQ_CSTRING(strview_suffix(sv, 0), "0123456789");
1024 1 EXPECT_STRVIEW_EQ_CSTRING(strview_suffix(sv, 4), "456789");
1025 1 EXPECT_STRVIEW_EQ_CSTRING(strview_suffix(sv, 7), "789");
1026 1 EXPECT_STRVIEW_EQ_CSTRING(strview_suffix(sv, sv.length), "");
1027 1 EXPECT_STRVIEW_EQ_CSTRING(strview_suffix(strview(NULL), 0), "");
1028 1 }
1029
1030 1 static void test_get_delim(TestContext *ctx)
1031 {
1032 1 static const StringView input = STRING_VIEW("-x-y-foo--bar--");
1033 1 static const char parts[][4] = {"", "x", "y", "foo", "", "bar", "", ""};
1034 1 const size_t nparts = ARRAYLEN(parts);
1035 1 const size_t part_size = ARRAYLEN(parts[0]);
1036
1037 1 size_t idx = 0;
1038
2/2
✓ Branch 8 → 3 taken 7 times.
✓ Branch 8 → 9 taken 1 time.
8 for (size_t pos = 0; pos < input.length; idx++) {
1039 7 const StringView sv = get_delim(input, &pos, '-');
1040 7 ASSERT_TRUE(idx < nparts);
1041 7 ASSERT_EQ(parts[idx][part_size - 1], '\0');
1042 7 EXPECT_STRVIEW_EQ_CSTRING(sv, parts[idx]);
1043 }
1044
1045 1 EXPECT_EQ(idx, nparts - 1);
1046 1 }
1047
1048 1 static void test_get_delim_str(TestContext *ctx)
1049 {
1050 1 char str[] = "word1-word2-end-";
1051 1 size_t len = sizeof(str) - 1;
1052 1 ASSERT_EQ(str[len - 1], '-'); // Last character in bounds is a delimiter
1053
1054 1 size_t pos = 0;
1055 1 const char *substr = get_delim_str(str, &pos, len, '-');
1056 1 EXPECT_STREQ(substr, "word1");
1057 1 EXPECT_EQ(pos, 6);
1058
1059 1 substr = get_delim_str(str, &pos, len, '-');
1060 1 EXPECT_STREQ(substr, "word2");
1061 1 EXPECT_EQ(pos, 12);
1062
1063 1 substr = get_delim_str(str, &pos, len, '-');
1064 1 EXPECT_STREQ(substr, "end");
1065 1 EXPECT_EQ(pos, 16);
1066
1067 // Note: str2 is not null-terminated and there are no delimiters present,
1068 // but there's one extra, writable byte in the buffer that falls outside
1069 // the length bound
1070 1 char str2[16] = "no delimiter...!";
1071 1 len = sizeof(str2) - 1;
1072 1 ASSERT_EQ(str2[len], '!');
1073 1 pos = 0;
1074 1 substr = get_delim_str(str2, &pos, len, '-');
1075 1 EXPECT_STREQ(substr, "no delimiter...");
1076 1 EXPECT_EQ(pos, len);
1077
1078 1 static const char after[] = "\0\0\0\0aa\0b\0c\0dd\0\0";
1079 1 char before[] = ",,,,aa,b,c,dd,,";
1080 1 unsigned int iters = 0;
1081 1 unsigned int width = 0;
1082
2/2
✓ Branch 19 → 17 taken 9 times.
✓ Branch 19 → 20 taken 1 time.
10 for (pos = 0, len = sizeof(before) - 1; pos < len; iters++) {
1083 9 width += strlen(get_delim_str(before, &pos, len, ','));
1084 }
1085 1 EXPECT_MEMEQ(before, sizeof(before), after, sizeof(after));
1086 1 EXPECT_EQ(width, 6);
1087 1 EXPECT_EQ(iters, 9);
1088 1 }
1089
1090 1 static void test_strn_replace_byte(TestContext *ctx)
1091 {
1092 1 static const char expected[] = "||a|b|c||\n\0\0|d|e|f|||\0g|h||\0\0";
1093 1 char str[] = /* ........... */ "..a.b.c..\n\0\0.d.e.f...\0g.h..\0\0";
1094 1 strn_replace_byte(str, sizeof(str), '.', '|');
1095 1 EXPECT_MEMEQ(str, sizeof(str), expected, sizeof(expected));
1096 1 }
1097
1098 1 static void test_string_array_concat(TestContext *ctx)
1099 {
1100 1 static const char *const strs[] = {"A", "B", "CC", "D", "EE"};
1101 1 char buf[64] = "\0";
1102 1 size_t nstrs = ARRAYLEN(strs);
1103
1104 1 StringView delim = strview(",");
1105 1 StringView expected = strview("A,B,CC,D,EE");
1106 1 ASSERT_TRUE(expected.length + 1 < sizeof(buf));
1107 1 memset(buf, '@', sizeof(buf) - 1);
1108 1 EXPECT_FALSE(string_array_concat_(buf, expected.length, strs, nstrs, delim));
1109 1 memset(buf, '@', sizeof(buf) - 1);
1110 1 EXPECT_TRUE(string_array_concat_(buf, expected.length + 1, strs, nstrs, delim));
1111 1 EXPECT_STRVIEW_EQ_CSTRING(expected, buf);
1112
1113 1 delim = strview(" ... ");
1114 1 expected = strview("A ... B ... CC ... D ... EE");
1115 1 ASSERT_TRUE(expected.length + 1 < sizeof(buf));
1116 1 memset(buf, '@', sizeof(buf) - 1);
1117 1 EXPECT_FALSE(string_array_concat_(buf, expected.length, strs, nstrs, delim));
1118 1 memset(buf, '@', sizeof(buf) - 1);
1119 1 EXPECT_TRUE(string_array_concat_(buf, expected.length + 1, strs, nstrs, delim));
1120 1 EXPECT_STRVIEW_EQ_CSTRING(expected, buf);
1121
1122
2/2
✓ Branch 18 → 15 taken 27 times.
✓ Branch 18 → 19 taken 1 time.
29 for (size_t i = 0; i < expected.length; i++) {
1123 27 EXPECT_FALSE(string_array_concat_(buf, expected.length - i, strs, nstrs, delim));
1124 }
1125
1126 1 memset(buf, '@', sizeof(buf) - 1);
1127 1 EXPECT_TRUE(string_array_concat_(buf, sizeof(buf), strs, 0, delim));
1128 1 EXPECT_STREQ(buf, "");
1129 1 }
1130
1131 1 static void test_size_str_width(TestContext *ctx)
1132 {
1133 1 EXPECT_EQ(size_str_width(0), 1);
1134 1 EXPECT_EQ(size_str_width(1), 1);
1135 1 EXPECT_EQ(size_str_width(9), 1);
1136 1 EXPECT_EQ(size_str_width(19), 2);
1137 1 EXPECT_EQ(size_str_width(425), 3);
1138 1 EXPECT_EQ(size_str_width(12345), 5);
1139 1 EXPECT_EQ(size_str_width(2147483647), 10);
1140 1 }
1141
1142 1 static void test_buf_parse_uintmax(TestContext *ctx)
1143 {
1144 1 uintmax_t val;
1145 1 char max[DECIMAL_STR_MAX(val) + 2];
1146 1 size_t max_len = xsnprintf(max, sizeof max, "%ju", UINTMAX_MAX);
1147
1148 1 val = 11;
1149 1 EXPECT_EQ(buf_parse_uintmax(string_view(max, max_len), &val), max_len);
1150 1 EXPECT_UINT_EQ(val, UINTMAX_MAX);
1151
1152 1 val = 22;
1153 1 max[max_len++] = '9';
1154 1 EXPECT_EQ(buf_parse_uintmax(string_view(max, max_len), &val), 0);
1155 1 EXPECT_EQ(val, 22);
1156
1157 1 val = 33;
1158 1 max[max_len++] = '7';
1159 1 EXPECT_EQ(buf_parse_uintmax(string_view(max, max_len), &val), 0);
1160 1 EXPECT_EQ(val, 33);
1161
1162 1 EXPECT_EQ(buf_parse_uintmax(strview("0"), &val), 1);
1163 1 EXPECT_EQ(val, 0);
1164
1165 1 EXPECT_EQ(buf_parse_uintmax(string_view("0019817", 8), &val), 7);
1166 1 EXPECT_EQ(val, 19817);
1167
1168 1 EXPECT_EQ(buf_parse_uintmax(string_view("0098765", 5), &val), 5);
1169 1 EXPECT_EQ(val, 987);
1170
1171 1 char buf[4] = " 90/";
1172 1 buf[0] = CHAR_MAX;
1173 1 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 4), &val), 0);
1174
1175
2/2
✓ Branch 46 → 24 taken 255 times.
✓ Branch 46 → 47 taken 1 time.
257 for (char c = CHAR_MIN; c < CHAR_MAX; c++) {
1176 255 buf[0] = c;
1177
2/2
✓ Branch 24 → 25 taken 245 times.
✓ Branch 24 → 28 taken 10 times.
255 if (!ascii_isdigit(c)) {
1178 245 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 4), &val), 0);
1179 245 continue;
1180 }
1181 10 val = 337;
1182 10 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 0), &val), 0);
1183 10 EXPECT_EQ(val, 337);
1184 10 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 1), &val), 1);
1185 10 EXPECT_TRUE(val <= 9);
1186 10 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 2), &val), 2);
1187 10 EXPECT_TRUE(val >= 9);
1188 10 EXPECT_TRUE(val <= 99);
1189 10 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 3), &val), 3);
1190 10 EXPECT_TRUE(val >= 90);
1191 10 EXPECT_TRUE(val <= 990);
1192 10 const uintmax_t prev = val;
1193 10 EXPECT_EQ(buf_parse_uintmax(string_view(buf, 4), &val), 3);
1194 10 EXPECT_EQ(val, prev);
1195 }
1196 1 }
1197
1198 1 static void test_buf_parse_ulong(TestContext *ctx)
1199 {
1200 1 unsigned long val;
1201 1 char max[DECIMAL_STR_MAX(val) + 1];
1202 1 size_t max_len = xsnprintf(max, sizeof max, "%lu", ULONG_MAX);
1203
1204 1 val = 88;
1205 1 EXPECT_EQ(buf_parse_ulong(strview(max), &val), max_len);
1206 1 EXPECT_UINT_EQ(val, ULONG_MAX);
1207
1208 1 val = 99;
1209 1 max[max_len++] = '1';
1210 1 EXPECT_EQ(buf_parse_ulong(string_view(max, max_len), &val), 0);
1211 1 EXPECT_EQ(val, 99);
1212
1213 1 EXPECT_EQ(buf_parse_ulong(strview("0"), &val), 1);
1214 1 EXPECT_EQ(val, 0);
1215
1216 1 EXPECT_EQ(buf_parse_ulong(strview("9876"), &val), 4);
1217 1 EXPECT_EQ(val, 9876);
1218 1 }
1219
1220 1 static void test_buf_parse_size(TestContext *ctx)
1221 {
1222 1 size_t val;
1223 1 char max[DECIMAL_STR_MAX(val) + 1];
1224 1 size_t max_len = xsnprintf(max, sizeof max, "%zu", SIZE_MAX);
1225
1226 1 val = 14;
1227 1 EXPECT_EQ(buf_parse_size(strview(max), &val), max_len);
1228 1 EXPECT_UINT_EQ(val, SIZE_MAX);
1229
1230 1 val = 88;
1231 1 max[max_len++] = '0';
1232 1 EXPECT_EQ(buf_parse_size(strview(max), &val), 0);
1233 1 EXPECT_EQ(val, 88);
1234 1 }
1235
1236 1 static void test_buf_parse_hex_uint(TestContext *ctx)
1237 {
1238 1 unsigned int val;
1239 1 char buf[HEX_STR_MAX(val) + 1];
1240 1 size_t buf_len = xsnprintf(buf, sizeof buf, "%x", UINT_MAX);
1241 1 val = 0x90;
1242 1 EXPECT_EQ(buf_parse_hex_uint(strview(buf), &val), buf_len);
1243 1 EXPECT_UINT_EQ(val, UINT_MAX);
1244
1245 1 buf_len = xsnprintf(buf, sizeof buf, "1%x", UINT_MAX);
1246 1 val = 0x100;
1247 1 EXPECT_EQ(buf_parse_hex_uint(strview(buf), &val), 0);
1248 1 EXPECT_UINT_EQ(val, 0x100);
1249
1250 1 buf_len = xsnprintf(buf, sizeof buf, "%xg", UINT_MAX);
1251 1 val = 0x110;
1252 1 EXPECT_EQ(buf_parse_hex_uint(strview(buf), &val), buf_len - 1);
1253 1 EXPECT_UINT_EQ(val, UINT_MAX);
1254
1255 1 buf_len = xsnprintf(buf, sizeof buf, "%xf", UINT_MAX);
1256 1 val = 0x120;
1257 1 EXPECT_EQ(buf_parse_hex_uint(strview(buf), &val), 0);
1258 1 EXPECT_UINT_EQ(val, 0x120);
1259
1260 1 buf_len = sizeof(buf);
1261 1 memset(buf, '0', buf_len);
1262 1 val = 0x130;
1263 1 EXPECT_EQ(buf_parse_hex_uint(string_view(buf, buf_len), &val), buf_len);
1264 1 EXPECT_UINT_EQ(val, 0);
1265
1266 1 val = 0x140;
1267 1 EXPECT_EQ(buf_parse_hex_uint(string_view(buf, buf_len - 2), &val), buf_len - 2);
1268 1 EXPECT_UINT_EQ(val, 0);
1269
1270 1 val = 0x150;
1271 1 EXPECT_EQ(buf_parse_hex_uint(strview("12345678"), &val), 8);
1272 1 EXPECT_UINT_EQ(val, 0x12345678);
1273
1274 1 val = 0x160;
1275 1 EXPECT_EQ(buf_parse_hex_uint(strview("00abcdeF01"), &val), 10);
1276 1 EXPECT_UINT_EQ(val, 0xABCDEF01);
1277
1278 1 val = 0x170;
1279 1 EXPECT_EQ(buf_parse_hex_uint(string_view("0123456789", 4), &val), 4);
1280 1 EXPECT_UINT_EQ(val, 0x123);
1281 1 }
1282
1283 1 static void test_str_to_int(TestContext *ctx)
1284 {
1285 1 int val = 0;
1286 1 EXPECT_TRUE(str_to_int("-1", &val));
1287 1 EXPECT_EQ(val, -1);
1288 1 EXPECT_TRUE(str_to_int("+1", &val));
1289 1 EXPECT_EQ(val, 1);
1290 1 EXPECT_TRUE(str_to_int("0", &val));
1291 1 EXPECT_EQ(val, 0);
1292 1 EXPECT_TRUE(str_to_int("1", &val));
1293 1 EXPECT_EQ(val, 1);
1294 1 EXPECT_TRUE(str_to_int("+00299", &val));
1295 1 EXPECT_EQ(val, 299);
1296
1297 1 EXPECT_FALSE(str_to_int("", &val));
1298 1 EXPECT_FALSE(str_to_int("100x", &val));
1299 1 EXPECT_FALSE(str_to_int("+-100", &val));
1300 1 EXPECT_FALSE(str_to_int("99999999999999999999999999999999", &val));
1301 1 }
1302
1303 1 static void test_str_to_size(TestContext *ctx)
1304 {
1305 1 size_t val = 0;
1306 1 EXPECT_TRUE(str_to_size("100", &val));
1307 1 EXPECT_EQ(val, 100);
1308 1 EXPECT_TRUE(str_to_size("0", &val));
1309 1 EXPECT_EQ(val, 0);
1310 1 EXPECT_TRUE(str_to_size("000000001003", &val));
1311 1 EXPECT_EQ(val, 1003);
1312 1 EXPECT_TRUE(str_to_size("29132", &val));
1313 1 EXPECT_EQ(val, 29132);
1314
1315 1 EXPECT_FALSE(str_to_size("", &val));
1316 1 EXPECT_FALSE(str_to_size("100x", &val));
1317 1 EXPECT_FALSE(str_to_size("-100", &val));
1318 1 EXPECT_FALSE(str_to_size("99999999999999999999999999999999", &val));
1319 1 }
1320
1321 1 static void test_str_to_filepos(TestContext *ctx)
1322 {
1323 1 size_t line = 0;
1324 1 size_t col = 0;
1325 1 EXPECT_TRUE(str_to_filepos("10,60", &line, &col));
1326 1 EXPECT_EQ(line, 10);
1327 1 EXPECT_EQ(col, 60);
1328
1329 1 EXPECT_TRUE(str_to_filepos("1:9", &line, &col));
1330 1 EXPECT_EQ(line, 1);
1331 1 EXPECT_EQ(col, 9);
1332
1333 1 EXPECT_TRUE(str_to_filepos("2", &line, &col));
1334 1 EXPECT_EQ(line, 2);
1335 1 EXPECT_EQ(col, 1);
1336
1337 1 EXPECT_TRUE(str_to_filepos("3,1", &line, &col));
1338 1 EXPECT_EQ(line, 3);
1339 1 EXPECT_EQ(col, 1);
1340
1341 1 EXPECT_TRUE(str_to_xfilepos(strview("4"), &line, &col));
1342 1 EXPECT_EQ(line, 4);
1343 1 EXPECT_EQ(col, 0);
1344
1345 1 EXPECT_TRUE(str_to_xfilepos(strview("5,1"), &line, &col));
1346 1 EXPECT_EQ(line, 5);
1347 1 EXPECT_EQ(col, 1);
1348
1349 1 line = 1111;
1350 1 col = 2222;
1351 1 EXPECT_FALSE(str_to_filepos("0", &line, &col));
1352 1 EXPECT_FALSE(str_to_filepos("1,0", &line, &col));
1353 1 EXPECT_FALSE(str_to_filepos("0,1", &line, &col));
1354 1 EXPECT_FALSE(str_to_filepos("1,2,3", &line, &col));
1355 1 EXPECT_FALSE(str_to_filepos("1,2.3", &line, &col));
1356 1 EXPECT_FALSE(str_to_filepos("5,", &line, &col));
1357 1 EXPECT_FALSE(str_to_filepos("5:", &line, &col));
1358 1 EXPECT_FALSE(str_to_filepos(",5", &line, &col));
1359 1 EXPECT_FALSE(str_to_filepos("6.7", &line, &col));
1360 1 EXPECT_FALSE(str_to_filepos("2 3", &line, &col));
1361 1 EXPECT_FALSE(str_to_filepos("9 ", &line, &col));
1362 1 EXPECT_FALSE(str_to_filepos("", &line, &col));
1363 1 EXPECT_FALSE(str_to_filepos("\t", &line, &col));
1364 1 EXPECT_FALSE(str_to_filepos("44,9x", &line, &col));
1365 1 EXPECT_EQ(line, 1111);
1366 1 EXPECT_EQ(col, 2222);
1367 1 }
1368
1369 1 static void test_parse_file_line_col(TestContext *ctx)
1370 {
1371 1 size_t line = 44;
1372 1 size_t col = 77;
1373 1 StringView path = parse_file_line_col("dir/file.ext:12:45", &line, &col);
1374 1 EXPECT_STRVIEW_EQ_CSTRING(path, "dir/file.ext");
1375 1 EXPECT_EQ(line, 12);
1376 1 EXPECT_EQ(col, 45);
1377
1378 1 path = parse_file_line_col("/x/y/z/file:901", &line, &col);
1379 1 EXPECT_STRVIEW_EQ_CSTRING(path, "/x/y/z/file");
1380 1 EXPECT_EQ(line, 901);
1381 1 EXPECT_EQ(col, 1);
1382
1383 // Colons are searched from the end of the string, so the filename may
1384 // contain colons
1385 1 path = parse_file_line_col("/x/:y:/z/file:99:32", &line, &col);
1386 1 EXPECT_STRVIEW_EQ_CSTRING(path, "/x/:y:/z/file");
1387 1 EXPECT_EQ(line, 99);
1388 1 EXPECT_EQ(col, 32);
1389
1390 1 path = parse_file_line_col("a:5", &line, &col);
1391 1 EXPECT_STRVIEW_EQ_CSTRING(path, "a");
1392 1 EXPECT_EQ(line, 5);
1393 1 EXPECT_EQ(col, 1);
1394
1395 1 static const char invalid[][8] = {
1396 "a", // Invalid because line number is mandatory
1397 "",
1398 ":",
1399 "::",
1400 "a:",
1401 "a::",
1402 ":1:1",
1403 "a:2:",
1404 "a::2",
1405 "a:1:0",
1406 "a:0:1",
1407 "a:0:0",
1408 "a:1:1:",
1409 "a:_:1",
1410 "a:1:_",
1411 "a:1:1_",
1412 };
1413
1414
2/2
✓ Branch 24 → 19 taken 16 times.
✓ Branch 24 → 25 taken 1 time.
18 FOR_EACH_I(i, invalid) {
1415 16 line = 7;
1416 16 col = 8;
1417 16 path = parse_file_line_col(invalid[i], &line, &col);
1418 16 EXPECT_STRVIEW_EQ_CSTRING(path, "");
1419 16 IEXPECT_EQ(line, 7);
1420 16 IEXPECT_EQ(col, 8);
1421 }
1422 1 }
1423
1424 1 static void test_buf_umax_to_hex_str(TestContext *ctx)
1425 {
1426 1 char buf[HEX_STR_MAX(uintmax_t)];
1427 1 memset(buf, '@', sizeof(buf));
1428
1429 1 size_t ndigits = buf_umax_to_hex_str(0x98EA412F0ull, buf, 0);
1430 1 EXPECT_EQ(ndigits, 9);
1431 1 EXPECT_STREQ(buf, "98EA412F0");
1432
1433 1 ndigits = buf_umax_to_hex_str(0xE, buf, 0);
1434 1 EXPECT_EQ(ndigits, 1);
1435 1 EXPECT_STREQ(buf, "E");
1436
1437 1 ndigits = buf_umax_to_hex_str(0xF, buf, 4);
1438 1 EXPECT_EQ(ndigits, 4);
1439 1 EXPECT_STREQ(buf, "000F");
1440
1441 1 ndigits = buf_umax_to_hex_str(0, buf, 10);
1442 1 EXPECT_EQ(ndigits, 10);
1443 1 EXPECT_STREQ(buf, "0000000000");
1444
1445 1 ndigits = buf_umax_to_hex_str(0xEF1300, buf, 8);
1446 1 EXPECT_EQ(ndigits, 8);
1447 1 EXPECT_STREQ(buf, "00EF1300");
1448
1449 1 ndigits = buf_umax_to_hex_str(0x1000, buf, 3);
1450 1 EXPECT_EQ(ndigits, 4);
1451 1 EXPECT_STREQ(buf, "1000");
1452
1453 1 ndigits = buf_umax_to_hex_str(0, buf, 0);
1454 1 EXPECT_EQ(ndigits, 1);
1455 1 EXPECT_STREQ(buf, "0");
1456
1457 1 ndigits = buf_umax_to_hex_str(1, buf, 0);
1458 1 EXPECT_EQ(ndigits, 1);
1459 1 EXPECT_STREQ(buf, "1");
1460
1461 1 ndigits = buf_umax_to_hex_str(0x10000000ULL, buf, 0);
1462 1 EXPECT_EQ(ndigits, 8);
1463 1 EXPECT_STREQ(buf, "10000000");
1464
1465 1 ndigits = buf_umax_to_hex_str(0x11111111ULL, buf, 0);
1466 1 EXPECT_EQ(ndigits, 8);
1467 1 EXPECT_STREQ(buf, "11111111");
1468
1469 1 ndigits = buf_umax_to_hex_str(0x123456789ABCDEF0ULL, buf, 0);
1470 1 EXPECT_EQ(ndigits, 16);
1471 1 EXPECT_STREQ(buf, "123456789ABCDEF0");
1472
1473 1 ndigits = buf_umax_to_hex_str(0xFFFFFFFFFFFFFFFFULL, buf, 0);
1474 1 EXPECT_EQ(ndigits, 16);
1475 1 EXPECT_STREQ(buf, "FFFFFFFFFFFFFFFF");
1476 1 }
1477
1478 1 static void test_codepoint_to_str(TestContext *ctx)
1479 {
1480 1 char buf[CODEPOINT_STR_BUFSIZE];
1481 1 EXPECT_EQ(u_codepoint_to_str(0, buf), 6);
1482 1 EXPECT_STREQ(buf, "U+0000");
1483
1484 1 EXPECT_EQ(u_codepoint_to_str(0x340F, buf), 6);
1485 1 EXPECT_STREQ(buf, "U+340F");
1486
1487 1 EXPECT_EQ(u_codepoint_to_str(0x1F601, buf), 7);
1488 1 EXPECT_STREQ(buf, "U+1F601");
1489
1490 1 EXPECT_EQ(u_codepoint_to_str(0x10FFFD, buf), 8);
1491 1 EXPECT_STREQ(buf, "U+10FFFD");
1492
1493 1 EXPECT_EQ(u_codepoint_to_str(UNICODE_MAX_VALID_CODEPOINT, buf), 8);
1494 1 EXPECT_STREQ(buf, "U+10FFFF");
1495
1496 1 EXPECT_EQ(u_codepoint_to_str(UNICODE_MAX_VALID_CODEPOINT + 1, buf), 7);
1497 1 EXPECT_STREQ(buf, "Invalid");
1498
1499 1 EXPECT_EQ(u_codepoint_to_str(UINT32_MAX, buf), 7);
1500 1 EXPECT_STREQ(buf, "Invalid");
1501 1 }
1502
1503 1 static void test_parse_filesize(TestContext *ctx)
1504 {
1505 1 EXPECT_EQ(parse_filesize("0"), 0);
1506 1 EXPECT_EQ(parse_filesize("1"), 1);
1507 1 EXPECT_EQ(parse_filesize("1KiB"), 1024);
1508 1 EXPECT_EQ(parse_filesize("4GiB"), 4LL << 30);
1509 1 EXPECT_EQ(parse_filesize("4096MiB"), 4LL << 30);
1510 1 EXPECT_EQ(parse_filesize("1234567890"), 1234567890LL);
1511 1 EXPECT_EQ(parse_filesize("9GiB"), 9LL << 30);
1512 1 EXPECT_EQ(parse_filesize("1GiB"), 1LL << 30);
1513 1 EXPECT_EQ(parse_filesize("0GiB"), 0);
1514 1 EXPECT_EQ(parse_filesize("0KiB"), 0);
1515 1 EXPECT_EQ(parse_filesize("1MiB"), 1LL << 20);
1516 1 EXPECT_EQ(parse_filesize("1TiB"), 1LL << 40);
1517 1 EXPECT_EQ(parse_filesize("1PiB"), 1LL << 50);
1518 1 EXPECT_EQ(parse_filesize("1EiB"), 1LL << 60);
1519 1 EXPECT_EQ(parse_filesize("9223372036854775807"), (1ULL << 63) - 1);
1520
1521 1 EXPECT_EQ(parse_filesize("4i"), -EINVAL);
1522 1 EXPECT_EQ(parse_filesize("4B"), -EINVAL);
1523 1 EXPECT_EQ(parse_filesize("4GB"), -EINVAL);
1524 1 EXPECT_EQ(parse_filesize("G4"), -EINVAL);
1525 1 EXPECT_EQ(parse_filesize("4G_"), -EINVAL);
1526 1 EXPECT_EQ(parse_filesize(" 4G"), -EINVAL);
1527 1 EXPECT_EQ(parse_filesize("4G "), -EINVAL);
1528 1 EXPECT_EQ(parse_filesize("1K"), -EINVAL);
1529 1 EXPECT_EQ(parse_filesize("4G"), -EINVAL);
1530 1 EXPECT_EQ(parse_filesize("4096M"), -EINVAL);
1531 1 EXPECT_EQ(parse_filesize("9Gi"), -EINVAL);
1532 1 EXPECT_EQ(parse_filesize("0K"), -EINVAL);
1533
1534 1 intmax_t a = parse_filesize("8EiB");
1535 1 intmax_t b = parse_filesize("9223372036854775808");
1536 1 EXPECT_TRUE(a > 0 || a == -EOVERFLOW);
1537 1 EXPECT_EQ(a, b);
1538
1539 1 char buf[DECIMAL_STR_MAX(uintmax_t) + 4];
1540 1 xsnprintf(buf, sizeof buf, "%jd", INTMAX_MAX);
1541 1 EXPECT_EQ(parse_filesize(buf), INTMAX_MAX);
1542 1 xsnprintf(buf, sizeof buf, "%ju", (uintmax_t)(INTMAX_MAX) + 1);
1543 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1544 1 xsnprintf(buf, sizeof buf, "%jdKiB", INTMAX_MAX);
1545 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1546 1 xsnprintf(buf, sizeof buf, "%jdEiB", INTMAX_MAX);
1547 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1548 1 xsnprintf(buf, sizeof buf, "%ju", UINTMAX_MAX);
1549 1 EXPECT_EQ(parse_filesize(buf), -EOVERFLOW);
1550 1 }
1551
1552 1 static void test_umax_to_str(TestContext *ctx)
1553 {
1554 1 EXPECT_STREQ(umax_to_str(0), "0");
1555 1 EXPECT_STREQ(umax_to_str(1), "1");
1556 1 EXPECT_STREQ(umax_to_str(7), "7");
1557 1 EXPECT_STREQ(umax_to_str(99), "99");
1558 1 EXPECT_STREQ(umax_to_str(111), "111");
1559 1 EXPECT_STREQ(umax_to_str(1000), "1000");
1560 1 EXPECT_STREQ(umax_to_str(20998), "20998");
1561
1562 1 uintmax_t x = UINTMAX_MAX;
1563 1 char ref[DECIMAL_STR_MAX(x)];
1564 1 xsnprintf(ref, sizeof ref, "%ju", x);
1565 1 EXPECT_STREQ(umax_to_str(x), ref);
1566 1 x--;
1567 1 xsnprintf(ref, sizeof ref, "%ju", x);
1568 1 EXPECT_STREQ(umax_to_str(x), ref);
1569 1 }
1570
1571 1 static void test_uint_to_str(TestContext *ctx)
1572 {
1573 1 EXPECT_STREQ(uint_to_str(0), "0");
1574 1 EXPECT_STREQ(uint_to_str(1), "1");
1575 1 EXPECT_STREQ(uint_to_str(9), "9");
1576 1 EXPECT_STREQ(uint_to_str(10), "10");
1577 1 EXPECT_STREQ(uint_to_str(11), "11");
1578 1 EXPECT_STREQ(uint_to_str(99), "99");
1579 1 EXPECT_STREQ(uint_to_str(100), "100");
1580 1 EXPECT_STREQ(uint_to_str(101), "101");
1581 1 EXPECT_STREQ(uint_to_str(21904), "21904");
1582
1583 // See also: test_posix_sanity()
1584 1 EXPECT_STREQ(uint_to_str(4294967295u), "4294967295");
1585 1 }
1586
1587 1 static void test_ulong_to_str(TestContext *ctx)
1588 {
1589 1 unsigned long x = ULONG_MAX;
1590 1 char ref[DECIMAL_STR_MAX(x)];
1591 1 xsnprintf(ref, sizeof ref, "%lu", x);
1592 1 EXPECT_STREQ(ulong_to_str(x), ref);
1593 1 EXPECT_STREQ(ulong_to_str(x + 1), "0");
1594 1 }
1595
1596 1 static void test_buf_umax_to_str(TestContext *ctx)
1597 {
1598 1 char buf[DECIMAL_STR_MAX(uintmax_t)];
1599 1 EXPECT_EQ(buf_umax_to_str(0, buf), 1);
1600 1 EXPECT_STREQ(buf, "0");
1601 1 EXPECT_EQ(buf_umax_to_str(1, buf), 1);
1602 1 EXPECT_STREQ(buf, "1");
1603 1 EXPECT_EQ(buf_umax_to_str(9, buf), 1);
1604 1 EXPECT_STREQ(buf, "9");
1605 1 EXPECT_EQ(buf_umax_to_str(10, buf), 2);
1606 1 EXPECT_STREQ(buf, "10");
1607 1 EXPECT_EQ(buf_umax_to_str(1234567890ull, buf), 10);
1608 1 EXPECT_STREQ(buf, "1234567890");
1609 1 EXPECT_EQ(buf_umax_to_str(9087654321ull, buf), 10);
1610 1 EXPECT_STREQ(buf, "9087654321");
1611 1 static_assert(sizeof(buf) > 20);
1612 1 EXPECT_EQ(buf_umax_to_str(18446744073709551615ull, buf), 20);
1613 1 EXPECT_STREQ(buf, "18446744073709551615");
1614 1 }
1615
1616 1 static void test_buf_uint_to_str(TestContext *ctx)
1617 {
1618 1 char buf[DECIMAL_STR_MAX(unsigned int)];
1619 1 EXPECT_EQ(buf_uint_to_str(0, buf), 1);
1620 1 EXPECT_STREQ(buf, "0");
1621 1 EXPECT_EQ(buf_uint_to_str(1, buf), 1);
1622 1 EXPECT_STREQ(buf, "1");
1623 1 EXPECT_EQ(buf_uint_to_str(9, buf), 1);
1624 1 EXPECT_STREQ(buf, "9");
1625 1 EXPECT_EQ(buf_uint_to_str(129, buf), 3);
1626 1 EXPECT_STREQ(buf, "129");
1627 1 EXPECT_EQ(buf_uint_to_str(21904, buf), 5);
1628 1 EXPECT_STREQ(buf, "21904");
1629 1 static_assert(sizeof(buf) > 10);
1630 1 EXPECT_EQ(buf_uint_to_str(4294967295u, buf), 10);
1631 1 EXPECT_STREQ(buf, "4294967295");
1632 1 }
1633
1634 1 static void test_buf_u8_to_str(TestContext *ctx)
1635 {
1636 // Note that buf_u8_to_str() doesn't null-terminate the buffer
1637 1 char buf[4] = "";
1638 1 EXPECT_MEMEQ(buf, buf_u8_to_str(0, buf), "0", 1);
1639 1 EXPECT_MEMEQ(buf, buf_u8_to_str(1, buf), "1", 1);
1640 1 EXPECT_MEMEQ(buf, buf_u8_to_str(9, buf), "9", 1);
1641 1 EXPECT_MEMEQ(buf, buf_u8_to_str(10, buf), "10", 2);
1642 1 EXPECT_MEMEQ(buf, buf_u8_to_str(72, buf), "72", 2);
1643 1 EXPECT_MEMEQ(buf, buf_u8_to_str(99, buf), "99", 2);
1644 1 EXPECT_MEMEQ(buf, buf_u8_to_str(100, buf), "100", 3);
1645 1 EXPECT_MEMEQ(buf, buf_u8_to_str(101, buf), "101", 3);
1646 1 EXPECT_MEMEQ(buf, buf_u8_to_str(123, buf), "123", 3);
1647 1 EXPECT_MEMEQ(buf, buf_u8_to_str(205, buf), "205", 3);
1648 1 EXPECT_MEMEQ(buf, buf_u8_to_str(215, buf), "215", 3);
1649 1 EXPECT_MEMEQ(buf, buf_u8_to_str(225, buf), "225", 3);
1650 1 EXPECT_MEMEQ(buf, buf_u8_to_str(250, buf), "250", 3);
1651 1 EXPECT_MEMEQ(buf, buf_u8_to_str(251, buf), "251", 3);
1652 1 EXPECT_MEMEQ(buf, buf_u8_to_str(255, buf), "255", 3);
1653 1 }
1654
1655 1 static void test_file_permissions_to_str(TestContext *ctx)
1656 {
1657 1 char buf[FILE_PERMISSIONS_BUFSIZE];
1658 1 EXPECT_STREQ("---------", file_permissions_to_str(0, buf));
1659 1 EXPECT_STREQ("--------x", file_permissions_to_str(01, buf));
1660 1 EXPECT_STREQ("--x--x--x", file_permissions_to_str(0111, buf));
1661 1 EXPECT_STREQ("rwx------", file_permissions_to_str(0700, buf));
1662 1 EXPECT_STREQ("r--r--r--", file_permissions_to_str(0444, buf));
1663 1 EXPECT_STREQ("rw-rw-rw-", file_permissions_to_str(0666, buf));
1664 1 EXPECT_STREQ("rwxrwxrwx", file_permissions_to_str(0777, buf));
1665
1666 1 EXPECT_STREQ("-----S---", file_permissions_to_str(02000, buf));
1667 1 EXPECT_STREQ("-----s---", file_permissions_to_str(02010, buf));
1668 1 EXPECT_STREQ("--S------", file_permissions_to_str(04000, buf));
1669 1 EXPECT_STREQ("--s------", file_permissions_to_str(04100, buf));
1670 1 EXPECT_STREQ("--S--S---", file_permissions_to_str(06000, buf));
1671 1 EXPECT_STREQ("--s--s---", file_permissions_to_str(06110, buf));
1672 1 EXPECT_STREQ("--s--S---", file_permissions_to_str(06100, buf));
1673 1 EXPECT_STREQ("--S--s---", file_permissions_to_str(06010, buf));
1674
1675 #ifdef S_ISVTX
1676 1 EXPECT_STREQ("--S--S--T", file_permissions_to_str(07000, buf));
1677 1 EXPECT_STREQ("--s--s--t", file_permissions_to_str(07111, buf));
1678 1 EXPECT_STREQ("rwsrwsrwt", file_permissions_to_str(07777, buf));
1679 1 EXPECT_STREQ("rwSrwSrwT", file_permissions_to_str(07666, buf));
1680 1 EXPECT_STREQ("------rwt", file_permissions_to_str(01007, buf));
1681 #else
1682 EXPECT_STREQ("--S--S---", file_permissions_to_str(07000, buf));
1683 EXPECT_STREQ("--s--s--x", file_permissions_to_str(07111, buf));
1684 EXPECT_STREQ("rwsrwsrwx", file_permissions_to_str(07777, buf));
1685 EXPECT_STREQ("rwSrwSrw-", file_permissions_to_str(07666, buf));
1686 EXPECT_STREQ("------rwx", file_permissions_to_str(01007, buf));
1687 #endif
1688 1 }
1689
1690 1 static void test_human_readable_size(TestContext *ctx)
1691 {
1692 1 char buf[HRSIZE_MAX];
1693 1 EXPECT_STREQ(human_readable_size(0, buf), "0");
1694 1 EXPECT_STREQ(human_readable_size(1, buf), "1");
1695 1 EXPECT_STREQ(human_readable_size(10, buf), "10");
1696 1 EXPECT_STREQ(human_readable_size(1u << 10, buf), "1 KiB");
1697 1 EXPECT_STREQ(human_readable_size(4u << 10, buf), "4 KiB");
1698 1 EXPECT_STREQ(human_readable_size(9u << 20, buf), "9 MiB");
1699 1 EXPECT_STREQ(human_readable_size(1024u << 10, buf), "1 MiB");
1700 1 EXPECT_STREQ(human_readable_size(1024u << 20, buf), "1 GiB");
1701 1 EXPECT_STREQ(human_readable_size(1023u << 10, buf), "1023 KiB");
1702 1 EXPECT_STREQ(human_readable_size(1023u << 20, buf), "1023 MiB");
1703 1 EXPECT_STREQ(human_readable_size(900ull << 30, buf), "900 GiB");
1704 1 EXPECT_STREQ(human_readable_size(1ull << 62, buf), "4 EiB");
1705 1 EXPECT_STREQ(human_readable_size((1ull << 62) + 232ull, buf), "4 EiB");
1706 1 EXPECT_STREQ(human_readable_size(3ull << 61, buf), "6 EiB");
1707 1 EXPECT_STREQ(human_readable_size(11ull << 59, buf), "5.50 EiB");
1708
1709 // Compare to e.g.: numfmt --to=iec --format=%0.7f 7427273
1710 1 EXPECT_STREQ(human_readable_size(990, buf), "990");
1711 1 EXPECT_STREQ(human_readable_size(1023, buf), "1023");
1712 1 EXPECT_STREQ(human_readable_size(1025, buf), "1 KiB");
1713 1 EXPECT_STREQ(human_readable_size(1123, buf), "1.09 KiB");
1714 1 EXPECT_STREQ(human_readable_size(1124, buf), "1.10 KiB");
1715 1 EXPECT_STREQ(human_readable_size(1127, buf), "1.10 KiB");
1716 1 EXPECT_STREQ(human_readable_size(4106, buf), "4.01 KiB");
1717 1 EXPECT_STREQ(human_readable_size(4192, buf), "4.09 KiB");
1718 1 EXPECT_STREQ(human_readable_size(4195, buf), "4.09 KiB");
1719 1 EXPECT_STREQ(human_readable_size(4196, buf), "4.10 KiB");
1720 1 EXPECT_STREQ(human_readable_size(4197, buf), "4.10 KiB");
1721 1 EXPECT_STREQ(human_readable_size(6947713, buf), "6.62 MiB");
1722 1 EXPECT_STREQ(human_readable_size(7427273, buf), "7.08 MiB");
1723 1 EXPECT_STREQ(human_readable_size(1116691500ull, buf), "1.04 GiB");
1724 1 EXPECT_STREQ(human_readable_size(8951980327583ull, buf), "8.14 TiB");
1725 1 EXPECT_STREQ(human_readable_size(8951998035275183ull, buf), "7.95 PiB");
1726
1727 // Some of these results are arguably off by 0.01, but that's fine
1728 // given the approximate nature of the function and its use cases.
1729 // These tests are here mostly to exercise edge cases and provide
1730 // useful feedback when tweaking the algorithm.
1731 1 EXPECT_STREQ(human_readable_size(5242803, buf), "4.99 MiB");
1732 1 EXPECT_STREQ(human_readable_size(5242804, buf), "5 MiB");
1733 1 EXPECT_STREQ(human_readable_size(5242879, buf), "5 MiB");
1734 1 EXPECT_STREQ(human_readable_size(5242880, buf), "5 MiB");
1735 1 EXPECT_STREQ(human_readable_size(5242881, buf), "5 MiB");
1736
1737 // Compare with e.g. `units '0xFF00000000000000 bytes' EiB`
1738 1 EXPECT_STREQ(human_readable_size(0xFFFFFFFFFFFFFFFFull, buf), "16 EiB");
1739 1 EXPECT_STREQ(human_readable_size(0x7FFFFFFFFFFFFFFFull, buf), "8 EiB");
1740 1 EXPECT_STREQ(human_readable_size(0x3FFFFFFFFFFFFFFFull, buf), "4 EiB");
1741 1 EXPECT_STREQ(human_readable_size(0xFF00000000000000ull, buf), "15.93 EiB");
1742
1743 1 const uintmax_t u64pow2max = 0x8000000000000000ull;
1744 1 EXPECT_STREQ(human_readable_size(u64pow2max, buf), "8 EiB");
1745 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 1), buf), "12 EiB");
1746 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 2), buf), "10 EiB");
1747 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 3), buf), "9 EiB");
1748 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 4), buf), "8.50 EiB");
1749 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 5), buf), "8.25 EiB");
1750 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 6), buf), "8.12 EiB");
1751 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 7), buf), "8.06 EiB");
1752 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 8), buf), "8.03 EiB");
1753 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 9), buf), "8.01 EiB");
1754 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 10), buf), "8 EiB");
1755 1 EXPECT_STREQ(human_readable_size(u64pow2max | (u64pow2max >> 11), buf), "8 EiB");
1756 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1, buf), "4 EiB");
1757 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 2, buf), "2 EiB");
1758 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 3, buf), "1 EiB");
1759 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 4, buf), "512 PiB");
1760 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 2), buf), "6 EiB");
1761 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 3), buf), "5 EiB");
1762 1 EXPECT_STREQ(human_readable_size(u64pow2max >> 1 | (u64pow2max >> 4), buf), "4.50 EiB");
1763 1 }
1764
1765 1 static void test_filesize_to_str(TestContext *ctx)
1766 {
1767 1 char buf[FILESIZE_STR_MAX];
1768 1 EXPECT_STREQ(filesize_to_str(0, buf), "0");
1769 1 EXPECT_STREQ(filesize_to_str(1023, buf), "1023");
1770 1 EXPECT_STREQ(filesize_to_str(1024, buf), "1 KiB (1024)");
1771
1772 1 static_assert(18446744073709551615ull == 0xFFFFFFFFFFFFFFFFull);
1773 1 EXPECT_STREQ(filesize_to_str(18446744073709551615ull, buf), "16 EiB (18446744073709551615)");
1774 1 EXPECT_STREQ(filesize_to_str(17446744073709551615ull, buf), "15.13 EiB (17446744073709551615)");
1775 1 }
1776
1777 1 static void test_filesize_to_str_precise(TestContext *ctx)
1778 {
1779 1 char buf[PRECISE_FILESIZE_STR_MAX];
1780 1 EXPECT_STREQ(filesize_to_str_precise(0, buf), "0");
1781 1 EXPECT_STREQ(filesize_to_str_precise(1, buf), "1");
1782 1 EXPECT_STREQ(filesize_to_str_precise(99, buf), "99");
1783 1 EXPECT_STREQ(filesize_to_str_precise(1023, buf), "1023");
1784 1 EXPECT_STREQ(filesize_to_str_precise(1024, buf), "1KiB");
1785 1 EXPECT_STREQ(filesize_to_str_precise(1025, buf), "1025");
1786 1 EXPECT_STREQ(filesize_to_str_precise(2047, buf), "2047");
1787 1 EXPECT_STREQ(filesize_to_str_precise(2048, buf), "2KiB");
1788 1 EXPECT_STREQ(filesize_to_str_precise(3 << 9, buf), "1536"); // Exactly 1.5 KiB
1789 1 EXPECT_STREQ(filesize_to_str_precise(3 << 19, buf), "1536KiB"); // Exactly 1.5 MiB
1790 1 EXPECT_STREQ(filesize_to_str_precise(3 << 29, buf), "1536MiB"); // Exactly 1.5 GiB
1791 1 EXPECT_STREQ(filesize_to_str_precise((3 << 29) + 1, buf), "1610612737");
1792 1 EXPECT_STREQ(filesize_to_str_precise(0x8000000000000000ull, buf), "8EiB");
1793 1 EXPECT_STREQ(filesize_to_str_precise(0xF000000000000000ull, buf), "15EiB");
1794 1 EXPECT_STREQ(filesize_to_str_precise(0xFF00000000000000ull, buf), "16320PiB");
1795 1 EXPECT_STREQ(filesize_to_str_precise(0xFFFFFFFFFFFFFFFFull, buf), "18446744073709551615");
1796 1 }
1797
1798 1 static void test_u_char_size(TestContext *ctx)
1799 {
1800 1 EXPECT_EQ(u_char_size('\0'), 1);
1801 1 EXPECT_EQ(u_char_size(' '), 1);
1802 1 EXPECT_EQ(u_char_size('z'), 1);
1803 1 EXPECT_EQ(u_char_size(0x7E), 1);
1804 1 EXPECT_EQ(u_char_size(0x7F), 1);
1805 1 EXPECT_EQ(u_char_size(0x80), 2);
1806 1 EXPECT_EQ(u_char_size(0x81), 2);
1807 1 EXPECT_EQ(u_char_size(0xFF), 2);
1808 1 EXPECT_EQ(u_char_size(0x7FE), 2);
1809 1 EXPECT_EQ(u_char_size(0x7FF), 2);
1810 1 EXPECT_EQ(u_char_size(0x800), 3);
1811 1 EXPECT_EQ(u_char_size(0x801), 3);
1812 1 EXPECT_EQ(u_char_size(0x1234), 3);
1813 1 EXPECT_EQ(u_char_size(0xFFFE), 3);
1814 1 EXPECT_EQ(u_char_size(0xFFFF), 3);
1815 1 EXPECT_EQ(u_char_size(0x10000), 4);
1816 1 EXPECT_EQ(u_char_size(0x10001), 4);
1817 1 EXPECT_EQ(u_char_size(0x10FFFE), 4);
1818 1 EXPECT_EQ(u_char_size(0x10FFFF), 4);
1819 1 EXPECT_EQ(u_char_size(0x110000), 1);
1820 1 EXPECT_EQ(u_char_size(0x110001), 1);
1821 1 EXPECT_EQ(u_char_size(UINT32_MAX), 1);
1822 1 }
1823
1824 1 static void test_u_char_width(TestContext *ctx)
1825 {
1826 // ASCII (1 column)
1827 1 EXPECT_EQ(u_char_width('a'), 1);
1828 1 EXPECT_EQ(u_char_width('z'), 1);
1829 1 EXPECT_EQ(u_char_width('A'), 1);
1830 1 EXPECT_EQ(u_char_width('Z'), 1);
1831 1 EXPECT_EQ(u_char_width(' '), 1);
1832 1 EXPECT_EQ(u_char_width('!'), 1);
1833 1 EXPECT_EQ(u_char_width('/'), 1);
1834 1 EXPECT_EQ(u_char_width('^'), 1);
1835 1 EXPECT_EQ(u_char_width('`'), 1);
1836 1 EXPECT_EQ(u_char_width('~'), 1);
1837
1838 // Rendered in caret notation (2 columns)
1839 1 EXPECT_EQ(u_char_width('\0'), 2);
1840 1 EXPECT_EQ(u_char_width('\t'), 2);
1841 1 EXPECT_EQ(u_char_width('\n'), 2);
1842 1 EXPECT_EQ(u_char_width('\r'), 2);
1843 1 EXPECT_EQ(u_char_width(0x1F), 2);
1844 1 EXPECT_EQ(u_char_width(0x7F), 2);
1845
1846 // Unprintable (rendered as <xx> -- 4 columns)
1847 1 EXPECT_EQ(u_char_width(0x0080), 4);
1848 1 EXPECT_EQ(u_char_width(0xDFFF), 4);
1849
1850 // Zero width (0 columns)
1851 1 EXPECT_EQ(u_char_width(0xAA31), 0);
1852 1 EXPECT_EQ(u_char_width(0xAA32), 0);
1853
1854 // Double width (2 columns)
1855 1 EXPECT_EQ(u_char_width(0x2757), 2);
1856 1 EXPECT_EQ(u_char_width(0x312F), 2);
1857 1 EXPECT_EQ(u_char_width(0x30000), 2);
1858
1859 // Double width but unassigned (rendered as <xx> -- 4 columns)
1860 1 EXPECT_EQ(u_char_width(0x3A009), 4);
1861 1 EXPECT_EQ(u_char_width(0x3FFFD), 4);
1862
1863 // 1 column character >= 0x1100
1864 1 EXPECT_EQ(u_char_width(0x104B3), 1);
1865 1 }
1866
1867 1 static void test_u_to_lower(TestContext *ctx)
1868 {
1869 1 EXPECT_EQ(u_to_lower('A'), 'a');
1870 1 EXPECT_EQ(u_to_lower('Z'), 'z');
1871 1 EXPECT_EQ(u_to_lower('a'), 'a');
1872 1 EXPECT_EQ(u_to_lower('0'), '0');
1873 1 EXPECT_EQ(u_to_lower('~'), '~');
1874 1 EXPECT_EQ(u_to_lower('@'), '@');
1875 1 EXPECT_EQ(u_to_lower('\0'), '\0');
1876 1 }
1877
1878 1 static void test_u_to_upper(TestContext *ctx)
1879 {
1880 1 EXPECT_EQ(u_to_upper('a'), 'A');
1881 1 EXPECT_EQ(u_to_upper('z'), 'Z');
1882 1 EXPECT_EQ(u_to_upper('A'), 'A');
1883 1 EXPECT_EQ(u_to_upper('0'), '0');
1884 1 EXPECT_EQ(u_to_upper('~'), '~');
1885 1 EXPECT_EQ(u_to_upper('@'), '@');
1886 1 EXPECT_EQ(u_to_upper('\0'), '\0');
1887 1 }
1888
1889 1 static void test_u_is_lower(TestContext *ctx)
1890 {
1891 1 EXPECT_TRUE(u_is_lower('a'));
1892 1 EXPECT_TRUE(u_is_lower('z'));
1893 1 EXPECT_FALSE(u_is_lower('A'));
1894 1 EXPECT_FALSE(u_is_lower('Z'));
1895 1 EXPECT_FALSE(u_is_lower('0'));
1896 1 EXPECT_FALSE(u_is_lower('9'));
1897 1 EXPECT_FALSE(u_is_lower('@'));
1898 1 EXPECT_FALSE(u_is_lower('['));
1899 1 EXPECT_FALSE(u_is_lower('{'));
1900 1 EXPECT_FALSE(u_is_lower('\0'));
1901 1 EXPECT_FALSE(u_is_lower('\t'));
1902 1 EXPECT_FALSE(u_is_lower(' '));
1903 1 EXPECT_FALSE(u_is_lower(0x1F315));
1904 1 EXPECT_FALSE(u_is_lower(0x10ffff));
1905
1906 /*
1907 Even if SANE_WCTYPE is defined, we still can't make many assumptions
1908 about the iswlower(3) implementation, since it depends on all kinds
1909 of factors out of our control. Otherwise it'd be reasonable to test
1910 something like:
1911
1912 EXPECT_TRUE(u_is_lower(0x00E0));
1913 EXPECT_TRUE(u_is_lower(0x00E7));
1914 */
1915 1 }
1916
1917 1 static void test_u_is_upper(TestContext *ctx)
1918 {
1919 1 EXPECT_TRUE(u_is_upper('A'));
1920 1 EXPECT_TRUE(u_is_upper('Z'));
1921 1 EXPECT_FALSE(u_is_upper('a'));
1922 1 EXPECT_FALSE(u_is_upper('z'));
1923 1 EXPECT_FALSE(u_is_upper('0'));
1924 1 EXPECT_FALSE(u_is_upper('9'));
1925 1 EXPECT_FALSE(u_is_upper('@'));
1926 1 EXPECT_FALSE(u_is_upper('['));
1927 1 EXPECT_FALSE(u_is_upper('{'));
1928 1 EXPECT_FALSE(u_is_upper('\0'));
1929 1 EXPECT_FALSE(u_is_upper('\t'));
1930 1 EXPECT_FALSE(u_is_upper(' '));
1931 1 EXPECT_FALSE(u_is_upper(0x1F315));
1932 1 EXPECT_FALSE(u_is_upper(0x10ffff));
1933 1 EXPECT_FALSE(u_is_upper(0x00E0));
1934 1 EXPECT_FALSE(u_is_upper(0x00E7));
1935 1 }
1936
1937 1 static void test_u_is_ascii_upper(TestContext *ctx)
1938 {
1939 1 EXPECT_TRUE(u_is_ascii_upper('A'));
1940 1 EXPECT_TRUE(u_is_ascii_upper('Z'));
1941 1 EXPECT_FALSE(u_is_ascii_upper('a'));
1942 1 EXPECT_FALSE(u_is_ascii_upper('z'));
1943 1 EXPECT_FALSE(u_is_ascii_upper('0'));
1944 1 EXPECT_FALSE(u_is_ascii_upper('9'));
1945 1 EXPECT_FALSE(u_is_ascii_upper('@'));
1946 1 EXPECT_FALSE(u_is_ascii_upper('['));
1947 1 EXPECT_FALSE(u_is_ascii_upper('{'));
1948 1 EXPECT_FALSE(u_is_ascii_upper('\0'));
1949 1 EXPECT_FALSE(u_is_ascii_upper('\t'));
1950 1 EXPECT_FALSE(u_is_ascii_upper(' '));
1951 1 EXPECT_FALSE(u_is_ascii_upper(0x7F));
1952 1 EXPECT_FALSE(u_is_ascii_upper(0x1D440));
1953 1 EXPECT_FALSE(u_is_ascii_upper(UNICODE_MAX_VALID_CODEPOINT));
1954 1 }
1955
1956 1 static void test_u_is_cntrl(TestContext *ctx)
1957 {
1958 1 EXPECT_TRUE(u_is_cntrl(0x00));
1959 1 EXPECT_TRUE(u_is_cntrl(0x09));
1960 1 EXPECT_TRUE(u_is_cntrl(0x0D));
1961 1 EXPECT_TRUE(u_is_cntrl(0x1F));
1962 1 EXPECT_TRUE(u_is_cntrl(0x7F));
1963 1 EXPECT_TRUE(u_is_cntrl(0x80));
1964 1 EXPECT_TRUE(u_is_cntrl(0x81));
1965 1 EXPECT_TRUE(u_is_cntrl(0x9E));
1966 1 EXPECT_TRUE(u_is_cntrl(0x9F));
1967 1 EXPECT_FALSE(u_is_cntrl(0x20));
1968 1 EXPECT_FALSE(u_is_cntrl(0x21));
1969 1 EXPECT_FALSE(u_is_cntrl(0x7E));
1970 1 EXPECT_FALSE(u_is_cntrl(0xA0));
1971 1 EXPECT_FALSE(u_is_cntrl(0x41));
1972 1 EXPECT_FALSE(u_is_cntrl(0x61));
1973 1 EXPECT_FALSE(u_is_cntrl(0xFF));
1974 1 }
1975
1976 1 static void test_u_is_unicode(TestContext *ctx)
1977 {
1978 1 EXPECT_TRUE(u_is_unicode(0));
1979 1 EXPECT_TRUE(u_is_unicode(1));
1980 1 EXPECT_TRUE(u_is_unicode(UNICODE_MAX_VALID_CODEPOINT));
1981 1 EXPECT_FALSE(u_is_unicode(UNICODE_MAX_VALID_CODEPOINT + 1));
1982 1 }
1983
1984 1 static void test_u_is_zero_width(TestContext *ctx)
1985 {
1986 // Default ignorable codepoints:
1987 1 EXPECT_TRUE(u_is_zero_width(0x034F));
1988 1 EXPECT_TRUE(u_is_zero_width(0x061C));
1989 1 EXPECT_TRUE(u_is_zero_width(0x115F));
1990 1 EXPECT_TRUE(u_is_zero_width(0x1160));
1991 1 EXPECT_TRUE(u_is_zero_width(0x180B));
1992 1 EXPECT_TRUE(u_is_zero_width(0x200B));
1993 1 EXPECT_TRUE(u_is_zero_width(0x202E));
1994 1 EXPECT_TRUE(u_is_zero_width(0xFEFF));
1995 1 EXPECT_TRUE(u_is_zero_width(0xE0000));
1996 1 EXPECT_TRUE(u_is_zero_width(0xE0FFF));
1997 // Non-spacing marks:
1998 1 EXPECT_TRUE(u_is_zero_width(0x0300));
1999 1 EXPECT_TRUE(u_is_zero_width(0x0730));
2000 1 EXPECT_TRUE(u_is_zero_width(0x11839));
2001 1 EXPECT_TRUE(u_is_zero_width(0x1183A));
2002 1 EXPECT_TRUE(u_is_zero_width(0xE01EF));
2003 // Not zero-width:
2004 1 EXPECT_FALSE(u_is_zero_width(0x0000));
2005 1 EXPECT_FALSE(u_is_zero_width('Z'));
2006 1 }
2007
2008 1 static void test_u_is_special_whitespace(TestContext *ctx)
2009 {
2010 1 EXPECT_FALSE(u_is_special_whitespace(' '));
2011 1 EXPECT_FALSE(u_is_special_whitespace('\t'));
2012 1 EXPECT_FALSE(u_is_special_whitespace('\n'));
2013 1 EXPECT_FALSE(u_is_special_whitespace('a'));
2014 1 EXPECT_FALSE(u_is_special_whitespace(0x1680));
2015 1 EXPECT_FALSE(u_is_special_whitespace(0x3000));
2016 1 EXPECT_TRUE(u_is_special_whitespace(0x00A0));
2017 1 EXPECT_TRUE(u_is_special_whitespace(0x00AD));
2018 1 EXPECT_TRUE(u_is_special_whitespace(0x2000));
2019 1 EXPECT_TRUE(u_is_special_whitespace(0x200a));
2020 1 EXPECT_TRUE(u_is_special_whitespace(0x2028));
2021 1 EXPECT_TRUE(u_is_special_whitespace(0x2029));
2022 1 EXPECT_TRUE(u_is_special_whitespace(0x202f));
2023 1 EXPECT_TRUE(u_is_special_whitespace(0x205f));
2024 1 }
2025
2026 1 static void test_u_is_unprintable(TestContext *ctx)
2027 {
2028 // Private-use characters ------------------------------------------------
2029 // • https://www.unicode.org/faq/private_use.html#pua2
2030 // • https://www.unicode.org/versions/latest/core-spec/chapter-2/#G286941:~:text=Private%2Duse,-Usage
2031
2032 // There are three ranges of private-use characters in the standard.
2033 // The main range in the BMP is U+E000..U+F8FF, containing 6,400
2034 // private-use characters.
2035 1 EXPECT_FALSE(u_is_unprintable(0xE000));
2036 1 EXPECT_FALSE(u_is_unprintable(0xF8FF));
2037
2038 // ... there are also two large ranges of supplementary private-use
2039 // characters, consisting of most of the code points on planes 15
2040 // and 16: U+F0000..U+FFFFD and U+100000..U+10FFFD. Together those
2041 // ranges allocate another 131,068 private-use characters.
2042 1 EXPECT_FALSE(u_is_unprintable(0xF0000));
2043 1 EXPECT_FALSE(u_is_unprintable(0xFFFFD));
2044 1 EXPECT_FALSE(u_is_unprintable(0x100000));
2045 1 EXPECT_FALSE(u_is_unprintable(0x10FFFD));
2046
2047 // Surrogates ------------------------------------------------------------
2048 // • https://www.unicode.org/versions/latest/core-spec/chapter-3/#G2630
2049 // • https://www.unicode.org/versions/latest/core-spec/chapter-2/#G286941:~:text=Surrogate,-Permanently
2050 1 EXPECT_TRUE(u_is_unprintable(0xD800));
2051 1 EXPECT_TRUE(u_is_unprintable(0xDBFF));
2052 1 EXPECT_TRUE(u_is_unprintable(0xDC00));
2053 1 EXPECT_TRUE(u_is_unprintable(0xDFFF));
2054
2055 // Non-characters --------------------------------------------------------
2056 // • https://www.unicode.org/faq/private_use.html#noncharacters
2057 // • https://www.unicode.org/versions/latest/core-spec/chapter-2/#G286941:~:text=Noncharacter,-Permanently
2058 1 unsigned int noncharacter_count = 0;
2059
2060 // "A contiguous range of 32 noncharacters: U+FDD0..U+FDEF in the BMP"
2061
2/2
✓ Branch 26 → 23 taken 32 times.
✓ Branch 26 → 27 taken 1 time.
34 for (CodePoint u = 0xFDD0; u <= 0xFDEF; u++) {
2062 32 EXPECT_TRUE(u_is_unprintable(u));
2063 32 noncharacter_count++;
2064 }
2065
2066 // "The last two code points of the BMP, U+FFFE and U+FFFF"
2067 1 EXPECT_TRUE(u_is_unprintable(0xFFFE));
2068 1 EXPECT_TRUE(u_is_unprintable(0xFFFF));
2069 1 noncharacter_count += 2;
2070
2071 // "The last two code points of each of the 16 supplementary planes:
2072 // U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, ... U+10FFFE, U+10FFFF"
2073
2/2
✓ Branch 37 → 32 taken 16 times.
✓ Branch 37 → 38 taken 1 time.
17 for (CodePoint step = 1; step <= 16; step++) {
2074 16 const CodePoint u = (0x10000 * step) + 0xFFFE;
2075 16 EXPECT_TRUE(u_is_unprintable(u));
2076 16 EXPECT_TRUE(u_is_unprintable(u + 1));
2077 16 noncharacter_count += 2;
2078 }
2079
2080 // "Q: How many noncharacters does Unicode have?"
2081 // "A: Exactly 66"
2082 1 EXPECT_EQ(noncharacter_count, 66);
2083 1 }
2084
2085 1 static void test_u_str_width(TestContext *ctx)
2086 {
2087 1 static const char ustr[] =
2088 "\xE0\xB8\x81\xE0\xB8\xB3\xE0\xB9\x81\xE0\xB8\x9E\xE0\xB8"
2089 "\x87\xE0\xB8\xA1\xE0\xB8\xB5\xE0\xB8\xAB\xE0\xB8\xB9"
2090 ;
2091
2092 1 EXPECT_EQ(u_str_width("foo"), 3);
2093 1 EXPECT_EQ(u_str_width(ustr), 7);
2094 1 }
2095
2096 1 static void test_u_set_char_raw(TestContext *ctx)
2097 {
2098 1 char buf[UTF8_MAX_SEQ_LEN] = "";
2099 1 EXPECT_EQ(sizeof(buf), 4);
2100 1 EXPECT_EQ(u_set_char_raw(buf, 'a'), 1);
2101 1 EXPECT_EQ(buf[0], 'a');
2102
2103 1 EXPECT_EQ(u_set_char_raw(buf, '\0'), 1);
2104 1 EXPECT_EQ(buf[0], '\0');
2105
2106 1 EXPECT_EQ(u_set_char_raw(buf, 0x1F), 1);
2107 1 EXPECT_EQ(buf[0], '\x1F');
2108
2109 1 EXPECT_EQ(u_set_char_raw(buf, 0x7F), 1);
2110 1 EXPECT_EQ(buf[0], '\x7F');
2111
2112 1 EXPECT_EQ(u_set_char_raw(buf, 0x7FF), 2);
2113 1 EXPECT_EQ(buf[0], '\xDF');
2114 1 EXPECT_EQ(buf[1], '\xBF');
2115
2116 1 EXPECT_EQ(u_set_char_raw(buf, 0xFF45), 3);
2117 1 EXPECT_EQ(buf[0], '\xEF');
2118 1 EXPECT_EQ(buf[1], '\xBD');
2119 1 EXPECT_EQ(buf[2], '\x85');
2120
2121 1 EXPECT_EQ(u_set_char_raw(buf, 0x1F311), 4);
2122 1 EXPECT_EQ(buf[0], '\xF0');
2123 1 EXPECT_EQ(buf[1], '\x9F');
2124 1 EXPECT_EQ(buf[2], '\x8C');
2125 1 EXPECT_EQ(buf[3], '\x91');
2126
2127 1 buf[1] = 0x88;
2128 1 EXPECT_EQ(u_set_char_raw(buf, 0x110000), 1);
2129 1 EXPECT_EQ(buf[0], '\0');
2130 1 EXPECT_EQ(buf[1], '\x88');
2131
2132 1 EXPECT_EQ(u_set_char_raw(buf, 0x110042), 1);
2133 1 EXPECT_EQ(buf[0], '\x42');
2134 1 EXPECT_EQ(buf[1], '\x88');
2135 1 }
2136
2137 1 static void test_u_set_char(TestContext *ctx)
2138 {
2139 1 char buf[U_SET_CHAR_MAXLEN] = "";
2140 1 EXPECT_EQ(sizeof(buf), 4);
2141 1 EXPECT_EQ(u_set_char(buf, 'a'), 1);
2142 1 EXPECT_EQ(buf[0], 'a');
2143
2144 1 EXPECT_EQ(u_set_char(buf, 0x00DF), 2);
2145 1 EXPECT_EQ(buf[0], '\xC3');
2146 1 EXPECT_EQ(buf[1], '\x9F');
2147
2148 1 EXPECT_EQ(u_set_char(buf, 0x0E01), 3);
2149 1 EXPECT_EQ(buf[0], '\xE0');
2150 1 EXPECT_EQ(buf[1], '\xB8');
2151 1 EXPECT_EQ(buf[2], '\x81');
2152
2153 1 EXPECT_EQ(UTF8_MAX_SEQ_LEN, 4);
2154 1 EXPECT_EQ(u_set_char(buf, 0x1F914), 4);
2155 1 EXPECT_EQ(buf[0], '\xF0');
2156 1 EXPECT_EQ(buf[1], '\x9F');
2157 1 EXPECT_EQ(buf[2], '\xA4');
2158 1 EXPECT_EQ(buf[3], '\x94');
2159
2160 1 EXPECT_EQ(U_SET_HEX_LEN, 4);
2161 1 EXPECT_EQ(u_set_char(buf, 0x10FFFF), 4);
2162 1 EXPECT_EQ(buf[0], '<');
2163 1 EXPECT_EQ(buf[1], '?');
2164 1 EXPECT_EQ(buf[2], '?');
2165 1 EXPECT_EQ(buf[3], '>');
2166
2167 1 EXPECT_EQ(u_set_char(buf, '\0'), 2);
2168 1 EXPECT_EQ(buf[0], '^');
2169 1 EXPECT_EQ(buf[1], '@');
2170
2171 1 EXPECT_EQ(u_set_char(buf, '\t'), 2);
2172 1 EXPECT_EQ(buf[0], '^');
2173 1 EXPECT_EQ(buf[1], 'I');
2174
2175 1 EXPECT_EQ(u_set_char(buf, 0x1F), 2);
2176 1 EXPECT_EQ(buf[0], '^');
2177 1 EXPECT_EQ(buf[1], '_');
2178
2179 1 EXPECT_EQ(u_set_char(buf, 0x7F), 2);
2180 1 EXPECT_EQ(buf[0], '^');
2181 1 EXPECT_EQ(buf[1], '?');
2182
2183 1 EXPECT_EQ(u_set_char(buf, 0x80), 4);
2184 1 EXPECT_EQ(buf[0], '<');
2185 1 EXPECT_EQ(buf[1], '?');
2186 1 EXPECT_EQ(buf[2], '?');
2187 1 EXPECT_EQ(buf[3], '>');
2188
2189 1 EXPECT_EQ(u_set_char(buf, 0x7E), 1);
2190 1 EXPECT_EQ(buf[0], '~');
2191
2192 1 EXPECT_EQ(u_set_char(buf, 0x20), 1);
2193 1 EXPECT_EQ(buf[0], ' ');
2194
2195 1 CodePoint u = -0x5Bu; // See comment in u_set_hex()
2196 1 EXPECT_UINT_EQ(u, 0xFFFFFFA5u);
2197 1 EXPECT_EQ(u_set_char(buf, u), 4);
2198 1 EXPECT_EQ(buf[0], '<');
2199 1 EXPECT_EQ(buf[1], '5');
2200 1 EXPECT_EQ(buf[2], 'b');
2201 1 EXPECT_EQ(buf[3], '>');
2202 1 }
2203
2204 1 static void test_u_make_printable(TestContext *ctx)
2205 {
2206 1 char buf[5];
2207 1 MakePrintableFlags flags = 0;
2208 1 EXPECT_EQ(sizeof(buf), U_SET_CHAR_MAXLEN + 1);
2209 1 memset(buf, '_', sizeof(buf));
2210 1 EXPECT_EQ(u_make_printable(strview("\xffxyz"), buf, sizeof(buf), flags), 4);
2211 1 EXPECT_STREQ(buf, "<ff>");
2212
2213 // Enough space for `U_SET_CHAR_MAXLEN + 1` is needed, regardless of
2214 // the CodePoint encountered, so 5 is the minimum remaining space
2215 // required in order to write more than just a null-terminator
2216 1 memset(buf, '_', sizeof(buf));
2217 1 EXPECT_TRUE(sizeof(buf) >= 5);
2218 1 EXPECT_EQ(u_make_printable(strview("12345"), buf, 1, flags), 0);
2219 1 EXPECT_EQ(u_make_printable(strview("12345"), buf, 2, flags), 0);
2220 1 EXPECT_EQ(u_make_printable(strview("12345"), buf, 3, flags), 0);
2221 1 EXPECT_EQ(u_make_printable(strview("12345"), buf, 4, flags), 0);
2222 1 EXPECT_EQ(buf[0], '\0');
2223 1 EXPECT_EQ(buf[1], '_');
2224 1 EXPECT_EQ(buf[2], '_');
2225 1 EXPECT_EQ(buf[3], '_');
2226 1 EXPECT_EQ(buf[4], '_');
2227 1 memset(buf, '_', sizeof(buf));
2228 1 EXPECT_EQ(u_make_printable(strview("12345"), buf, 5, flags), 1);
2229 1 EXPECT_EQ(buf[0], '1');
2230 1 EXPECT_EQ(buf[1], '\0');
2231 1 EXPECT_EQ(buf[2], '_');
2232 1 EXPECT_EQ(buf[3], '_');
2233 1 EXPECT_EQ(buf[4], '_');
2234
2235 1 memset(buf, '_', sizeof(buf));
2236 1 EXPECT_EQ(u_make_printable(strview("\x7F\n123"), buf, 5, flags), 2);
2237 1 EXPECT_STREQ(buf, "^?");
2238 1 EXPECT_EQ(buf[3], '_');
2239
2240 1 flags |= MPF_C0_SYMBOLS;
2241 1 memset(buf, '_', sizeof(buf));
2242 1 EXPECT_EQ(u_make_printable(strview("\x7F\n123"), buf, 5, flags), 3);
2243 1 EXPECT_STREQ(buf, "\xE2\x90\xA1"); // UTF-8 encoding of U+2421
2244 1 EXPECT_EQ(buf[4], '_');
2245
2246 1 memset(buf, '_', sizeof(buf));
2247 1 EXPECT_EQ(u_make_printable(string_view(STRN("\0xyz")), buf, 5, flags), 3);
2248 1 EXPECT_STREQ(buf, "\xE2\x90\x80"); // UTF-8 encoding of U+2400
2249 1 EXPECT_EQ(buf[4], '_');
2250 1 }
2251
2252 1 static void test_u_get_char(TestContext *ctx)
2253 {
2254 1 static const char a[] = "//";
2255 1 size_t idx = 0;
2256 1 EXPECT_UINT_EQ(u_get_char(a, sizeof a, &idx), '/');
2257 1 ASSERT_EQ(idx, 1);
2258 1 EXPECT_UINT_EQ(u_get_char(a, sizeof a, &idx), '/');
2259 1 ASSERT_EQ(idx, 2);
2260 1 EXPECT_UINT_EQ(u_get_char(a, sizeof a, &idx), 0);
2261 1 ASSERT_EQ(idx, 3);
2262
2263 // Non-character U+FDD0.
2264 // • https://www.unicode.org/faq/private_use.html#nonchar4:~:text=EF%20B7%2090
2265 1 static const char nc1[] = "\xEF\xB7\x90";
2266 1 idx = 0;
2267 1 EXPECT_UINT_EQ(u_get_char(nc1, sizeof nc1, &idx), 0xFDD0);
2268 1 ASSERT_EQ(idx, 3);
2269 1 EXPECT_TRUE(u_is_unprintable(0xFDD0));
2270
2271 // Non-character U+FFFE
2272 // • https://www.unicode.org/faq/private_use.html#nonchar4:~:text=EF%20BF%20B%23
2273 1 static const char nc2[] = "\xEF\xBF\xBE";
2274 1 idx = 0;
2275 1 EXPECT_UINT_EQ(u_get_char(nc2, sizeof nc2, &idx), 0xFFFE);
2276 1 ASSERT_EQ(idx, 3);
2277 1 EXPECT_TRUE(u_is_unprintable(0xFFFE));
2278
2279 // -----------------------------------------------------------------------
2280
2281 // "In UTF-8, the code point sequence <004D, 0430, 4E8C, 10302> is
2282 // represented as <4D D0 B0 E4 BA 8C F0 90 8C 82>, where <4D>
2283 // corresponds to U+004D, <D0 B0> corresponds to U+0430, <E4 BA 8C>
2284 // corresponds to U+4E8C, and <F0 90 8C 82> corresponds to U+10302."
2285 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G31703
2286 1 static const char b[] = "\x4D\xD0\xB0\xE4\xBA\x8C\xF0\x90\x8C\x82";
2287 1 idx = 0;
2288 1 EXPECT_UINT_EQ(u_get_char(b, sizeof b, &idx), 0x004D);
2289 1 ASSERT_EQ(idx, 1);
2290 1 EXPECT_UINT_EQ(u_get_char(b, sizeof b, &idx), 0x0430);
2291 1 ASSERT_EQ(idx, 3);
2292 1 EXPECT_UINT_EQ(u_get_char(b, sizeof b, &idx), 0x4E8C);
2293 1 ASSERT_EQ(idx, 6);
2294 1 EXPECT_UINT_EQ(u_get_char(b, sizeof b, &idx), 0x10302);
2295 1 ASSERT_EQ(idx, 10);
2296
2297 // "The byte sequence <F4 80 83 92> is well-formed, because every
2298 // byte in that sequence matches a byte range in a row of the table
2299 // (the last row)."
2300 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G27288
2301 1 idx = 0;
2302 1 EXPECT_UINT_EQ(u_get_char(STRN("\xF4\x80\x83\x92"), &idx), 0x1000D2);
2303 1 EXPECT_EQ(idx, 4);
2304
2305 // Overlong encodings are consumed as individual bytes and
2306 // each byte returned negated (to indicate that it's invalid).
2307 // See also: u_get_nonascii(), u_seq_len_ok(), u_char_size()
2308
2309 // Overlong (2 byte) encoding of U+002F ('/').
2310 // "The byte sequence <C0 AF> is ill-formed, because C0 is not
2311 // well-formed in the “First Byte” column."
2312 1 static const char ol1[] = "\xC0\xAF";
2313 1 idx = 0;
2314 1 EXPECT_UINT_EQ(u_get_char(ol1, sizeof ol1, &idx), -0xC0u);
2315 1 ASSERT_EQ(idx, 1);
2316 1 EXPECT_UINT_EQ(u_get_char(ol1, sizeof ol1, &idx), -0xAFu);
2317 1 ASSERT_EQ(idx, 2);
2318
2319 // Overlong (3 byte) encoding of U+002F ('/')
2320 1 static const char ol2[] = "\xE0\x80\xAF";
2321 1 idx = 0;
2322 1 EXPECT_UINT_EQ(u_get_char(ol2, sizeof ol2, &idx), -0xE0u);
2323 1 ASSERT_EQ(idx, 1);
2324 1 EXPECT_UINT_EQ(u_get_char(ol2, sizeof ol2, &idx), -0x80u);
2325 1 ASSERT_EQ(idx, 2);
2326 1 EXPECT_UINT_EQ(u_get_char(ol2, sizeof ol2, &idx), -0xAFu);
2327 1 ASSERT_EQ(idx, 3);
2328
2329 // Overlong (2 byte) encoding of U+0041 ('A')
2330 1 static const char ol3[] = "\xC1\x81";
2331 1 idx = 0;
2332 1 EXPECT_UINT_EQ(u_get_char(ol3, sizeof ol3, &idx), -0xC1u);
2333 1 ASSERT_EQ(idx, 1);
2334 1 EXPECT_UINT_EQ(u_get_char(ol3, sizeof ol3, &idx), -0x81u);
2335 1 ASSERT_EQ(idx, 2);
2336
2337 // "The byte sequence <E0 9F 80> is ill-formed, because in the row
2338 // where E0 is well-formed as a first byte, 9F is not well-formed
2339 // as a second byte."
2340 1 static const char ol4[] = "\xE0\x9F\x80";
2341 1 idx = 0;
2342 1 EXPECT_UINT_EQ(u_get_char(ol4, sizeof ol4, &idx), -0xE0u);
2343 1 ASSERT_EQ(idx, 1);
2344 1 EXPECT_UINT_EQ(u_get_char(ol4, sizeof ol4, &idx), -0x9Fu);
2345 1 ASSERT_EQ(idx, 2);
2346 1 EXPECT_UINT_EQ(u_get_char(ol4, sizeof ol4, &idx), -0x80u);
2347 1 ASSERT_EQ(idx, 3);
2348
2349 // "For example, in processing the UTF-8 code unit sequence
2350 // <F0 80 80 41>, the only formal requirement mandated by Unicode
2351 // conformance for a converter is that the <41> be processed and
2352 // correctly interpreted as <U+0041>. The converter could return
2353 // <U+FFFD, U+0041>, handling <F0 80 80> as a single error, or
2354 // <U+FFFD, U+FFFD, U+FFFD, U+0041>, handling each byte of
2355 // <F0 80 80> as a separate error, or could take other approaches
2356 // to signalling <F0 80 80> as an ill-formed code unit subsequence."
2357 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G48534
2358 1 static const char e1[] = "\xF0\x80\x80\x41";
2359 1 idx = 0;
2360 1 EXPECT_UINT_EQ(u_get_char(e1, sizeof e1, &idx), -0xF0u);
2361 1 ASSERT_EQ(idx, 1);
2362 1 EXPECT_UINT_EQ(u_get_char(e1, sizeof e1, &idx), -0x80u);
2363 1 ASSERT_EQ(idx, 2);
2364 1 EXPECT_UINT_EQ(u_get_char(e1, sizeof e1, &idx), -0x80u);
2365 1 ASSERT_EQ(idx, 3);
2366 1 EXPECT_UINT_EQ(u_get_char(e1, sizeof e1, &idx), 0x41u);
2367 1 ASSERT_EQ(idx, 4);
2368
2369 // The following test cases are taken from Unicode's examples in
2370 // Tables 3-{8,9,10,11}. We return the negation of each individual
2371 // byte in an ill-formed sequence, instead of the "maximal subpart"
2372 // approach mentioned there. This is explicitly permitted by the
2373 // spec and is more flexible for our purposes:
2374 //
2375 // "Although the Unicode Standard does not require this practice for
2376 // conformance, the following text describes this practice and gives
2377 // detailed examples."
2378 //
2379 // - https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G66453
2380
2381 // Table 3-8. … Non-Shortest Form Sequences
2382 // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G67519
2383 1 static const char s8[] = "\xC0\xAF\xE0\x80\xBF\xF0\x81\x82\x41";
2384 1 idx = 0;
2385 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0xC0u);
2386 1 ASSERT_EQ(idx, 1);
2387 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0xAFu);
2388 1 ASSERT_EQ(idx, 2);
2389 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0xE0u);
2390 1 ASSERT_EQ(idx, 3);
2391 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0x80u);
2392 1 ASSERT_EQ(idx, 4);
2393 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0xBFu);
2394 1 ASSERT_EQ(idx, 5);
2395 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0xF0u);
2396 1 ASSERT_EQ(idx, 6);
2397 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0x81u);
2398 1 ASSERT_EQ(idx, 7);
2399 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), -0x82u);
2400 1 ASSERT_EQ(idx, 8);
2401 1 EXPECT_UINT_EQ(u_get_char(s8, sizeof s8, &idx), 0x41u);
2402 1 ASSERT_EQ(idx, 9);
2403
2404 // Table 3-9. … Ill-Formed Sequences for Surrogates
2405 // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G67520
2406 1 static const char s9[] = "\xED\xA0\x80\xED\xBF\xBF\xED\xAF\x41";
2407 1 EXPECT_TRUE(u_is_surrogate(0xD800)); // "\xED\xA0\x80"
2408 1 EXPECT_TRUE(u_is_unprintable(0xD800));
2409 1 idx = 0;
2410 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xEDu);
2411 1 ASSERT_EQ(idx, 1);
2412 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xA0u);
2413 1 ASSERT_EQ(idx, 2);
2414 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0x80u);
2415 1 ASSERT_EQ(idx, 3);
2416 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xEDu);
2417 1 ASSERT_EQ(idx, 4);
2418 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xBFu);
2419 1 ASSERT_EQ(idx, 5);
2420 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xBFu);
2421 1 ASSERT_EQ(idx, 6);
2422 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xEDu);
2423 1 ASSERT_EQ(idx, 7);
2424 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), -0xAFu);
2425 1 ASSERT_EQ(idx, 8);
2426 1 EXPECT_UINT_EQ(u_get_char(s9, sizeof s9, &idx), 0x41u);
2427 1 ASSERT_EQ(idx, 9);
2428
2429 // Table 3-10. … Other Ill-Formed Sequences
2430 // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G68064
2431 1 static const char s10[] = "\xF4\x91\x92\x93\xFF\x41\x80\xBF\x42";
2432 1 idx = 0;
2433 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0xF4u);
2434 1 ASSERT_EQ(idx, 1);
2435 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0x91u);
2436 1 ASSERT_EQ(idx, 2);
2437 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0x92u);
2438 1 ASSERT_EQ(idx, 3);
2439 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0x93u);
2440 1 ASSERT_EQ(idx, 4);
2441 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0xFFu);
2442 1 ASSERT_EQ(idx, 5);
2443 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), 0x41u);
2444 1 ASSERT_EQ(idx, 6);
2445 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0x80u);
2446 1 ASSERT_EQ(idx, 7);
2447 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), -0xBFu);
2448 1 ASSERT_EQ(idx, 8);
2449 1 EXPECT_UINT_EQ(u_get_char(s10, sizeof s10, &idx), 0x42u);
2450 1 ASSERT_EQ(idx, 9);
2451
2452 // Table 3-11. … Truncated Sequences
2453 // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G68202
2454 1 static const char s11[] = "\xE1\x80\xE2\xF0\x91\x92\xF1\xBF\x41";
2455 1 idx = 0;
2456 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0xE1u);
2457 1 ASSERT_EQ(idx, 1);
2458 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0x80u);
2459 1 ASSERT_EQ(idx, 2);
2460 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0xE2u);
2461 1 ASSERT_EQ(idx, 3);
2462 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0xF0u);
2463 1 ASSERT_EQ(idx, 4);
2464 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0x91u);
2465 1 ASSERT_EQ(idx, 5);
2466 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0x92u);
2467 1 ASSERT_EQ(idx, 6);
2468 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0xF1u);
2469 1 ASSERT_EQ(idx, 7);
2470 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), -0xBFu);
2471 1 ASSERT_EQ(idx, 8);
2472 1 EXPECT_UINT_EQ(u_get_char(s11, sizeof s11, &idx), 0x41u);
2473 1 ASSERT_EQ(idx, 9);
2474
2475 // TODO: Provide explicit coverage for each row of Table 3-7:
2476 // https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G27506
2477 1 }
2478
2479 1 static void test_u_prev_char(TestContext *ctx)
2480 {
2481 1 const char *buf = "\xE6\xB7\xB1\xE5\x9C\xB3\xE5\xB8\x82"; // 深圳市
2482 1 size_t idx = 9;
2483 1 CodePoint c = u_prev_char(buf, &idx);
2484 1 EXPECT_UINT_EQ(c, 0x5E02);
2485 1 EXPECT_EQ(idx, 6);
2486 1 c = u_prev_char(buf, &idx);
2487 1 EXPECT_UINT_EQ(c, 0x5733);
2488 1 EXPECT_EQ(idx, 3);
2489 1 c = u_prev_char(buf, &idx);
2490 1 EXPECT_UINT_EQ(c, 0x6DF1);
2491 1 EXPECT_EQ(idx, 0);
2492
2493 1 idx = 1;
2494 1 c = u_prev_char(buf, &idx);
2495 1 EXPECT_UINT_EQ(c, -0xE6u);
2496 1 EXPECT_EQ(idx, 0);
2497
2498 1 buf = "Shenzhen";
2499 1 idx = 8;
2500 1 c = u_prev_char(buf, &idx);
2501 1 EXPECT_UINT_EQ(c, 'n');
2502 1 EXPECT_EQ(idx, 7);
2503 1 c = u_prev_char(buf, &idx);
2504 1 EXPECT_UINT_EQ(c, 'e');
2505 1 EXPECT_EQ(idx, 6);
2506
2507 1 buf = "\xF0\x9F\xA5\xA3\xF0\x9F\xA5\xA4"; // 🥣🥤
2508 1 idx = 8;
2509 1 c = u_prev_char(buf, &idx);
2510 1 EXPECT_UINT_EQ(c, 0x1F964);
2511 1 EXPECT_EQ(idx, 4);
2512 1 c = u_prev_char(buf, &idx);
2513 1 EXPECT_UINT_EQ(c, 0x1F963);
2514 1 EXPECT_EQ(idx, 0);
2515
2516 1 buf = "\xF0\xF5";
2517 1 idx = 2;
2518 1 c = u_prev_char(buf, &idx);
2519 1 EXPECT_UINT_EQ(-c, 0xF5);
2520 1 EXPECT_EQ(idx, 1);
2521 1 c = u_prev_char(buf, &idx);
2522 1 EXPECT_UINT_EQ(-c, 0xF0);
2523 1 EXPECT_EQ(idx, 0);
2524
2525 1 buf = "\xF5\xF0";
2526 1 idx = 2;
2527 1 c = u_prev_char(buf, &idx);
2528 1 EXPECT_UINT_EQ(-c, 0xF0);
2529 1 EXPECT_EQ(idx, 1);
2530 1 c = u_prev_char(buf, &idx);
2531 1 EXPECT_UINT_EQ(-c, 0xF5);
2532 1 EXPECT_EQ(idx, 0);
2533 1 }
2534
2535 1 static void test_u_skip_chars(TestContext *ctx)
2536 {
2537 1 EXPECT_EQ(u_skip_chars("12345", 5), 5);
2538 1 EXPECT_EQ(u_skip_chars("12345", 3), 3);
2539 1 EXPECT_EQ(u_skip_chars("12345", 0), 0);
2540
2541 // Display: <c1> x ^G y 😁 z ^G .
2542 1 static const char str[] = "\xc1x\ay\xF0\x9F\x98\x81z\a.";
2543 1 const size_t w = u_str_width(str);
2544 1 const size_t n = sizeof(str) - 1;
2545 1 EXPECT_EQ(w, 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1);
2546 1 EXPECT_EQ(w, 14);
2547 1 EXPECT_EQ(n, 11);
2548
2549 1 EXPECT_EQ(u_skip_chars(str, 1), 1); // <c1>
2550 1 EXPECT_EQ(u_skip_chars(str, 2), 1);
2551 1 EXPECT_EQ(u_skip_chars(str, 3), 1);
2552 1 EXPECT_EQ(u_skip_chars(str, 4), 1);
2553 1 EXPECT_EQ(u_skip_chars(str, 5), 2); // x
2554 1 EXPECT_EQ(u_skip_chars(str, 6), 3); // ^G
2555 1 EXPECT_EQ(u_skip_chars(str, 7), 3);
2556 1 EXPECT_EQ(u_skip_chars(str, 8), 4); // y
2557 1 EXPECT_EQ(u_skip_chars(str, 9), 8); // 😁
2558 1 EXPECT_EQ(u_skip_chars(str, 10), 8);
2559 1 EXPECT_EQ(u_skip_chars(str, 11), 9); // z
2560 1 EXPECT_EQ(u_skip_chars(str, 12), 10); // ^G
2561 1 EXPECT_EQ(u_skip_chars(str, 13), 10);
2562 1 EXPECT_EQ(14, w);
2563 1 EXPECT_EQ(u_skip_chars(str, 14), n); // .
2564 1 EXPECT_TRUE(15 > w);
2565 1 EXPECT_EQ(u_skip_chars(str, 15), n);
2566 1 EXPECT_EQ(u_skip_chars(str, 16), n);
2567 1 }
2568
2569 1 static void test_ptr_array(TestContext *ctx)
2570 {
2571 1 PointerArray a = ptr_array_new(0);
2572 1 EXPECT_EQ(a.count, 0);
2573 1 EXPECT_EQ(a.alloc, 0);
2574 1 EXPECT_NULL(a.ptrs);
2575 1 ptr_array_append(&a, NULL);
2576 1 EXPECT_EQ(a.count, 1);
2577 1 EXPECT_EQ(a.alloc, 8);
2578 1 EXPECT_NONNULL(a.ptrs);
2579
2580 1 ptr_array_append(&a, NULL);
2581 1 ptr_array_append(&a, xstrdup("foo"));
2582 1 ptr_array_append(&a, NULL);
2583 1 ptr_array_append(&a, xstrdup("bar"));
2584 1 ptr_array_append(&a, NULL);
2585 1 ptr_array_append(&a, NULL);
2586 1 EXPECT_EQ(a.count, 7);
2587 1 EXPECT_EQ(a.alloc, 8);
2588
2589 1 ptr_array_trim_nulls(&a);
2590 1 EXPECT_EQ(a.count, 4);
2591 1 EXPECT_STREQ(a.ptrs[0], "foo");
2592 1 EXPECT_NULL(a.ptrs[1]);
2593 1 EXPECT_STREQ(a.ptrs[2], "bar");
2594 1 EXPECT_NULL(a.ptrs[3]);
2595 1 ptr_array_trim_nulls(&a);
2596 1 EXPECT_EQ(a.count, 4);
2597
2598 1 ptr_array_free(&a);
2599 1 EXPECT_EQ(a.count, 0);
2600 1 ptr_array_trim_nulls(&a);
2601 1 EXPECT_EQ(a.count, 0);
2602
2603 1 a = ptr_array_new(0);
2604 1 EXPECT_EQ(a.alloc, 0);
2605 1 EXPECT_NULL(a.ptrs);
2606 1 ptr_array_free(&a);
2607 1 a = ptr_array_new(1);
2608 1 EXPECT_EQ(a.alloc, 8);
2609 1 EXPECT_NONNULL(a.ptrs);
2610 1 ptr_array_free(&a);
2611
2612 // ptr_array_trim_nulls() should remove everything (i.e. not leave 1
2613 // trailing NULL) when all elements are NULL
2614 1 a = ptr_array_new(0);
2615 1 ptr_array_append(&a, NULL);
2616 1 ptr_array_append(&a, NULL);
2617 1 ptr_array_append(&a, NULL);
2618 1 EXPECT_EQ(a.count, 3);
2619 1 ptr_array_trim_nulls(&a);
2620 1 EXPECT_EQ(a.count, 0);
2621 1 ptr_array_free(&a);
2622 1 }
2623
2624 1 static void test_ptr_array_move(TestContext *ctx)
2625 {
2626 1 PointerArray a = ptr_array_new(0);
2627 1 ptr_array_append(&a, xstrdup("A"));
2628 1 ptr_array_append(&a, xstrdup("B"));
2629 1 ptr_array_append(&a, xstrdup("C"));
2630 1 ptr_array_append(&a, xstrdup("D"));
2631 1 ptr_array_append(&a, xstrdup("E"));
2632 1 ptr_array_append(&a, xstrdup("F"));
2633 1 EXPECT_EQ(a.count, 6);
2634
2635 1 ptr_array_move(&a, 0, 1);
2636 1 EXPECT_STREQ(a.ptrs[0], "B");
2637 1 EXPECT_STREQ(a.ptrs[1], "A");
2638
2639 1 ptr_array_move(&a, 1, 0);
2640 1 EXPECT_STREQ(a.ptrs[0], "A");
2641 1 EXPECT_STREQ(a.ptrs[1], "B");
2642
2643 1 ptr_array_move(&a, 1, 5);
2644 1 EXPECT_STREQ(a.ptrs[0], "A");
2645 1 EXPECT_STREQ(a.ptrs[1], "C");
2646 1 EXPECT_STREQ(a.ptrs[2], "D");
2647 1 EXPECT_STREQ(a.ptrs[3], "E");
2648 1 EXPECT_STREQ(a.ptrs[4], "F");
2649 1 EXPECT_STREQ(a.ptrs[5], "B");
2650
2651 1 ptr_array_move(&a, 5, 1);
2652 1 EXPECT_STREQ(a.ptrs[0], "A");
2653 1 EXPECT_STREQ(a.ptrs[1], "B");
2654 1 EXPECT_STREQ(a.ptrs[2], "C");
2655 1 EXPECT_STREQ(a.ptrs[3], "D");
2656 1 EXPECT_STREQ(a.ptrs[4], "E");
2657 1 EXPECT_STREQ(a.ptrs[5], "F");
2658
2659 1 ptr_array_move(&a, 0, 5);
2660 1 EXPECT_STREQ(a.ptrs[0], "B");
2661 1 EXPECT_STREQ(a.ptrs[1], "C");
2662 1 EXPECT_STREQ(a.ptrs[2], "D");
2663 1 EXPECT_STREQ(a.ptrs[3], "E");
2664 1 EXPECT_STREQ(a.ptrs[4], "F");
2665 1 EXPECT_STREQ(a.ptrs[5], "A");
2666
2667 1 ptr_array_move(&a, 5, 0);
2668 1 EXPECT_STREQ(a.ptrs[0], "A");
2669 1 EXPECT_STREQ(a.ptrs[1], "B");
2670 1 EXPECT_STREQ(a.ptrs[2], "C");
2671 1 EXPECT_STREQ(a.ptrs[3], "D");
2672 1 EXPECT_STREQ(a.ptrs[4], "E");
2673 1 EXPECT_STREQ(a.ptrs[5], "F");
2674
2675 1 ptr_array_move(&a, 5, 0);
2676 1 EXPECT_STREQ(a.ptrs[0], "F");
2677 1 EXPECT_STREQ(a.ptrs[1], "A");
2678 1 EXPECT_STREQ(a.ptrs[2], "B");
2679 1 EXPECT_STREQ(a.ptrs[3], "C");
2680 1 EXPECT_STREQ(a.ptrs[4], "D");
2681 1 EXPECT_STREQ(a.ptrs[5], "E");
2682
2683 1 ptr_array_move(&a, 4, 5);
2684 1 EXPECT_STREQ(a.ptrs[4], "E");
2685 1 EXPECT_STREQ(a.ptrs[5], "D");
2686
2687 1 ptr_array_move(&a, 1, 3);
2688 1 EXPECT_STREQ(a.ptrs[1], "B");
2689 1 EXPECT_STREQ(a.ptrs[2], "C");
2690 1 EXPECT_STREQ(a.ptrs[3], "A");
2691
2692 1 ptr_array_move(&a, 3, 3);
2693 1 EXPECT_STREQ(a.ptrs[3], "A");
2694 1 ptr_array_move(&a, 1, 1);
2695 1 EXPECT_STREQ(a.ptrs[1], "B");
2696 1 ptr_array_move(&a, 0, 0);
2697 1 EXPECT_STREQ(a.ptrs[0], "F");
2698
2699 1 ptr_array_free(&a);
2700 1 }
2701
2702 1 static void test_ptr_array_insert(TestContext *ctx)
2703 {
2704 1 PointerArray a = ptr_array_new(0);
2705 1 ptr_array_insert(&a, xstrdup("D"), 0);
2706 1 ptr_array_insert(&a, xstrdup("C"), 0);
2707 1 ptr_array_insert(&a, xstrdup("B"), 0);
2708 1 ptr_array_insert(&a, xstrdup("A"), 0);
2709 1 EXPECT_EQ(a.count, 4);
2710
2711 1 ptr_array_insert(&a, xstrdup("X"), 1);
2712 1 ptr_array_insert(&a, xstrdup("Y"), 3);
2713 1 EXPECT_EQ(a.count, 6);
2714
2715 1 ptr_array_insert(&a, xstrdup("Z"), a.count);
2716 1 EXPECT_EQ(a.count, 7);
2717
2718 1 EXPECT_STREQ(a.ptrs[0], "A");
2719 1 EXPECT_STREQ(a.ptrs[1], "X");
2720 1 EXPECT_STREQ(a.ptrs[2], "B");
2721 1 EXPECT_STREQ(a.ptrs[3], "Y");
2722 1 EXPECT_STREQ(a.ptrs[4], "C");
2723 1 EXPECT_STREQ(a.ptrs[5], "D");
2724 1 EXPECT_STREQ(a.ptrs[6], "Z");
2725
2726 1 ptr_array_free(&a);
2727 1 }
2728
2729 1 static void test_list(TestContext *ctx)
2730 {
2731 1 ListHead a, b, c;
2732 1 list_init(&b);
2733 1 EXPECT_TRUE(list_empty(&b));
2734
2735 1 list_insert_before(&a, &b);
2736 1 EXPECT_FALSE(list_empty(&a));
2737 1 EXPECT_FALSE(list_empty(&b));
2738 1 EXPECT_PTREQ(a.next, &b);
2739 1 EXPECT_PTREQ(a.prev, &b);
2740 1 EXPECT_PTREQ(b.next, &a);
2741 1 EXPECT_PTREQ(b.prev, &a);
2742
2743 1 list_insert_after(&c, &b);
2744 1 EXPECT_FALSE(list_empty(&a));
2745 1 EXPECT_FALSE(list_empty(&b));
2746 1 EXPECT_FALSE(list_empty(&c));
2747 1 EXPECT_PTREQ(a.next, &b);
2748 1 EXPECT_PTREQ(a.prev, &c);
2749 1 EXPECT_PTREQ(b.next, &c);
2750 1 EXPECT_PTREQ(b.prev, &a);
2751 1 EXPECT_PTREQ(c.next, &a);
2752 1 EXPECT_PTREQ(c.prev, &b);
2753
2754 1 list_remove(&b);
2755 1 EXPECT_FALSE(list_empty(&a));
2756 1 EXPECT_FALSE(list_empty(&c));
2757 1 EXPECT_PTREQ(a.next, &c);
2758 1 EXPECT_PTREQ(a.prev, &c);
2759 1 EXPECT_PTREQ(c.next, &a);
2760 1 EXPECT_PTREQ(c.prev, &a);
2761 1 EXPECT_NULL(b.next);
2762 1 EXPECT_NULL(b.prev);
2763 1 }
2764
2765 1 static void test_hashmap(TestContext *ctx)
2766 {
2767 1 static const char strings[][8] = {
2768 "foo", "bar", "quux", "etc", "",
2769 "A", "B", "C", "D", "E", "F", "G",
2770 "a", "b", "c", "d", "e", "f", "g",
2771 "test", "1234567", "..", "...",
2772 "\x01\x02\x03 \t\xfe\xff",
2773 };
2774
2775 1 HashMap map = hashmap_new(ARRAYLEN(strings), HMAP_NO_FLAGS);
2776 1 ASSERT_NONNULL(map.entries);
2777 1 EXPECT_EQ(map.mask, 31);
2778 1 EXPECT_EQ(map.count, 0);
2779 1 EXPECT_NULL(hashmap_find(&map, "foo"));
2780
2781 1 static const char value[] = "VALUE";
2782
2/2
✓ Branch 18 → 9 taken 24 times.
✓ Branch 18 → 19 taken 1 time.
26 FOR_EACH_I(i, strings) {
2783 24 const char *key = strings[i];
2784 24 ASSERT_EQ(key[sizeof(strings[0]) - 1], '\0');
2785 24 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2786 24 HashMapEntry *e = hashmap_find(&map, key);
2787 24 ASSERT_NONNULL(e);
2788 24 EXPECT_STREQ(e->key, key);
2789 24 EXPECT_PTREQ(e->value, value);
2790 }
2791
2792 1 EXPECT_EQ(map.count, 24);
2793 1 EXPECT_EQ(map.mask, 31);
2794
2795 1 HashMapIter it = hashmap_iter(&map);
2796 1 EXPECT_PTREQ(it.map, &map);
2797 1 EXPECT_NULL(it.entry);
2798 1 EXPECT_EQ(it.idx, 0);
2799
2800
2/2
✓ Branch 29 → 25 taken 24 times.
✓ Branch 29 → 41 taken 1 time.
25 while (hashmap_next(&it)) {
2801 24 ASSERT_NONNULL(it.entry);
2802 24 ASSERT_NONNULL(it.entry->key);
2803 24 EXPECT_PTREQ(it.entry->value, value);
2804 }
2805
2806
2/2
✓ Branch 41 → 30 taken 24 times.
✓ Branch 41 → 42 taken 1 time.
25 FOR_EACH_I(i, strings) {
2807 24 const char *key = strings[i];
2808 24 HashMapEntry *e = hashmap_find(&map, key);
2809 24 ASSERT_NONNULL(e);
2810 24 EXPECT_STREQ(e->key, key);
2811 24 EXPECT_PTREQ(e->value, value);
2812 24 EXPECT_PTREQ(hashmap_remove(&map, key), value);
2813 24 EXPECT_STREQ(e->key, NULL);
2814 24 EXPECT_UINT_EQ(e->hash, 0xdead);
2815 24 EXPECT_NULL(hashmap_find(&map, key));
2816 }
2817
2818 1 EXPECT_EQ(map.count, 0);
2819 1 it = hashmap_iter(&map);
2820 1 EXPECT_FALSE(hashmap_next(&it));
2821
2822 1 EXPECT_PTREQ(hashmap_insert(&map, xstrdup("new"), (void*)value), value);
2823 1 ASSERT_NONNULL(hashmap_find(&map, "new"));
2824 1 EXPECT_STREQ(hashmap_find(&map, "new")->key, "new");
2825 1 EXPECT_EQ(map.count, 1);
2826
2827
2/2
✓ Branch 62 → 54 taken 24 times.
✓ Branch 62 → 63 taken 1 time.
26 FOR_EACH_I(i, strings) {
2828 24 const char *key = strings[i];
2829 24 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2830 24 HashMapEntry *e = hashmap_find(&map, key);
2831 24 ASSERT_NONNULL(e);
2832 24 EXPECT_STREQ(e->key, key);
2833 24 EXPECT_PTREQ(e->value, value);
2834 }
2835
2836 1 EXPECT_EQ(map.count, 25);
2837
2838
2/2
✓ Branch 75 → 65 taken 24 times.
✓ Branch 75 → 76 taken 1 time.
26 FOR_EACH_I(i, strings) {
2839 24 const char *key = strings[i];
2840 24 HashMapEntry *e = hashmap_find(&map, key);
2841 24 ASSERT_NONNULL(e);
2842 24 EXPECT_STREQ(e->key, key);
2843 24 EXPECT_PTREQ(hashmap_remove(&map, key), value);
2844 24 EXPECT_STREQ(e->key, NULL);
2845 24 EXPECT_UINT_EQ(e->hash, 0xdead);
2846 24 EXPECT_NULL(hashmap_find(&map, key));
2847 }
2848
2849 1 EXPECT_EQ(map.count, 1);
2850 1 EXPECT_NULL(hashmap_remove(&map, "non-existent-key"));
2851 1 EXPECT_EQ(map.count, 1);
2852 1 EXPECT_PTREQ(hashmap_remove(&map, "new"), value);
2853 1 EXPECT_EQ(map.count, 0);
2854
2855 1 it = hashmap_iter(&map);
2856 1 EXPECT_FALSE(hashmap_next(&it));
2857
2858 1 hashmap_free(&map, NULL);
2859 1 EXPECT_NULL(map.entries);
2860 1 EXPECT_EQ(map.count, 0);
2861 1 EXPECT_EQ(map.mask, 0);
2862
2863 1 map = hashmap_new(0, HMAP_NO_FLAGS);
2864 1 ASSERT_NONNULL(map.entries);
2865 1 EXPECT_EQ(map.mask, 7);
2866 1 EXPECT_EQ(map.count, 0);
2867 1 hashmap_free(&map, NULL);
2868 1 EXPECT_NULL(map.entries);
2869
2870 1 map = hashmap_new(13, HMAP_NO_FLAGS);
2871 1 ASSERT_NONNULL(map.entries);
2872 1 EXPECT_EQ(map.mask, 31);
2873 1 EXPECT_EQ(map.count, 0);
2874
2875
2/2
✓ Branch 110 → 100 taken 380 times.
✓ Branch 110 → 111 taken 1 time.
382 for (unsigned int i = 1; i <= 380; i++) {
2876 380 char key[4];
2877 380 ASSERT_TRUE(buf_uint_to_str(i, key) < sizeof(key));
2878 380 EXPECT_PTREQ(hashmap_insert(&map, xstrdup(key), (void*)value), value);
2879 380 HashMapEntry *e = hashmap_find(&map, key);
2880 380 ASSERT_NONNULL(e);
2881 380 EXPECT_STREQ(e->key, key);
2882 380 EXPECT_PTREQ(e->value, value);
2883 }
2884
2885 1 EXPECT_EQ(map.count, 380);
2886 1 EXPECT_EQ(map.mask, 511);
2887 1 hashmap_free(&map, NULL);
2888
2889 1 static const char val[] = "VAL";
2890 1 char *key = xstrdup("KEY");
2891 1 EXPECT_NULL(hashmap_insert_or_replace(&map, key, (char*)val));
2892 1 EXPECT_EQ(map.count, 1);
2893 1 EXPECT_STREQ(hashmap_get(&map, "KEY"), val);
2894
2895 1 static const char new_val[] = "NEW";
2896 1 char *duplicate_key = xstrdup(key);
2897 1 EXPECT_PTREQ(val, hashmap_insert_or_replace(&map, duplicate_key, (char*)new_val));
2898 1 EXPECT_EQ(map.count, 1);
2899 1 EXPECT_STREQ(hashmap_get(&map, "KEY"), new_val);
2900 1 hashmap_free(&map, NULL);
2901 1 }
2902
2903 1 static void test_hashset(TestContext *ctx)
2904 {
2905 1 static const char *const strings[] = {
2906 "foo", "Foo", "bar", "quux", "etc",
2907 "\t\xff\x80\b", "\t\t\t", "\x01\x02\x03\xfe\xff",
2908 #if HAS_STD_C11
2909 (const char*)u8"ภาษาไทย",
2910 (const char*)u8"中文",
2911 (const char*)u8"日本語",
2912 #endif
2913 };
2914
2915 1 HashSet set = hashset_new(ARRAYLEN(strings), false);
2916 1 EXPECT_EQ(set.nr_entries, 0);
2917 1 EXPECT_EQ(set.table_size, 16);
2918 1 EXPECT_EQ(set.grow_at, 12);
2919 1 EXPECT_NONNULL(set.table);
2920 1 EXPECT_FALSE(set.icase);
2921 1 EXPECT_NULL(hashset_get(&set, strview("foo")));
2922
2923 1 HashSetIter iter = hashset_iter(&set);
2924 1 EXPECT_PTREQ(iter.set, &set);
2925 1 EXPECT_NULL(iter.entry);
2926 1 EXPECT_EQ(iter.idx, 0);
2927 1 EXPECT_FALSE(hashset_next(&iter));
2928 1 EXPECT_PTREQ(iter.set, &set);
2929 1 EXPECT_NULL(iter.entry);
2930 1 EXPECT_EQ(iter.idx, 0);
2931
2932
2/2
✓ Branch 21 → 19 taken 11 times.
✓ Branch 21 → 25 taken 1 time.
13 FOR_EACH_I(i, strings) {
2933 11 hashset_insert(&set, strview(strings[i]));
2934 }
2935
2936
2/2
✓ Branch 25 → 22 taken 11 times.
✓ Branch 25 → 26 taken 1 time.
12 FOR_EACH_I(i, strings) {
2937 11 EXPECT_TRUE(hashset_next(&iter));
2938 }
2939 1 EXPECT_FALSE(hashset_next(&iter));
2940 1 EXPECT_FALSE(hashset_next(&iter));
2941
2942 1 EXPECT_EQ(set.nr_entries, ARRAYLEN(strings));
2943 1 EXPECT_NONNULL(hashset_get(&set, strview("\t\xff\x80\b")));
2944 1 EXPECT_NONNULL(hashset_get(&set, strview("foo")));
2945 1 EXPECT_NONNULL(hashset_get(&set, strview("Foo")));
2946
2947 1 EXPECT_NULL(hashset_get(&set, strview("FOO")));
2948 1 EXPECT_NULL(hashset_get(&set, strview("")));
2949 1 EXPECT_NULL(hashset_get(&set, strview(NULL)));
2950 1 EXPECT_NULL(hashset_get(&set, strview("\0")));
2951
2952 1 StringView last_string = strview(strings[ARRAYLEN(strings) - 1]);
2953 1 EXPECT_NONNULL(hashset_get(&set, last_string));
2954
2955
2/2
✓ Branch 56 → 48 taken 11 times.
✓ Branch 56 → 57 taken 1 time.
13 FOR_EACH_I(i, strings) {
2956 11 StringView sv = strview(strings[i]);
2957 11 EXPECT_NONNULL(hashset_get(&set, sv));
2958 11 EXPECT_NULL(hashset_get(&set, string_view(sv.data, sv.length - 1)));
2959 11 EXPECT_NULL(hashset_get(&set, strview_suffix(sv, 1)));
2960 }
2961
2962 1 hashset_free(&set);
2963 1 set = hashset_new(0, true);
2964 1 EXPECT_EQ(set.nr_entries, 0);
2965 1 EXPECT_TRUE(set.icase);
2966 1 hashset_insert(&set, strview("foo"));
2967 1 hashset_insert(&set, strview("Foo"));
2968 1 EXPECT_EQ(set.nr_entries, 1);
2969 1 EXPECT_NONNULL(hashset_get(&set, strview("foo")));
2970 1 EXPECT_NONNULL(hashset_get(&set, strview("FOO")));
2971 1 EXPECT_NONNULL(hashset_get(&set, strview("fOO")));
2972 1 hashset_free(&set);
2973
2974 // Check that hashset_insert() returns existing entries instead of
2975 // inserting duplicates
2976 1 set = hashset_new(0, false);
2977 1 EXPECT_EQ(set.nr_entries, 0);
2978 1 HashSetEntry *e1 = hashset_insert(&set, strview("foo"));
2979 1 EXPECT_EQ(e1->str_len, 3);
2980 1 EXPECT_STREQ(e1->str, "foo");
2981 1 EXPECT_EQ(set.nr_entries, 1);
2982 1 HashSetEntry *e2 = hashset_insert(&set, strview("foo"));
2983 1 EXPECT_PTREQ(e1, e2);
2984 1 EXPECT_EQ(set.nr_entries, 1);
2985 1 hashset_free(&set);
2986
2987 1 set = hashset_new(0, false);
2988 // Initial table size should be 16 (minimum + load factor + rounding)
2989 1 EXPECT_EQ(set.table_size, 16);
2990
2/2
✓ Branch 88 → 84 taken 80 times.
✓ Branch 88 → 89 taken 1 time.
82 for (unsigned int i = 1; i <= 80; i++) {
2991 80 char buf[4];
2992 80 size_t len = buf_uint_to_str(i, buf);
2993 80 ASSERT_TRUE(len < sizeof(buf));
2994 80 hashset_insert(&set, string_view(buf, len));
2995 }
2996 1 EXPECT_EQ(set.nr_entries, 80);
2997 1 EXPECT_NONNULL(hashset_get(&set, strview("1")));
2998 1 EXPECT_NONNULL(hashset_get(&set, strview("80")));
2999 1 EXPECT_NULL(hashset_get(&set, strview("0")));
3000 1 EXPECT_NULL(hashset_get(&set, strview("81")));
3001 // Table size should be the first power of 2 larger than the number
3002 // of entries (including load factor adjustment)
3003 1 EXPECT_EQ(set.table_size, 128);
3004 1 hashset_free(&set);
3005 1 }
3006
3007 1 static void test_intmap(TestContext *ctx)
3008 {
3009 1 IntMap map = {.entries = NULL};
3010 1 EXPECT_NULL(intmap_find(&map, 0));
3011 1 EXPECT_NULL(intmap_get(&map, 0));
3012 1 intmap_free(&map, free);
3013
3014 1 static const char value[] = "value";
3015 1 EXPECT_NULL(intmap_insert_or_replace(&map, 0, xstrdup(value)));
3016 1 EXPECT_NULL(intmap_insert_or_replace(&map, 1, xstrdup(value)));
3017 1 EXPECT_NULL(intmap_insert_or_replace(&map, 2, xstrdup(value)));
3018 1 EXPECT_NULL(intmap_insert_or_replace(&map, 4, xstrdup(value)));
3019 1 EXPECT_EQ(map.count, 4);
3020 1 EXPECT_EQ(map.mask, 7);
3021
3022 1 char *replaced = intmap_insert_or_replace(&map, 0, xstrdup(value));
3023 1 EXPECT_STREQ(replaced, value);
3024 1 free(replaced);
3025 1 EXPECT_EQ(map.tombstones, 0);
3026 1 EXPECT_STREQ(intmap_get(&map, 0), value);
3027
3028 1 char *removed = intmap_remove(&map, 0);
3029 1 EXPECT_STREQ(removed, value);
3030 1 free(removed);
3031 1 EXPECT_EQ(map.tombstones, 1);
3032 1 EXPECT_NULL(intmap_get(&map, 0));
3033
3034 1 EXPECT_NULL(intmap_insert_or_replace(&map, 100, xstrdup(value)));
3035 1 EXPECT_NULL(intmap_insert_or_replace(&map, 488, xstrdup(value)));
3036 1 EXPECT_NULL(intmap_insert_or_replace(&map, 899, xstrdup(value)));
3037 1 EXPECT_NULL(intmap_insert_or_replace(&map, 256, xstrdup(value)));
3038 1 EXPECT_EQ(map.count, 7);
3039 1 EXPECT_EQ(map.mask, 15);
3040
3041 1 intmap_free(&map, free);
3042 1 }
3043
3044 1 static void test_next_multiple(TestContext *ctx)
3045 {
3046 1 EXPECT_EQ(next_multiple(0, 1), 0);
3047 1 EXPECT_EQ(next_multiple(1, 1), 1);
3048 1 EXPECT_EQ(next_multiple(2, 1), 2);
3049 1 EXPECT_EQ(next_multiple(3, 1), 3);
3050 1 EXPECT_EQ(next_multiple(0, 2), 0);
3051 1 EXPECT_EQ(next_multiple(1, 2), 2);
3052 1 EXPECT_EQ(next_multiple(5, 2), 6);
3053 1 EXPECT_EQ(next_multiple(1, 8), 8);
3054 1 EXPECT_EQ(next_multiple(3, 8), 8);
3055 1 EXPECT_EQ(next_multiple(8, 8), 8);
3056 1 EXPECT_EQ(next_multiple(9, 8), 16);
3057 1 EXPECT_EQ(next_multiple(0, 8), 0);
3058 1 EXPECT_EQ(next_multiple(0, 16), 0);
3059 1 EXPECT_EQ(next_multiple(1, 16), 16);
3060 1 EXPECT_EQ(next_multiple(123, 16), 128);
3061 1 EXPECT_EQ(next_multiple(4, 64), 64);
3062 1 EXPECT_EQ(next_multiple(80, 64), 128);
3063 1 EXPECT_EQ(next_multiple(256, 256), 256);
3064 1 EXPECT_EQ(next_multiple(257, 256), 512);
3065 1 EXPECT_EQ(next_multiple(8000, 256), 8192);
3066
3067
2/2
✓ Branch 27 → 25 taken 70 times.
✓ Branch 27 → 28 taken 1 time.
72 for (size_t i = 0; i < 70; i++) {
3068
2/2
✓ Branch 25 → 23 taken 490 times.
✓ Branch 25 → 26 taken 70 times.
560 for (size_t p2 = 64; p2; p2 >>= 1) {
3069 490 size_t remainder_complement = (-i & (p2 - 1));
3070 490 IEXPECT_EQ(next_multiple(i, p2), i + remainder_complement);
3071 }
3072 }
3073
3074 1 const size_t size_max = (size_t)-1;
3075 1 const size_t pow2_max = size_max & ~(size_max >> 1);
3076 1 EXPECT_TRUE(IS_POWER_OF_2(pow2_max));
3077 1 EXPECT_UINT_EQ(next_multiple(size_max, 1), size_max);
3078 1 EXPECT_UINT_EQ(next_multiple(pow2_max, 1), pow2_max);
3079 1 EXPECT_UINT_EQ(next_multiple(pow2_max, pow2_max), pow2_max);
3080
3081 // Note: returns 0 on overflow
3082 1 EXPECT_UINT_EQ(next_multiple(pow2_max + 1, pow2_max), 0);
3083 1 EXPECT_UINT_EQ(next_multiple(size_max + 0, pow2_max), 0);
3084 1 EXPECT_UINT_EQ(next_multiple(size_max - 1, pow2_max), 0);
3085
3086 1 const size_t a = pow2_max >> 1;
3087 1 EXPECT_UINT_EQ(next_multiple(a, a), a);
3088 1 EXPECT_UINT_EQ(next_multiple(a + 1, a), pow2_max);
3089 1 }
3090
3091 1 static void test_next_pow2(TestContext *ctx)
3092 {
3093 1 EXPECT_UINT_EQ(next_pow2(0), 1);
3094 1 EXPECT_UINT_EQ(next_pow2(1), 1);
3095 1 EXPECT_UINT_EQ(next_pow2(2), 2);
3096 1 EXPECT_UINT_EQ(next_pow2(3), 4);
3097 1 EXPECT_UINT_EQ(next_pow2(4), 4);
3098 1 EXPECT_UINT_EQ(next_pow2(5), 8);
3099 1 EXPECT_UINT_EQ(next_pow2(8), 8);
3100 1 EXPECT_UINT_EQ(next_pow2(9), 16);
3101 1 EXPECT_UINT_EQ(next_pow2(17), 32);
3102 1 EXPECT_UINT_EQ(next_pow2(61), 64);
3103 1 EXPECT_UINT_EQ(next_pow2(64), 64);
3104 1 EXPECT_UINT_EQ(next_pow2(65), 128);
3105 1 EXPECT_UINT_EQ(next_pow2(200), 256);
3106 1 EXPECT_UINT_EQ(next_pow2(1000), 1024);
3107 1 EXPECT_UINT_EQ(next_pow2(5500), 8192);
3108
3109 1 const size_t size_max = (size_t)-1;
3110 1 const size_t pow2_max = ~(size_max >> 1);
3111 1 EXPECT_TRUE(IS_POWER_OF_2(pow2_max));
3112 1 EXPECT_UINT_EQ(next_pow2(size_max >> 1), pow2_max);
3113 1 EXPECT_UINT_EQ(next_pow2(pow2_max), pow2_max);
3114 1 EXPECT_UINT_EQ(next_pow2(pow2_max - 1), pow2_max);
3115
3116 // Note: returns 0 on overflow
3117 1 EXPECT_UINT_EQ(next_pow2(pow2_max + 1), 0);
3118 1 EXPECT_UINT_EQ(next_pow2(size_max), 0);
3119 1 EXPECT_UINT_EQ(next_pow2(size_max - 1), 0);
3120 1 }
3121
3122 1 static void test_popcount(TestContext *ctx)
3123 {
3124 1 EXPECT_EQ(u32_popcount(0), 0);
3125 1 EXPECT_EQ(u32_popcount(1), 1);
3126 1 EXPECT_EQ(u32_popcount(11), 3);
3127 1 EXPECT_EQ(u32_popcount(128), 1);
3128 1 EXPECT_EQ(u32_popcount(255), 8);
3129 1 EXPECT_EQ(u32_popcount(UINT32_MAX), 32);
3130 1 EXPECT_EQ(u32_popcount(UINT32_MAX - 1), 31);
3131 1 EXPECT_EQ(u32_popcount(0xE10F02C9u), 13);
3132
3133 1 EXPECT_EQ(u64_popcount(0), 0);
3134 1 EXPECT_EQ(u64_popcount(1), 1);
3135 1 EXPECT_EQ(u64_popcount(255), 8);
3136 1 EXPECT_EQ(u64_popcount(UINT64_MAX), 64);
3137 1 EXPECT_EQ(u64_popcount(UINT64_MAX - 1), 63);
3138 1 EXPECT_EQ(u64_popcount(0xFFFFFFFFFFull), 40);
3139 1 EXPECT_EQ(u64_popcount(0x10000000000ull), 1);
3140 1 EXPECT_EQ(u64_popcount(0x9010F0EEC2003B70ull), 24);
3141
3142
2/2
✓ Branch 23 → 19 taken 32 times.
✓ Branch 23 → 28 taken 1 time.
34 for (unsigned int i = 0; i < 32; i++) {
3143 32 IEXPECT_EQ(u32_popcount(UINT32_MAX << i), 32 - i);
3144 32 IEXPECT_EQ(u32_popcount(UINT32_MAX >> i), 32 - i);
3145 32 IEXPECT_EQ(u32_popcount(1u << i), 1);
3146 }
3147
3148
2/2
✓ Branch 28 → 24 taken 64 times.
✓ Branch 28 → 29 taken 1 time.
65 for (unsigned int i = 0; i < 64; i++) {
3149 64 IEXPECT_EQ(u64_popcount(UINT64_MAX << i), 64 - i);
3150 64 IEXPECT_EQ(u64_popcount(UINT64_MAX >> i), 64 - i);
3151 64 IEXPECT_EQ(u64_popcount(1ull << i), 1);
3152 }
3153 1 }
3154
3155 1 static void test_ctz(TestContext *ctx)
3156 {
3157 1 EXPECT_EQ(u32_ctz(1), 0);
3158 1 EXPECT_EQ(u32_ctz(11), 0);
3159 1 EXPECT_EQ(u32_ctz(127), 0);
3160 1 EXPECT_EQ(u32_ctz(128), 7);
3161 1 EXPECT_EQ(u32_ctz(129), 0);
3162 1 EXPECT_EQ(u32_ctz(130), 1);
3163 1 EXPECT_EQ(u32_ctz(255), 0);
3164 1 EXPECT_EQ(u32_ctz(UINT32_MAX), 0);
3165 1 EXPECT_EQ(u32_ctz(UINT32_MAX - 1), 1);
3166 1 EXPECT_EQ(u32_ctz(0xE10F02C9u), 0);
3167 1 EXPECT_EQ(u32_ctz(0xE10F02CCu), 2);
3168
3169 1 EXPECT_EQ(umax_ctz(1), 0);
3170 1 EXPECT_EQ(umax_ctz(11), 0);
3171 1 EXPECT_EQ(umax_ctz(127), 0);
3172 1 EXPECT_EQ(umax_ctz(128), 7);
3173 1 EXPECT_EQ(umax_ctz(129), 0);
3174 1 EXPECT_EQ(umax_ctz(130), 1);
3175 1 EXPECT_EQ(umax_ctz(255), 0);
3176 1 EXPECT_EQ(umax_ctz(0xE10F02C9u), 0);
3177 1 EXPECT_EQ(umax_ctz(0xE10F02CCu), 2);
3178 1 EXPECT_EQ(umax_ctz(0x8000000000000000ull), 63);
3179 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX), 0);
3180 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX - 1), 1);
3181 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX - 7), 3);
3182 1 }
3183
3184 1 static void test_ffs(TestContext *ctx)
3185 {
3186 1 EXPECT_EQ(u32_ffs(0), 0);
3187 1 EXPECT_EQ(u32_ffs(1), 1);
3188 1 EXPECT_EQ(u32_ffs(6), 2);
3189 1 EXPECT_EQ(u32_ffs(8), 4);
3190 1 EXPECT_EQ(u32_ffs(255), 1);
3191 1 EXPECT_EQ(u32_ffs(256), 9);
3192 1 EXPECT_EQ(u32_ffs(UINT32_MAX), 1);
3193 1 EXPECT_EQ(u32_ffs(UINT32_MAX - 1), 2);
3194 1 EXPECT_EQ(u32_ffs(UINT32_MAX << 8), 9);
3195 1 EXPECT_EQ(u32_ffs(1u << 31), 32);
3196 1 EXPECT_EQ(u32_ffs(1u << 30), 31);
3197 1 EXPECT_EQ(u32_ffs(1u << 18), 19);
3198 1 }
3199
3200 1 static void test_lsbit(TestContext *ctx)
3201 {
3202 1 EXPECT_EQ(u32_lsbit(0), 0);
3203 1 EXPECT_EQ(u32_lsbit(1), 1);
3204 1 EXPECT_EQ(u32_lsbit(2), 2);
3205 1 EXPECT_EQ(u32_lsbit(3), 1);
3206 1 EXPECT_EQ(u32_lsbit(4), 4);
3207 1 EXPECT_EQ(u32_lsbit(255), 1);
3208 1 EXPECT_EQ(u32_lsbit(256), 256);
3209 1 EXPECT_EQ(u32_lsbit(257), 1);
3210 1 EXPECT_EQ(u32_lsbit(258), 2);
3211 1 EXPECT_EQ(u32_lsbit(1u << 31), 1u << 31);
3212 1 EXPECT_EQ(u32_lsbit(1u << 30), 1u << 30);
3213 1 EXPECT_EQ(u32_lsbit(7u << 30), 1u << 30);
3214 1 EXPECT_EQ(u32_lsbit(UINT32_MAX), 1);
3215 1 EXPECT_EQ(u32_lsbit(UINT32_MAX << 25), 1u << 25);
3216
3217
2/2
✓ Branch 23 → 17 taken 69 times.
✓ Branch 23 → 24 taken 1 time.
71 for (uint32_t i = 1; i < 70; i++) {
3218 69 uint32_t lsb = u32_lsbit(i);
3219 69 IEXPECT_TRUE(IS_POWER_OF_2(lsb));
3220 69 IEXPECT_TRUE(lsb & i);
3221 }
3222 1 }
3223
3224 1 static void test_msbit(TestContext *ctx)
3225 {
3226 1 EXPECT_EQ(size_msbit(0), 0);
3227 1 EXPECT_EQ(size_msbit(1), 1);
3228 1 EXPECT_EQ(size_msbit(2), 2);
3229 1 EXPECT_EQ(size_msbit(3), 2);
3230 1 EXPECT_EQ(size_msbit(4), 4);
3231 1 EXPECT_EQ(size_msbit(7), 4);
3232 1 EXPECT_EQ(size_msbit(8), 8);
3233 1 EXPECT_EQ(size_msbit(255), 128);
3234 1 EXPECT_EQ(size_msbit(256), 256);
3235 1 EXPECT_UINT_EQ(size_msbit(0x1FFFu), 0x1000u);
3236 1 EXPECT_UINT_EQ(size_msbit(0xFFFFu), 0x8000u);
3237
3238 1 const size_t max = SIZE_MAX;
3239 1 const size_t max_pow2 = ~(max >> 1);
3240 1 EXPECT_UINT_EQ(size_msbit(max), max_pow2);
3241 1 EXPECT_UINT_EQ(size_msbit(max - 1), max_pow2);
3242 1 EXPECT_UINT_EQ(size_msbit(max_pow2), max_pow2);
3243 1 EXPECT_UINT_EQ(size_msbit(max_pow2 - 1), max_pow2 >> 1);
3244 1 EXPECT_UINT_EQ(size_msbit(max_pow2 + 1), max_pow2);
3245
3246
2/2
✓ Branch 25 → 19 taken 69 times.
✓ Branch 25 → 26 taken 1 time.
71 for (size_t i = 1; i < 70; i++) {
3247 69 size_t msb = size_msbit(i);
3248 69 IEXPECT_TRUE(IS_POWER_OF_2(msb));
3249 69 IEXPECT_TRUE(msb & i);
3250 }
3251 1 }
3252
3253 1 static void test_clz(TestContext *ctx)
3254 {
3255 1 EXPECT_EQ(u64_clz(1), 63);
3256 1 EXPECT_EQ(u64_clz(2), 62);
3257 1 EXPECT_EQ(u64_clz(3), 62);
3258 1 EXPECT_EQ(u64_clz(1ULL << 10), 53);
3259 1 EXPECT_EQ(u64_clz(1ULL << 55), 8);
3260 1 EXPECT_EQ(u64_clz(1ULL << 63), 0);
3261 1 EXPECT_EQ(u64_clz(UINT64_MAX), 0);
3262 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 1), 1);
3263 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 3), 3);
3264 1 }
3265
3266 1 static void test_umax_bitwidth(TestContext *ctx)
3267 {
3268 1 EXPECT_EQ(umax_bitwidth(0), 0);
3269 1 EXPECT_EQ(umax_bitwidth(1), 1);
3270 1 EXPECT_EQ(umax_bitwidth(2), 2);
3271 1 EXPECT_EQ(umax_bitwidth(3), 2);
3272 1 EXPECT_EQ(umax_bitwidth(0x80), 8);
3273 1 EXPECT_EQ(umax_bitwidth(0xFF), 8);
3274 1 EXPECT_EQ(umax_bitwidth(0x10081), 17);
3275 1 EXPECT_EQ(umax_bitwidth(1ULL << 62), 63);
3276 1 EXPECT_EQ(umax_bitwidth(0xFFFFFFFFFFFFFFFFULL), 64);
3277 1 }
3278
3279 1 static void test_umax_count_base16_digits(TestContext *ctx)
3280 {
3281 1 EXPECT_EQ(umax_count_base16_digits(0x0), 1);
3282 1 EXPECT_EQ(umax_count_base16_digits(0x1), 1);
3283 1 EXPECT_EQ(umax_count_base16_digits(0x2), 1);
3284 1 EXPECT_EQ(umax_count_base16_digits(0x3), 1);
3285 1 EXPECT_EQ(umax_count_base16_digits(0x4), 1);
3286 1 EXPECT_EQ(umax_count_base16_digits(0x5), 1);
3287 1 EXPECT_EQ(umax_count_base16_digits(0x6), 1);
3288 1 EXPECT_EQ(umax_count_base16_digits(0x7), 1);
3289 1 EXPECT_EQ(umax_count_base16_digits(0x8), 1);
3290 1 EXPECT_EQ(umax_count_base16_digits(0x9), 1);
3291 1 EXPECT_EQ(umax_count_base16_digits(0xA), 1);
3292 1 EXPECT_EQ(umax_count_base16_digits(0xB), 1);
3293 1 EXPECT_EQ(umax_count_base16_digits(0xF), 1);
3294 1 EXPECT_EQ(umax_count_base16_digits(0x10), 2);
3295 1 EXPECT_EQ(umax_count_base16_digits(0x111), 3);
3296 1 EXPECT_EQ(umax_count_base16_digits(0xFF11), 4);
3297 1 EXPECT_EQ(umax_count_base16_digits(0x80000000ULL), 8);
3298 1 EXPECT_EQ(umax_count_base16_digits(0x800000000ULL), 9);
3299 1 EXPECT_EQ(umax_count_base16_digits(0X98EA412F0ULL), 9);
3300 1 EXPECT_EQ(umax_count_base16_digits(0x8000000000000000ULL), 16);
3301 1 EXPECT_EQ(umax_count_base16_digits(0xFFFFFFFFFFFFFFFFULL), 16);
3302 1 }
3303
3304 1 static void test_path_dirname_basename(TestContext *ctx)
3305 {
3306 1 static const struct {
3307 const char *path;
3308 const char *dirname;
3309 const char *basename;
3310 } tests[] = {
3311 {"/home/user/example.txt", "/home/user", "example.txt"},
3312 {"./../dir/example.txt", "./../dir", "example.txt"},
3313 {"example.txt", ".", "example.txt"},
3314 {"/usr/lib", "/usr", "lib"},
3315 {"/usr", "/", "usr"},
3316 {"usr", ".", "usr"},
3317 {"/", "/", ""},
3318 {".", ".", "."},
3319 {"..", ".", ".."},
3320 {"", ".", ""},
3321 // For edge case coverage only; see comment above path_basename()
3322 {"/usr/bin/", "/usr/bin", ""},
3323 };
3324
3325
2/2
✓ Branch 10 → 3 taken 11 times.
✓ Branch 10 → 11 taken 1 time.
12 FOR_EACH_I(i, tests) {
3326 11 EXPECT_STRVIEW_EQ_CSTRING(path_slice_dirname(tests[i].path), tests[i].dirname);
3327 11 EXPECT_STRVIEW_EQ_CSTRING(path_slice_basename(strview(tests[i].path)), tests[i].basename);
3328 11 IEXPECT_STREQ(path_basename(tests[i].path), tests[i].basename);
3329
3330 11 char *dir = path_dirname(tests[i].path);
3331 11 IEXPECT_STREQ(dir, tests[i].dirname);
3332 11 free(dir);
3333 }
3334
3335 1 EXPECT_STRVIEW_EQ_CSTRING(path_slice_basename(strview(NULL)), "");
3336 1 }
3337
3338 1 static void test_path_relative(TestContext *ctx)
3339 {
3340 1 static const struct {
3341 const char *cwd;
3342 const char *path;
3343 const char *result;
3344 } tests[] = { // NOTE: at most 2 ".." components allowed in relative name
3345 { "/", "/", "/" },
3346 { "/", "/file", "file" },
3347 { "/a/b/c/d", "/a/b/file", "../../file" },
3348 { "/a/b/c/d/e", "/a/b/file", "/a/b/file" },
3349 { "/a/foobar", "/a/foo/file", "../foo/file" },
3350 { "/home/user", "/home/userx", "../userx"},
3351 { "/home/user", "/home/use", "../use"},
3352 { "/home/user", "/home/user", "."},
3353 { "/home", "/home/user", "user"},
3354 };
3355
3356
2/2
✓ Branch 6 → 3 taken 9 times.
✓ Branch 6 → 7 taken 1 time.
10 FOR_EACH_I(i, tests) {
3357 9 char *result = path_relative(tests[i].path, tests[i].cwd);
3358 9 IEXPECT_STREQ(tests[i].result, result);
3359 9 free(result);
3360 }
3361 1 }
3362
3363 1 static void test_path_slice_relative(TestContext *ctx)
3364 {
3365 1 static const char abs[] = "/a/b/c/d";
3366 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c/d/e"), abs);
3367 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/file"), abs);
3368 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c/d"), ".");
3369 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c"), "d");
3370 1 EXPECT_STREQ(path_slice_relative(abs, "/"), "a/b/c/d");
3371 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c"), abs + STRLEN("/a/b/c/"));
3372 1 EXPECT_STREQ(path_slice_relative("/", "/"), "/");
3373 1 EXPECT_STREQ(path_slice_relative("/aa/bb/ccX", "/aa/bb/cc"), "/aa/bb/ccX");
3374 1 }
3375
3376 1 static void test_short_filename_cwd(TestContext *ctx)
3377 {
3378 1 const StringView home = strview("/home/user");
3379 1 char *s = short_filename_cwd("/home/user", "/home/user", home);
3380 1 EXPECT_STREQ(s, ".");
3381 1 free(s);
3382
3383 1 s = short_filename_cwd("/home/use", "/home/user", home);
3384 1 EXPECT_STREQ(s, "../use");
3385 1 free(s);
3386
3387 1 s = short_filename_cwd("/a/b/c/d", "/a/x/y/file", home);
3388 1 EXPECT_STREQ(s, "/a/b/c/d");
3389 1 free(s);
3390
3391 1 s = short_filename_cwd("/home/user/file", "/home/user/cwd", home);
3392 1 EXPECT_STREQ(s, "~/file");
3393 1 free(s);
3394
3395 1 static const char abs[] = "/a/b";
3396 1 static const char cwd[] = "/a/x/c";
3397 1 char *rel = path_relative(abs, cwd);
3398 1 EXPECT_TRUE(strlen(abs) < strlen(rel));
3399 1 EXPECT_STREQ(rel, "../../b");
3400 1 free(rel);
3401 1 s = short_filename_cwd(abs, cwd, home);
3402 1 EXPECT_STREQ(s, "/a/b");
3403 1 free(s);
3404 1 }
3405
3406 1 static void test_short_filename(TestContext *ctx)
3407 {
3408 1 const StringView home = strview("/home/user");
3409 1 static const char rel[] = "test/main.c";
3410 1 char *abs = path_absolute(rel);
3411 1 ASSERT_NONNULL(abs);
3412 1 char *s = short_filename(abs, home);
3413 1 EXPECT_STREQ(s, rel);
3414 1 free(abs);
3415 1 free(s);
3416
3417 1 s = short_filename("/home/user/subdir/file.txt", home);
3418 1 EXPECT_STREQ(s, "~/subdir/file.txt");
3419 1 free(s);
3420
3421 1 s = short_filename("/x/y/z", home);
3422 1 EXPECT_STREQ(s, "/x/y/z");
3423 1 free(s);
3424 1 }
3425
3426 1 static void test_path_absolute(TestContext *ctx)
3427 {
3428 1 char *path = path_absolute("///dev///");
3429 1 EXPECT_STREQ(path, "/dev");
3430 1 free(path);
3431
3432 1 path = path_absolute("///dev///..///dev//");
3433 1 EXPECT_STREQ(path, "/dev");
3434 1 free(path);
3435
3436 1 path = path_absolute("///dev//n0nexist3nt-file");
3437 1 EXPECT_STREQ(path, "/dev/n0nexist3nt-file");
3438 1 free(path);
3439
3440 1 errno = 0;
3441 1 path = path_absolute("/dev/-n0n-existent-dir-[];/file");
3442 1 EXPECT_EQ(errno, ENOENT);
3443 1 EXPECT_STREQ(path, NULL);
3444 1 free(path);
3445
3446 1 path = path_absolute("///../..//./");
3447 1 EXPECT_STREQ(path, "/");
3448 1 free(path);
3449
3450 1 path = path_absolute("/");
3451 1 EXPECT_STREQ(path, "/");
3452 1 free(path);
3453
3454 1 path = path_absolute("");
3455 1 EXPECT_STREQ(path, NULL);
3456 1 free(path);
3457
3458 1 static const char linkpath[] = "./build/test/../test/test-symlink";
3459
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 22 taken 1 time.
1 if (symlink("../gen/platform.mk", linkpath) != 0) {
3460 − TEST_FAIL("symlink() failed: %s", strerror(errno));
3461 ✗ return;
3462 }
3463 1 test_pass(ctx);
3464
3465 1 path = path_absolute(linkpath);
3466 1 EXPECT_EQ(unlink(linkpath), 0);
3467 1 ASSERT_NONNULL(path);
3468 1 EXPECT_STREQ(path_basename(path), "platform.mk");
3469 1 free(path);
3470 }
3471
3472 1 static void test_path_join(TestContext *ctx)
3473 {
3474 1 char *p = path_join("/", "file");
3475 1 EXPECT_STREQ(p, "/file");
3476 1 free(p);
3477 1 p = path_join("foo", "bar");
3478 1 EXPECT_STREQ(p, "foo/bar");
3479 1 free(p);
3480 1 p = path_join("foo/", "bar");
3481 1 EXPECT_STREQ(p, "foo/bar");
3482 1 free(p);
3483 1 p = path_join("", "bar");
3484 1 EXPECT_STREQ(p, "bar");
3485 1 free(p);
3486 1 p = path_join("foo", "");
3487 1 EXPECT_STREQ(p, "foo");
3488 1 free(p);
3489 1 p = path_join("", "");
3490 1 EXPECT_STREQ(p, "");
3491 1 free(p);
3492 1 p = path_join("/", "");
3493 1 EXPECT_STREQ(p, "/");
3494 1 free(p);
3495 1 p = path_join("/home/user", ".dte");
3496 1 EXPECT_STREQ(p, "/home/user/.dte");
3497 1 free(p);
3498 1 p = path_join("/home/user/", ".dte");
3499 1 EXPECT_STREQ(p, "/home/user/.dte");
3500 1 free(p);
3501 1 p = path_join("/home/user//", ".dte");
3502 1 EXPECT_STREQ(p, "/home/user//.dte");
3503 1 free(p);
3504 1 p = path_join(NULL, NULL);
3505 1 EXPECT_STREQ(p, "");
3506 1 free(p);
3507
3508 1 p = path_join_sv(strview("foo"), strview("bar"), true);
3509 1 EXPECT_STREQ(p, "foo/bar/");
3510 1 free(p);
3511 1 p = path_join_sv(strview("foo"), strview("bar"), false);
3512 1 EXPECT_STREQ(p, "foo/bar");
3513 1 free(p);
3514 1 p = path_join_sv(strview(""), strview(""), true);
3515 1 EXPECT_STREQ(p, "");
3516 1 free(p);
3517 1 p = path_join_sv(strview("/"), strview(""), true);
3518 1 EXPECT_STREQ(p, "/");
3519 1 free(p);
3520 1 p = path_join_sv(strview(""), strview("file"), true);
3521 1 EXPECT_STREQ(p, "file/");
3522 1 free(p);
3523 1 p = path_join_sv(strview(""), strview("file"), false);
3524 1 EXPECT_STREQ(p, "file");
3525 1 free(p);
3526 1 p = path_join_sv(strview(""), strview("file/"), true);
3527 1 EXPECT_STREQ(p, "file/");
3528 1 free(p);
3529 1 p = path_join_sv(strview(NULL), strview(NULL), false);
3530 1 EXPECT_STREQ(p, "");
3531 1 free(p);
3532 1 }
3533
3534 1 static void test_path_parent(TestContext *ctx)
3535 {
3536 1 StringView sv = strview("/a/foo/bar/etc/file");
3537 1 EXPECT_EQ(sv.length, 19);
3538 1 EXPECT_TRUE(path_parent(&sv));
3539 1 EXPECT_EQ(sv.length, 14);
3540 1 EXPECT_TRUE(path_parent(&sv));
3541 1 EXPECT_EQ(sv.length, 10);
3542 1 EXPECT_TRUE(path_parent(&sv));
3543 1 EXPECT_EQ(sv.length, 6);
3544 1 EXPECT_TRUE(path_parent(&sv));
3545 1 EXPECT_EQ(sv.length, 2);
3546 1 EXPECT_TRUE(path_parent(&sv));
3547 1 EXPECT_EQ(sv.length, 1);
3548 1 EXPECT_FALSE(path_parent(&sv));
3549 1 EXPECT_EQ(sv.length, 1);
3550
3551 1 StringView sv2 = strview("/etc/foo/x/y/");
3552 1 EXPECT_EQ(sv2.length, 13);
3553 1 EXPECT_TRUE(path_parent(&sv2));
3554 1 EXPECT_EQ(sv2.length, 10);
3555 1 EXPECT_TRUE(path_parent(&sv2));
3556 1 EXPECT_EQ(sv2.length, 8);
3557 1 EXPECT_TRUE(path_parent(&sv2));
3558 1 EXPECT_EQ(sv2.length, 4);
3559 1 EXPECT_TRUE(path_parent(&sv2));
3560 1 EXPECT_EQ(sv2.length, 1);
3561 1 EXPECT_FALSE(path_parent(&sv2));
3562 1 EXPECT_EQ(sv2.length, 1);
3563 1 }
3564
3565 1 static void test_wrapping_increment(TestContext *ctx)
3566 {
3567 1 EXPECT_EQ(wrapping_increment(0, 1), 0);
3568 1 EXPECT_EQ(wrapping_increment(3, 5), 4);
3569 1 EXPECT_EQ(wrapping_increment(4, 5), 0);
3570 1 EXPECT_EQ(wrapping_increment(0, 5), 1);
3571
3572
2/2
✓ Branch 15 → 13 taken 8 times.
✓ Branch 15 → 16 taken 1 time.
10 for (size_t m = 1; m < 9; m++) {
3573
2/2
✓ Branch 13 → 11 taken 36 times.
✓ Branch 13 → 14 taken 8 times.
44 for (size_t x = 0; x < m; x++) {
3574 36 EXPECT_EQ(wrapping_increment(x, m), (x + 1) % m);
3575 }
3576 }
3577 1 }
3578
3579 1 static void test_wrapping_decrement(TestContext *ctx)
3580 {
3581 1 EXPECT_EQ(wrapping_decrement(0, 1), 0);
3582 1 EXPECT_EQ(wrapping_decrement(1, 450), 0);
3583 1 EXPECT_EQ(wrapping_decrement(0, 450), 449);
3584 1 EXPECT_EQ(wrapping_decrement(449, 450), 448);
3585
3586
2/2
✓ Branch 19 → 11 taken 8 times.
✓ Branch 19 → 20 taken 1 time.
10 for (size_t m = 1; m < 9; m++) {
3587 8 EXPECT_EQ(wrapping_decrement(0, m), m - 1);
3588
2/2
✓ Branch 17 → 14 taken 28 times.
✓ Branch 17 → 18 taken 8 times.
44 for (size_t x = 1; x < m; x++) {
3589 28 EXPECT_EQ(wrapping_decrement(x, m), (x - 1) % m);
3590 }
3591 }
3592 1 }
3593
3594 1 static void test_saturating_increment(TestContext *ctx)
3595 {
3596 1 EXPECT_UINT_EQ(saturating_increment(0, 0), 0);
3597 1 EXPECT_UINT_EQ(saturating_increment(1, 1), 1);
3598 1 EXPECT_UINT_EQ(saturating_increment(6, 7), 7);
3599 1 EXPECT_UINT_EQ(saturating_increment(7, 7), 7);
3600
3601 1 const size_t m = SIZE_MAX;
3602 1 EXPECT_UINT_EQ(saturating_increment(m - 2, m), m - 1);
3603 1 EXPECT_UINT_EQ(saturating_increment(m - 1, m), m);
3604 1 EXPECT_UINT_EQ(saturating_increment(m, m), m);
3605 1 }
3606
3607 1 static void test_saturating_decrement(TestContext *ctx)
3608 {
3609 1 EXPECT_UINT_EQ(saturating_decrement(0), 0);
3610 1 EXPECT_UINT_EQ(saturating_decrement(1), 0);
3611 1 EXPECT_UINT_EQ(saturating_decrement(2), 1);
3612 1 EXPECT_UINT_EQ(saturating_decrement(3), 2);
3613
3614 1 const size_t m = SIZE_MAX;
3615 1 EXPECT_UINT_EQ(saturating_decrement(m), m - 1);
3616 1 }
3617
3618 1 static void test_saturating_subtract(TestContext *ctx)
3619 {
3620 1 EXPECT_UINT_EQ(saturating_subtract(0, 1), 0);
3621 1 EXPECT_UINT_EQ(saturating_subtract(1, 1), 0);
3622 1 EXPECT_UINT_EQ(saturating_subtract(2, 1), 1);
3623 1 EXPECT_UINT_EQ(saturating_subtract(191, 170), 21);
3624
3625 1 const size_t m = SIZE_MAX;
3626 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m - 2), 1);
3627 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m), 0);
3628 1 EXPECT_UINT_EQ(saturating_subtract(m, m), 0);
3629 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 1), 1);
3630 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 2), 2);
3631 1 EXPECT_UINT_EQ(saturating_subtract(0, m), 0);
3632 1 EXPECT_UINT_EQ(saturating_subtract(1, m), 0);
3633 1 EXPECT_UINT_EQ(saturating_subtract(m, 1), m - 1);
3634 1 }
3635
3636 1 static void test_size_multiply_overflows(TestContext *ctx)
3637 {
3638 1 size_t r = 0;
3639 1 EXPECT_FALSE(size_multiply_overflows(10, 20, &r));
3640 1 EXPECT_UINT_EQ(r, 200);
3641 1 EXPECT_FALSE(size_multiply_overflows(0, 0, &r));
3642 1 EXPECT_UINT_EQ(r, 0);
3643 1 EXPECT_FALSE(size_multiply_overflows(1, 0, &r));
3644 1 EXPECT_UINT_EQ(r, 0);
3645 1 EXPECT_FALSE(size_multiply_overflows(0, 1, &r));
3646 1 EXPECT_UINT_EQ(r, 0);
3647 1 EXPECT_FALSE(size_multiply_overflows(0, SIZE_MAX, &r));
3648 1 EXPECT_UINT_EQ(r, 0);
3649 1 EXPECT_FALSE(size_multiply_overflows(SIZE_MAX, 0, &r));
3650 1 EXPECT_UINT_EQ(r, 0);
3651 1 EXPECT_FALSE(size_multiply_overflows(1, SIZE_MAX, &r));
3652 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3653 1 EXPECT_FALSE(size_multiply_overflows(2, SIZE_MAX / 3, &r));
3654 1 EXPECT_UINT_EQ(r, 2 * (SIZE_MAX / 3));
3655 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, 2, &r));
3656 1 EXPECT_TRUE(size_multiply_overflows(2, SIZE_MAX, &r));
3657 1 EXPECT_TRUE(size_multiply_overflows(3, SIZE_MAX / 2, &r));
3658 1 EXPECT_TRUE(size_multiply_overflows(32767, SIZE_MAX, &r));
3659 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX, &r));
3660 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3661 1 }
3662
3663 1 static void test_size_add_overflows(TestContext *ctx)
3664 {
3665 1 size_t r = 0;
3666 1 EXPECT_FALSE(size_add_overflows(10, 20, &r));
3667 1 EXPECT_UINT_EQ(r, 30);
3668 1 EXPECT_FALSE(size_add_overflows(SIZE_MAX, 0, &r));
3669 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3670 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 1, &r));
3671 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 16, &r));
3672 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX, &r));
3673 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3674 1 }
3675
3676 1 static void test_xmul(TestContext *ctx)
3677 {
3678 1 const size_t halfmax = SIZE_MAX / 2;
3679 1 EXPECT_UINT_EQ(xmul(2, halfmax), 2 * halfmax);
3680 1 EXPECT_UINT_EQ(xmul(8, 8), 64);
3681 1 EXPECT_UINT_EQ(xmul(1, SIZE_MAX), SIZE_MAX);
3682 1 EXPECT_UINT_EQ(xmul(2000, 1), 2000);
3683 1 }
3684
3685 1 static void test_xadd(TestContext *ctx)
3686 {
3687 1 const size_t max = SIZE_MAX;
3688 1 EXPECT_UINT_EQ(xadd(max - 1, 1), max);
3689 1 EXPECT_UINT_EQ(xadd(8, 8), 16);
3690 1 EXPECT_UINT_EQ(xadd(0, 0), 0);
3691
3692 1 EXPECT_UINT_EQ(xadd3(max - 3, 2, 1), max);
3693 1 EXPECT_UINT_EQ(xadd3(11, 9, 5071), 5091);
3694 1 EXPECT_UINT_EQ(xadd3(0, 0, 0), 0);
3695 1 }
3696
3697 1 static void test_mem_intern(TestContext *ctx)
3698 {
3699 1 const char *ptrs[256];
3700 1 char str[8];
3701
3702
2/2
✓ Branch 6 → 3 taken 256 times.
✓ Branch 6 → 7 taken 1 time.
257 FOR_EACH_I(i, ptrs) {
3703 256 size_t len = buf_uint_to_str(i, str);
3704 256 ptrs[i] = mem_intern(str, len);
3705 }
3706
3707 // Note that hashset_insert() (and thus also mem_intern()) always
3708 // null-terminates, even if there was no '\0' within the length bound
3709 1 EXPECT_STREQ(ptrs[0], "0");
3710 1 EXPECT_STREQ(ptrs[1], "1");
3711 1 EXPECT_STREQ(ptrs[101], "101");
3712 1 EXPECT_STREQ(ptrs[255], "255");
3713
3714 1 EXPECT_FALSE(mem_is_intern(NULL, 0));
3715 1 EXPECT_FALSE(str_is_intern(NULL));
3716 1 EXPECT_FALSE(str_is_intern("1"));
3717 1 EXPECT_TRUE(str_is_intern(ptrs[1]));
3718
3719
2/2
✓ Branch 38 → 20 taken 256 times.
✓ Branch 38 → 39 taken 1 time.
258 FOR_EACH_I(i, ptrs) {
3720 256 size_t len = buf_uint_to_str(i, str);
3721 256 const char *intern = mem_intern(str, len);
3722 256 ASSERT_NONNULL(intern);
3723 256 EXPECT_PTREQ(intern, ptrs[i]);
3724 256 EXPECT_PTREQ(intern, mem_intern(intern, len));
3725 256 EXPECT_PTREQ(intern, str_intern(intern));
3726 256 EXPECT_TRUE(interned_strings_equal(intern, ptrs[i]));
3727
3728 256 EXPECT_TRUE(mem_is_intern(intern, len));
3729 256 EXPECT_TRUE(str_is_intern(intern));
3730 256 EXPECT_FALSE(mem_is_intern(str, len));
3731 256 EXPECT_FALSE(str_is_intern(str));
3732 }
3733 1 }
3734
3735 1 static void test_read_file(TestContext *ctx)
3736 {
3737 1 char *buf = NULL;
3738 1 ASSERT_EQ(read_file("/dev/null", &buf, 64), 0);
3739 1 ASSERT_NONNULL(buf);
3740 1 EXPECT_UINT_EQ((unsigned char)buf[0], '\0');
3741 1 free(buf);
3742
3743 1 buf = NULL;
3744 1 errno = 0;
3745 1 EXPECT_EQ(read_file("test/data/", &buf, 64), -1);
3746 1 EXPECT_EQ(errno, EISDIR);
3747 1 EXPECT_NULL(buf);
3748 1 free(buf);
3749
3750 1 buf = NULL;
3751 1 errno = 0;
3752 1 EXPECT_EQ(read_file("test/data/3lines.txt", &buf, 1), -1);
3753 1 EXPECT_EQ(errno, EFBIG);
3754 1 EXPECT_NULL(buf);
3755 1 free(buf);
3756
3757 1 ssize_t size = read_file("test/data/3lines.txt", &buf, 512);
3758 1 EXPECT_EQ(size, 26);
3759 1 ASSERT_NONNULL(buf);
3760 1 size_t pos = 0;
3761 1 const char *line = buf_next_line(buf, &pos, size);
3762 1 EXPECT_STREQ(line, "line #1");
3763 1 EXPECT_EQ(pos, 8);
3764 1 ASSERT_TRUE(pos < size);
3765 1 line = buf_next_line(buf, &pos, size);
3766 1 EXPECT_STREQ(line, " line #2");
3767 1 EXPECT_EQ(pos, 17);
3768 1 ASSERT_TRUE(pos < size);
3769 1 line = buf_next_line(buf, &pos, size);
3770 1 EXPECT_STREQ(line, " line #3");
3771 1 EXPECT_EQ3(pos, size, 26);
3772 1 free(buf);
3773 1 }
3774
3775 1 static void test_xfopen(TestContext *ctx)
3776 {
3777 1 static const char modes[][4] = {"a", "a+", "r", "r+", "w", "w+"};
3778
2/2
✓ Branch 10 → 3 taken 6 times.
✓ Branch 10 → 11 taken 1 time.
7 FOR_EACH_I(i, modes) {
3779 6 FILE *f = xfopen("/dev/null", modes[i], O_CLOEXEC, 0666);
3780 6 IEXPECT_TRUE(f && fclose(f) == 0);
3781 }
3782 1 }
3783
3784 1 static void test_xstdio(TestContext *ctx)
3785 {
3786 1 FILE *f = xfopen("/dev/null", "r+", O_CLOEXEC, 0666);
3787 1 ASSERT_NONNULL(f);
3788
3789 1 char buf[16];
3790 1 EXPECT_NULL(xfgets(buf, sizeof(buf), f));
3791 1 EXPECT_NE(xfputs("str", f), EOF);
3792 1 EXPECT_EQ(xfputc(' ', f), ' ');
3793 1 EXPECT_EQ(xfprintf(f, "fmt %d", 42), 6);
3794 1 EXPECT_EQ(xfflush(f), 0);
3795 1 EXPECT_EQ(fclose(f), 0);
3796 1 }
3797
3798 1 static void test_fd_set_cloexec(TestContext *ctx)
3799 {
3800 1 int fd = xopen("/dev/null", O_RDONLY, 0);
3801 1 ASSERT_TRUE(fd >= 0);
3802 1 int flags = fcntl(fd, F_GETFD);
3803 1 EXPECT_TRUE(flags >= 0);
3804 1 EXPECT_EQ(flags & FD_CLOEXEC, 0);
3805
3806 1 EXPECT_TRUE(fd_set_cloexec(fd, true));
3807 1 flags = fcntl(fd, F_GETFD);
3808 1 EXPECT_TRUE(flags > 0);
3809 1 EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
3810
3811 // This set of tests is repeated twice, in order to check the special
3812 // case where the F_SETFD operation can be omitted because FD_CLOEXEC
3813 // was already set as requested
3814
2/2
✓ Branch 19 → 13 taken 2 times.
✓ Branch 19 → 20 taken 1 time.
4 for (size_t i = 0; i < 2; i++) {
3815 2 IEXPECT_TRUE(fd_set_cloexec(fd, false));
3816 2 flags = fcntl(fd, F_GETFD);
3817 2 IEXPECT_TRUE(flags >= 0);
3818 2 IEXPECT_EQ(flags & FD_CLOEXEC, 0);
3819 }
3820
3821 1 xclose(fd);
3822 1 }
3823
3824 1 static void test_fd_set_nonblock(TestContext *ctx)
3825 {
3826 1 int fd = xopen("/dev/null", O_RDONLY, 0);
3827 1 ASSERT_TRUE(fd >= 0);
3828 1 int flags = fcntl(fd, F_GETFL);
3829 1 EXPECT_TRUE(flags >= 0);
3830 1 EXPECT_EQ(flags & O_NONBLOCK, 0);
3831
3832 1 EXPECT_TRUE(fd_set_nonblock(fd, true));
3833 1 flags = fcntl(fd, F_GETFL);
3834 1 EXPECT_TRUE(flags > 0);
3835 1 EXPECT_EQ(flags & O_NONBLOCK, O_NONBLOCK);
3836
3837
2/2
✓ Branch 19 → 13 taken 2 times.
✓ Branch 19 → 20 taken 1 time.
4 for (size_t i = 0; i < 2; i++) {
3838 2 IEXPECT_TRUE(fd_set_nonblock(fd, false));
3839 2 flags = fcntl(fd, F_GETFL);
3840 2 IEXPECT_TRUE(flags >= 0);
3841 2 IEXPECT_EQ(flags & O_NONBLOCK, 0);
3842 }
3843
3844 1 xclose(fd);
3845 1 }
3846
3847 1 static void test_fork_exec(TestContext *ctx)
3848 {
3849 1 int fd[3];
3850 1 fd[0] = xopen("/dev/null", O_RDWR | O_CLOEXEC, 0);
3851 1 ASSERT_TRUE(fd[0] > 0);
3852 1 fd[1] = fd[0];
3853 1 fd[2] = fd[0];
3854
3855 1 const char *argv[] = {"sh", "-c", "exit 95", NULL};
3856 1 pid_t pid = fork_exec(argv, fd, 0, 0, true);
3857 1 ASSERT_NE(pid, -1);
3858 1 int r = wait_child(pid);
3859 1 EXPECT_EQ(r, 95);
3860
3861 1 argv[0] = "sleep";
3862 1 argv[1] = "5";
3863 1 argv[2] = NULL;
3864 1 pid = fork_exec(argv, fd, 0, 0, true);
3865 1 ASSERT_NE(pid, -1);
3866 1 EXPECT_EQ(kill(pid, SIGINT), 0);
3867 1 r = wait_child(pid);
3868 1 EXPECT_TRUE(r >= 256);
3869 1 EXPECT_EQ(r >> 8, SIGINT);
3870
3871 1 EXPECT_EQ(xclose(fd[0]), 0);
3872 1 }
3873
3874 1 static void test_xmemmem(TestContext *ctx)
3875 {
3876 1 static const char haystack[] = "finding a needle in a haystack";
3877 1 const char *needle = xmemmem(haystack, sizeof(haystack), STRN("needle"));
3878 1 ASSERT_NONNULL(needle);
3879 1 EXPECT_PTREQ(needle, haystack + 10);
3880
3881 1 needle = xmemmem(haystack, sizeof(haystack), "\0", 1);
3882 1 ASSERT_NONNULL(needle);
3883 1 EXPECT_PTREQ(needle, haystack + sizeof(haystack) - 1);
3884
3885 1 needle = xmemmem(haystack, sizeof(haystack) - 1, "\0", 1);
3886 1 EXPECT_NULL(needle);
3887
3888 1 needle = xmemmem(haystack, sizeof(haystack), STRN("in "));
3889 1 ASSERT_NONNULL(needle);
3890 1 EXPECT_PTREQ(needle, haystack + 17);
3891
3892 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystack"));
3893 1 ASSERT_NONNULL(needle);
3894 1 EXPECT_PTREQ(needle, haystack + 22);
3895
3896 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystacks"));
3897 1 EXPECT_NULL(needle);
3898
3899 1 needle = xmemmem(haystack, sizeof(haystack), STRN("haystacks"));
3900 1 EXPECT_NULL(needle);
3901 1 }
3902
3903 1 static void test_xmemrchr(TestContext *ctx)
3904 {
3905 1 static const char str[] = "123456789 abcdefedcba 987654321";
3906 1 EXPECT_PTREQ(xmemrchr(NULL, '1', 0), NULL);
3907 1 EXPECT_PTREQ(xmemrchr(str, '9', sizeof(str) - 1), str + 22);
3908 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 1), str + sizeof(str) - 2);
3909 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 2), str);
3910 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str)), str + sizeof(str) - 1);
3911 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str) - 1), NULL);
3912 1 EXPECT_PTREQ(xmemrchr(str, 'z', sizeof(str) - 1), NULL);
3913 1 }
3914
3915 1 static void test_str_to_bitflags(TestContext *ctx)
3916 {
3917 1 static const char strs[][8] = {"zero", "one", "two", "three"};
3918 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS(strview("one,three"), strs, true), 1 << 1 | 1 << 3);
3919 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS(strview("two,invalid,zero"), strs, true), 1 << 2 | 1 << 0);
3920 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS(strview("two,invalid,zero"), strs, false), 0);
3921 1 }
3922
3923 1 static void test_log_level_from_str(TestContext *ctx)
3924 {
3925 1 EXPECT_EQ(log_level_from_str("none"), LOG_LEVEL_NONE);
3926 1 EXPECT_EQ(log_level_from_str("crit"), LOG_LEVEL_CRITICAL);
3927 1 EXPECT_EQ(log_level_from_str("error"), LOG_LEVEL_ERROR);
3928 1 EXPECT_EQ(log_level_from_str("warning"), LOG_LEVEL_WARNING);
3929 1 EXPECT_EQ(log_level_from_str("notice"), LOG_LEVEL_NOTICE);
3930 1 EXPECT_EQ(log_level_from_str("info"), LOG_LEVEL_INFO);
3931 1 EXPECT_EQ(log_level_from_str("debug"), LOG_LEVEL_DEBUG);
3932 1 EXPECT_EQ(log_level_from_str("trace"), LOG_LEVEL_TRACE);
3933
3934 1 EXPECT_EQ(log_level_from_str("xyz"), LOG_LEVEL_INVALID);
3935 1 EXPECT_EQ(log_level_from_str(" "), LOG_LEVEL_INVALID);
3936 1 EXPECT_EQ(log_level_from_str("warn"), LOG_LEVEL_INVALID);
3937 1 EXPECT_EQ(log_level_from_str("errors"), LOG_LEVEL_INVALID);
3938
3939 1 LogLevel default_level = log_level_default();
3940 1 EXPECT_EQ(log_level_from_str(""), default_level);
3941 1 EXPECT_EQ(log_level_from_str(NULL), default_level);
3942 1 }
3943
3944 1 static void test_log_level_to_str(TestContext *ctx)
3945 {
3946 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NONE), "none");
3947 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_CRITICAL), "crit");
3948 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_ERROR), "error");
3949 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_WARNING), "warning");
3950 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NOTICE), "notice");
3951 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_INFO), "info");
3952 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_DEBUG), "debug");
3953 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_TRACE), "trace");
3954 1 }
3955
3956 1 static void test_timespec_subtract(TestContext *ctx)
3957 {
3958 1 struct timespec a = {.tv_sec = 3, .tv_nsec = 5497};
3959 1 struct timespec b = {.tv_sec = 1, .tv_nsec = NS_PER_SECOND - 1};
3960 1 struct timespec r = timespec_subtract(&a, &b);
3961 1 EXPECT_EQ(r.tv_sec, 1);
3962 1 EXPECT_EQ(r.tv_nsec, 5498);
3963
3964 1 b.tv_nsec = 501;
3965 1 r = timespec_subtract(&a, &b);
3966 1 EXPECT_EQ(r.tv_sec, 2);
3967 1 EXPECT_EQ(r.tv_nsec, 4996);
3968 1 }
3969
3970 1 static void test_timespec_to_str(TestContext *ctx)
3971 {
3972 1 char buf[TIME_STR_BUFSIZE] = "";
3973 1 struct timespec ts = {.tv_sec = 0};
3974 1 EXPECT_TRUE(timespecs_equal(&ts, &ts));
3975
3976 1 errno = 0;
3977 1 ts.tv_nsec = NS_PER_SECOND;
3978 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3979 1 EXPECT_EQ(errno, EINVAL);
3980
3981 1 errno = 0;
3982 1 ts.tv_nsec = -1;
3983 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3984 1 EXPECT_EQ(errno, EINVAL);
3985
3986 // Note: $TZ is set to "UTC" in test_init()
3987 1 ts.tv_sec = 4321;
3988 1 ts.tv_nsec = 9876;
3989 1 const char *r = timespec_to_str(&ts, buf);
3990 1 EXPECT_STREQ(r, "1970-01-01 01:12:01.9876 +0000");
3991 1 EXPECT_PTREQ(r, buf);
3992
3993 1 ts.tv_sec = -1;
3994 1 ts.tv_nsec = NS_PER_SECOND - 1;
3995 1 r = timespec_to_str(&ts, buf);
3996 1 EXPECT_STREQ(r, "1969-12-31 23:59:59.999999999 +0000");
3997 1 }
3998
3999 1 static void test_progname(TestContext *ctx)
4000 {
4001 1 const char *const args[] = {"arg0", "", NULL};
4002 1 char **arg0 = (char**)args;
4003 1 char **arg1 = arg0 + 1;
4004 1 char **arg2 = arg0 + 2;
4005 1 EXPECT_STREQ(progname(1, arg0, "1"), "arg0");
4006 1 EXPECT_STREQ(progname(1, NULL, "2"), "2");
4007 1 EXPECT_STREQ(progname(0, arg0, "3"), "3");
4008 1 EXPECT_STREQ(progname(1, arg1, "4"), "4");
4009 1 EXPECT_STREQ(progname(1, arg2, "5"), "5");
4010 1 EXPECT_STREQ(progname(0, NULL, NULL), "_PROG_");
4011 1 }
4012
4013 static const TestEntry tests[] = {
4014 TEST(test_util_macros),
4015 TEST(test_is_power_of_2),
4016 TEST(test_xmalloc),
4017 TEST(test_xstreq),
4018 TEST(test_xstrrchr),
4019 TEST(test_xmempcpy),
4020 TEST(test_str_has_sv_prefix),
4021 TEST(test_str_has_prefix),
4022 TEST(test_hex_decode),
4023 TEST(test_hex_encode_byte),
4024 TEST(test_ascii),
4025 TEST(test_mem_equal),
4026 TEST(test_mem_equal_icase),
4027 TEST(test_base64_decode),
4028 TEST(test_base64_encode_block),
4029 TEST(test_base64_encode_final),
4030 TEST(test_string),
4031 TEST(test_string_next_alloc_size),
4032 TEST(test_string_view),
4033 TEST(test_strview_has_suffix),
4034 TEST(test_strview_suffix_length),
4035 TEST(test_strview_remove_matching),
4036 TEST(test_strview_from_slice),
4037 TEST(test_get_delim),
4038 TEST(test_get_delim_str),
4039 TEST(test_strn_replace_byte),
4040 TEST(test_string_array_concat),
4041 TEST(test_size_str_width),
4042 TEST(test_buf_parse_uintmax),
4043 TEST(test_buf_parse_ulong),
4044 TEST(test_buf_parse_size),
4045 TEST(test_buf_parse_hex_uint),
4046 TEST(test_str_to_int),
4047 TEST(test_str_to_size),
4048 TEST(test_str_to_filepos),
4049 TEST(test_parse_file_line_col),
4050 TEST(test_buf_umax_to_hex_str),
4051 TEST(test_codepoint_to_str),
4052 TEST(test_parse_filesize),
4053 TEST(test_umax_to_str),
4054 TEST(test_uint_to_str),
4055 TEST(test_ulong_to_str),
4056 TEST(test_buf_umax_to_str),
4057 TEST(test_buf_uint_to_str),
4058 TEST(test_buf_u8_to_str),
4059 TEST(test_file_permissions_to_str),
4060 TEST(test_human_readable_size),
4061 TEST(test_filesize_to_str),
4062 TEST(test_filesize_to_str_precise),
4063 TEST(test_u_char_size),
4064 TEST(test_u_char_width),
4065 TEST(test_u_to_lower),
4066 TEST(test_u_to_upper),
4067 TEST(test_u_is_lower),
4068 TEST(test_u_is_upper),
4069 TEST(test_u_is_ascii_upper),
4070 TEST(test_u_is_cntrl),
4071 TEST(test_u_is_unicode),
4072 TEST(test_u_is_zero_width),
4073 TEST(test_u_is_special_whitespace),
4074 TEST(test_u_is_unprintable),
4075 TEST(test_u_str_width),
4076 TEST(test_u_set_char_raw),
4077 TEST(test_u_set_char),
4078 TEST(test_u_make_printable),
4079 TEST(test_u_get_char),
4080 TEST(test_u_prev_char),
4081 TEST(test_u_skip_chars),
4082 TEST(test_ptr_array),
4083 TEST(test_ptr_array_move),
4084 TEST(test_ptr_array_insert),
4085 TEST(test_list),
4086 TEST(test_hashmap),
4087 TEST(test_hashset),
4088 TEST(test_intmap),
4089 TEST(test_next_multiple),
4090 TEST(test_next_pow2),
4091 TEST(test_popcount),
4092 TEST(test_ctz),
4093 TEST(test_ffs),
4094 TEST(test_lsbit),
4095 TEST(test_msbit),
4096 TEST(test_clz),
4097 TEST(test_umax_bitwidth),
4098 TEST(test_umax_count_base16_digits),
4099 TEST(test_path_dirname_basename),
4100 TEST(test_path_relative),
4101 TEST(test_path_slice_relative),
4102 TEST(test_short_filename_cwd),
4103 TEST(test_short_filename),
4104 TEST(test_path_absolute),
4105 TEST(test_path_join),
4106 TEST(test_path_parent),
4107 TEST(test_wrapping_increment),
4108 TEST(test_wrapping_decrement),
4109 TEST(test_saturating_increment),
4110 TEST(test_saturating_decrement),
4111 TEST(test_saturating_subtract),
4112 TEST(test_size_multiply_overflows),
4113 TEST(test_size_add_overflows),
4114 TEST(test_xmul),
4115 TEST(test_xadd),
4116 TEST(test_mem_intern),
4117 TEST(test_read_file),
4118 TEST(test_xfopen),
4119 TEST(test_xstdio),
4120 TEST(test_fd_set_cloexec),
4121 TEST(test_fd_set_nonblock),
4122 TEST(test_fork_exec),
4123 TEST(test_xmemmem),
4124 TEST(test_xmemrchr),
4125 TEST(test_str_to_bitflags),
4126 TEST(test_log_level_from_str),
4127 TEST(test_log_level_to_str),
4128 TEST(test_timespec_subtract),
4129 TEST(test_timespec_to_str),
4130 TEST(test_progname),
4131 };
4132
4133 const TestGroup util_tests = TEST_GROUP(tests);
4134