dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 99.9% 2999 / 1 / 3001
Functions: 100.0% 115 / 0 / 115
Branches: 99.0% 101 / 42 / 144

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