dte test coverage


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