dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 99.9% 3003 / 1 / 3005
Functions: 100.0% 115 / 0 / 115
Branches: 99.1% 105 / 42 / 148

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
2/2
✓ Branch 27 → 25 taken 70 times.
✓ Branch 27 → 28 taken 1 time.
71 for (size_t i = 0; i < 70; i++) {
2985
2/2
✓ Branch 25 → 23 taken 490 times.
✓ Branch 25 → 26 taken 70 times.
560 for (size_t p2 = 64; p2; p2 >>= 1) {
2986 490 size_t remainder_complement = (-i & (p2 - 1));
2987 490 IEXPECT_EQ(next_multiple(i, p2), i + remainder_complement);
2988 }
2989 }
2990
2991 1 const size_t size_max = (size_t)-1;
2992 1 const size_t pow2_max = size_max & ~(size_max >> 1);
2993 1 EXPECT_TRUE(IS_POWER_OF_2(pow2_max));
2994 1 EXPECT_UINT_EQ(next_multiple(size_max, 1), size_max);
2995 1 EXPECT_UINT_EQ(next_multiple(pow2_max, 1), pow2_max);
2996 1 EXPECT_UINT_EQ(next_multiple(pow2_max, pow2_max), pow2_max);
2997
2998 // Note: returns 0 on overflow
2999 1 EXPECT_UINT_EQ(next_multiple(pow2_max + 1, pow2_max), 0);
3000 1 EXPECT_UINT_EQ(next_multiple(size_max + 0, pow2_max), 0);
3001 1 EXPECT_UINT_EQ(next_multiple(size_max - 1, pow2_max), 0);
3002
3003 1 const size_t a = pow2_max >> 1;
3004 1 EXPECT_UINT_EQ(next_multiple(a, a), a);
3005 1 EXPECT_UINT_EQ(next_multiple(a + 1, a), pow2_max);
3006 1 }
3007
3008 1 static void test_next_pow2(TestContext *ctx)
3009 {
3010 1 EXPECT_UINT_EQ(next_pow2(0), 1);
3011 1 EXPECT_UINT_EQ(next_pow2(1), 1);
3012 1 EXPECT_UINT_EQ(next_pow2(2), 2);
3013 1 EXPECT_UINT_EQ(next_pow2(3), 4);
3014 1 EXPECT_UINT_EQ(next_pow2(4), 4);
3015 1 EXPECT_UINT_EQ(next_pow2(5), 8);
3016 1 EXPECT_UINT_EQ(next_pow2(8), 8);
3017 1 EXPECT_UINT_EQ(next_pow2(9), 16);
3018 1 EXPECT_UINT_EQ(next_pow2(17), 32);
3019 1 EXPECT_UINT_EQ(next_pow2(61), 64);
3020 1 EXPECT_UINT_EQ(next_pow2(64), 64);
3021 1 EXPECT_UINT_EQ(next_pow2(65), 128);
3022 1 EXPECT_UINT_EQ(next_pow2(200), 256);
3023 1 EXPECT_UINT_EQ(next_pow2(1000), 1024);
3024 1 EXPECT_UINT_EQ(next_pow2(5500), 8192);
3025
3026 1 const size_t size_max = (size_t)-1;
3027 1 const size_t pow2_max = ~(size_max >> 1);
3028 1 EXPECT_TRUE(IS_POWER_OF_2(pow2_max));
3029 1 EXPECT_UINT_EQ(next_pow2(size_max >> 1), pow2_max);
3030 1 EXPECT_UINT_EQ(next_pow2(pow2_max), pow2_max);
3031 1 EXPECT_UINT_EQ(next_pow2(pow2_max - 1), pow2_max);
3032
3033 // Note: returns 0 on overflow
3034 1 EXPECT_UINT_EQ(next_pow2(pow2_max + 1), 0);
3035 1 EXPECT_UINT_EQ(next_pow2(size_max), 0);
3036 1 EXPECT_UINT_EQ(next_pow2(size_max - 1), 0);
3037 1 }
3038
3039 1 static void test_popcount(TestContext *ctx)
3040 {
3041 1 EXPECT_EQ(u32_popcount(0), 0);
3042 1 EXPECT_EQ(u32_popcount(1), 1);
3043 1 EXPECT_EQ(u32_popcount(11), 3);
3044 1 EXPECT_EQ(u32_popcount(128), 1);
3045 1 EXPECT_EQ(u32_popcount(255), 8);
3046 1 EXPECT_EQ(u32_popcount(UINT32_MAX), 32);
3047 1 EXPECT_EQ(u32_popcount(UINT32_MAX - 1), 31);
3048 1 EXPECT_EQ(u32_popcount(0xE10F02C9u), 13);
3049
3050 1 EXPECT_EQ(u64_popcount(0), 0);
3051 1 EXPECT_EQ(u64_popcount(1), 1);
3052 1 EXPECT_EQ(u64_popcount(255), 8);
3053 1 EXPECT_EQ(u64_popcount(UINT64_MAX), 64);
3054 1 EXPECT_EQ(u64_popcount(UINT64_MAX - 1), 63);
3055 1 EXPECT_EQ(u64_popcount(0xFFFFFFFFFFull), 40);
3056 1 EXPECT_EQ(u64_popcount(0x10000000000ull), 1);
3057 1 EXPECT_EQ(u64_popcount(0x9010F0EEC2003B70ull), 24);
3058
3059
2/2
✓ Branch 23 → 19 taken 32 times.
✓ Branch 23 → 28 taken 1 time.
33 for (unsigned int i = 0; i < 32; i++) {
3060 32 IEXPECT_EQ(u32_popcount(UINT32_MAX << i), 32 - i);
3061 32 IEXPECT_EQ(u32_popcount(UINT32_MAX >> i), 32 - i);
3062 32 IEXPECT_EQ(u32_popcount(1u << i), 1);
3063 }
3064
3065
2/2
✓ Branch 28 → 24 taken 64 times.
✓ Branch 28 → 29 taken 1 time.
65 for (unsigned int i = 0; i < 64; i++) {
3066 64 IEXPECT_EQ(u64_popcount(UINT64_MAX << i), 64 - i);
3067 64 IEXPECT_EQ(u64_popcount(UINT64_MAX >> i), 64 - i);
3068 64 IEXPECT_EQ(u64_popcount(1ull << i), 1);
3069 }
3070 1 }
3071
3072 1 static void test_ctz(TestContext *ctx)
3073 {
3074 1 EXPECT_EQ(u32_ctz(1), 0);
3075 1 EXPECT_EQ(u32_ctz(11), 0);
3076 1 EXPECT_EQ(u32_ctz(127), 0);
3077 1 EXPECT_EQ(u32_ctz(128), 7);
3078 1 EXPECT_EQ(u32_ctz(129), 0);
3079 1 EXPECT_EQ(u32_ctz(130), 1);
3080 1 EXPECT_EQ(u32_ctz(255), 0);
3081 1 EXPECT_EQ(u32_ctz(UINT32_MAX), 0);
3082 1 EXPECT_EQ(u32_ctz(UINT32_MAX - 1), 1);
3083 1 EXPECT_EQ(u32_ctz(0xE10F02C9u), 0);
3084 1 EXPECT_EQ(u32_ctz(0xE10F02CCu), 2);
3085
3086 1 EXPECT_EQ(umax_ctz(1), 0);
3087 1 EXPECT_EQ(umax_ctz(11), 0);
3088 1 EXPECT_EQ(umax_ctz(127), 0);
3089 1 EXPECT_EQ(umax_ctz(128), 7);
3090 1 EXPECT_EQ(umax_ctz(129), 0);
3091 1 EXPECT_EQ(umax_ctz(130), 1);
3092 1 EXPECT_EQ(umax_ctz(255), 0);
3093 1 EXPECT_EQ(umax_ctz(0xE10F02C9u), 0);
3094 1 EXPECT_EQ(umax_ctz(0xE10F02CCu), 2);
3095 1 EXPECT_EQ(umax_ctz(0x8000000000000000ull), 63);
3096 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX), 0);
3097 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX - 1), 1);
3098 1 EXPECT_EQ(umax_ctz(UINTMAX_MAX - 7), 3);
3099 1 }
3100
3101 1 static void test_ffs(TestContext *ctx)
3102 {
3103 1 EXPECT_EQ(u32_ffs(0), 0);
3104 1 EXPECT_EQ(u32_ffs(1), 1);
3105 1 EXPECT_EQ(u32_ffs(6), 2);
3106 1 EXPECT_EQ(u32_ffs(8), 4);
3107 1 EXPECT_EQ(u32_ffs(255), 1);
3108 1 EXPECT_EQ(u32_ffs(256), 9);
3109 1 EXPECT_EQ(u32_ffs(UINT32_MAX), 1);
3110 1 EXPECT_EQ(u32_ffs(UINT32_MAX - 1), 2);
3111 1 EXPECT_EQ(u32_ffs(UINT32_MAX << 8), 9);
3112 1 EXPECT_EQ(u32_ffs(1u << 31), 32);
3113 1 EXPECT_EQ(u32_ffs(1u << 30), 31);
3114 1 EXPECT_EQ(u32_ffs(1u << 18), 19);
3115 1 }
3116
3117 1 static void test_lsbit(TestContext *ctx)
3118 {
3119 1 EXPECT_EQ(u32_lsbit(0), 0);
3120 1 EXPECT_EQ(u32_lsbit(1), 1);
3121 1 EXPECT_EQ(u32_lsbit(2), 2);
3122 1 EXPECT_EQ(u32_lsbit(3), 1);
3123 1 EXPECT_EQ(u32_lsbit(4), 4);
3124 1 EXPECT_EQ(u32_lsbit(255), 1);
3125 1 EXPECT_EQ(u32_lsbit(256), 256);
3126 1 EXPECT_EQ(u32_lsbit(257), 1);
3127 1 EXPECT_EQ(u32_lsbit(258), 2);
3128 1 EXPECT_EQ(u32_lsbit(1u << 31), 1u << 31);
3129 1 EXPECT_EQ(u32_lsbit(1u << 30), 1u << 30);
3130 1 EXPECT_EQ(u32_lsbit(7u << 30), 1u << 30);
3131 1 EXPECT_EQ(u32_lsbit(UINT32_MAX), 1);
3132 1 EXPECT_EQ(u32_lsbit(UINT32_MAX << 25), 1u << 25);
3133
3134
2/2
✓ Branch 23 → 17 taken 69 times.
✓ Branch 23 → 24 taken 1 time.
70 for (uint32_t i = 1; i < 70; i++) {
3135 69 uint32_t lsb = u32_lsbit(i);
3136 69 IEXPECT_TRUE(IS_POWER_OF_2(lsb));
3137 69 IEXPECT_TRUE(lsb & i);
3138 }
3139 1 }
3140
3141 1 static void test_msbit(TestContext *ctx)
3142 {
3143 1 EXPECT_EQ(size_msbit(0), 0);
3144 1 EXPECT_EQ(size_msbit(1), 1);
3145 1 EXPECT_EQ(size_msbit(2), 2);
3146 1 EXPECT_EQ(size_msbit(3), 2);
3147 1 EXPECT_EQ(size_msbit(4), 4);
3148 1 EXPECT_EQ(size_msbit(7), 4);
3149 1 EXPECT_EQ(size_msbit(8), 8);
3150 1 EXPECT_EQ(size_msbit(255), 128);
3151 1 EXPECT_EQ(size_msbit(256), 256);
3152 1 EXPECT_UINT_EQ(size_msbit(0x1FFFu), 0x1000u);
3153 1 EXPECT_UINT_EQ(size_msbit(0xFFFFu), 0x8000u);
3154
3155 1 const size_t max = SIZE_MAX;
3156 1 const size_t max_pow2 = ~(max >> 1);
3157 1 EXPECT_UINT_EQ(size_msbit(max), max_pow2);
3158 1 EXPECT_UINT_EQ(size_msbit(max - 1), max_pow2);
3159 1 EXPECT_UINT_EQ(size_msbit(max_pow2), max_pow2);
3160 1 EXPECT_UINT_EQ(size_msbit(max_pow2 - 1), max_pow2 >> 1);
3161 1 EXPECT_UINT_EQ(size_msbit(max_pow2 + 1), max_pow2);
3162
3163
2/2
✓ Branch 25 → 19 taken 69 times.
✓ Branch 25 → 26 taken 1 time.
70 for (size_t i = 1; i < 70; i++) {
3164 69 size_t msb = size_msbit(i);
3165 69 IEXPECT_TRUE(IS_POWER_OF_2(msb));
3166 69 IEXPECT_TRUE(msb & i);
3167 }
3168 1 }
3169
3170 1 static void test_clz(TestContext *ctx)
3171 {
3172 1 EXPECT_EQ(u64_clz(1), 63);
3173 1 EXPECT_EQ(u64_clz(2), 62);
3174 1 EXPECT_EQ(u64_clz(3), 62);
3175 1 EXPECT_EQ(u64_clz(1ULL << 10), 53);
3176 1 EXPECT_EQ(u64_clz(1ULL << 55), 8);
3177 1 EXPECT_EQ(u64_clz(1ULL << 63), 0);
3178 1 EXPECT_EQ(u64_clz(UINT64_MAX), 0);
3179 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 1), 1);
3180 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 3), 3);
3181 1 }
3182
3183 1 static void test_umax_bitwidth(TestContext *ctx)
3184 {
3185 1 EXPECT_EQ(umax_bitwidth(0), 0);
3186 1 EXPECT_EQ(umax_bitwidth(1), 1);
3187 1 EXPECT_EQ(umax_bitwidth(2), 2);
3188 1 EXPECT_EQ(umax_bitwidth(3), 2);
3189 1 EXPECT_EQ(umax_bitwidth(0x80), 8);
3190 1 EXPECT_EQ(umax_bitwidth(0xFF), 8);
3191 1 EXPECT_EQ(umax_bitwidth(0x10081), 17);
3192 1 EXPECT_EQ(umax_bitwidth(1ULL << 62), 63);
3193 1 EXPECT_EQ(umax_bitwidth(0xFFFFFFFFFFFFFFFFULL), 64);
3194 1 }
3195
3196 1 static void test_umax_count_base16_digits(TestContext *ctx)
3197 {
3198 1 EXPECT_EQ(umax_count_base16_digits(0x0), 1);
3199 1 EXPECT_EQ(umax_count_base16_digits(0x1), 1);
3200 1 EXPECT_EQ(umax_count_base16_digits(0x2), 1);
3201 1 EXPECT_EQ(umax_count_base16_digits(0x3), 1);
3202 1 EXPECT_EQ(umax_count_base16_digits(0x4), 1);
3203 1 EXPECT_EQ(umax_count_base16_digits(0x5), 1);
3204 1 EXPECT_EQ(umax_count_base16_digits(0x6), 1);
3205 1 EXPECT_EQ(umax_count_base16_digits(0x7), 1);
3206 1 EXPECT_EQ(umax_count_base16_digits(0x8), 1);
3207 1 EXPECT_EQ(umax_count_base16_digits(0x9), 1);
3208 1 EXPECT_EQ(umax_count_base16_digits(0xA), 1);
3209 1 EXPECT_EQ(umax_count_base16_digits(0xB), 1);
3210 1 EXPECT_EQ(umax_count_base16_digits(0xF), 1);
3211 1 EXPECT_EQ(umax_count_base16_digits(0x10), 2);
3212 1 EXPECT_EQ(umax_count_base16_digits(0x111), 3);
3213 1 EXPECT_EQ(umax_count_base16_digits(0xFF11), 4);
3214 1 EXPECT_EQ(umax_count_base16_digits(0x80000000ULL), 8);
3215 1 EXPECT_EQ(umax_count_base16_digits(0x800000000ULL), 9);
3216 1 EXPECT_EQ(umax_count_base16_digits(0X98EA412F0ULL), 9);
3217 1 EXPECT_EQ(umax_count_base16_digits(0x8000000000000000ULL), 16);
3218 1 EXPECT_EQ(umax_count_base16_digits(0xFFFFFFFFFFFFFFFFULL), 16);
3219 1 }
3220
3221 1 static void test_path_dirname_basename(TestContext *ctx)
3222 {
3223 1 static const struct {
3224 const char *path;
3225 const char *dirname;
3226 const char *basename;
3227 } tests[] = {
3228 {"/home/user/example.txt", "/home/user", "example.txt"},
3229 {"./../dir/example.txt", "./../dir", "example.txt"},
3230 {"/usr/bin/", "/usr/bin", ""},
3231 {"example.txt", ".", "example.txt"},
3232 {"/usr/lib", "/usr", "lib"},
3233 {"/usr", "/", "usr"},
3234 {"usr", ".", "usr"},
3235 {"/", "/", ""},
3236 {".", ".", "."},
3237 {"..", ".", ".."},
3238 {"", ".", ""},
3239 };
3240
2/2
✓ Branch 7 → 3 taken 11 times.
✓ Branch 7 → 8 taken 1 time.
12 FOR_EACH_I(i, tests) {
3241 11 char *dir = path_dirname(tests[i].path);
3242 11 IEXPECT_STREQ(dir, tests[i].dirname);
3243 11 free(dir);
3244 11 IEXPECT_STREQ(path_basename(tests[i].path), tests[i].basename);
3245 }
3246 1 }
3247
3248 1 static void test_path_relative(TestContext *ctx)
3249 {
3250 1 static const struct {
3251 const char *cwd;
3252 const char *path;
3253 const char *result;
3254 } tests[] = { // NOTE: at most 2 ".." components allowed in relative name
3255 { "/", "/", "/" },
3256 { "/", "/file", "file" },
3257 { "/a/b/c/d", "/a/b/file", "../../file" },
3258 { "/a/b/c/d/e", "/a/b/file", "/a/b/file" },
3259 { "/a/foobar", "/a/foo/file", "../foo/file" },
3260 { "/home/user", "/home/userx", "../userx"},
3261 { "/home/user", "/home/use", "../use"},
3262 { "/home/user", "/home/user", "."},
3263 { "/home", "/home/user", "user"},
3264 };
3265
2/2
✓ Branch 6 → 3 taken 9 times.
✓ Branch 6 → 7 taken 1 time.
10 FOR_EACH_I(i, tests) {
3266 9 char *result = path_relative(tests[i].path, tests[i].cwd);
3267 9 IEXPECT_STREQ(tests[i].result, result);
3268 9 free(result);
3269 }
3270 1 }
3271
3272 1 static void test_path_slice_relative(TestContext *ctx)
3273 {
3274 1 static const char abs[] = "/a/b/c/d";
3275 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c/d/e"), abs);
3276 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/file"), abs);
3277 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c/d"), ".");
3278 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c"), "d");
3279 1 EXPECT_STREQ(path_slice_relative(abs, "/"), "a/b/c/d");
3280 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c"), abs + STRLEN("/a/b/c/"));
3281 1 EXPECT_STREQ(path_slice_relative("/", "/"), "/");
3282 1 EXPECT_STREQ(path_slice_relative("/aa/bb/ccX", "/aa/bb/cc"), "/aa/bb/ccX");
3283 1 }
3284
3285 1 static void test_short_filename_cwd(TestContext *ctx)
3286 {
3287 1 const StringView home = STRING_VIEW("/home/user");
3288 1 char *s = short_filename_cwd("/home/user", "/home/user", home);
3289 1 EXPECT_STREQ(s, ".");
3290 1 free(s);
3291
3292 1 s = short_filename_cwd("/home/use", "/home/user", home);
3293 1 EXPECT_STREQ(s, "../use");
3294 1 free(s);
3295
3296 1 s = short_filename_cwd("/a/b/c/d", "/a/x/y/file", home);
3297 1 EXPECT_STREQ(s, "/a/b/c/d");
3298 1 free(s);
3299
3300 1 s = short_filename_cwd("/home/user/file", "/home/user/cwd", home);
3301 1 EXPECT_STREQ(s, "~/file");
3302 1 free(s);
3303
3304 1 static const char abs[] = "/a/b";
3305 1 static const char cwd[] = "/a/x/c";
3306 1 char *rel = path_relative(abs, cwd);
3307 1 EXPECT_TRUE(strlen(abs) < strlen(rel));
3308 1 EXPECT_STREQ(rel, "../../b");
3309 1 free(rel);
3310 1 s = short_filename_cwd(abs, cwd, home);
3311 1 EXPECT_STREQ(s, "/a/b");
3312 1 free(s);
3313 1 }
3314
3315 1 static void test_short_filename(TestContext *ctx)
3316 {
3317 1 const StringView home = STRING_VIEW("/home/user");
3318 1 static const char rel[] = "test/main.c";
3319 1 char *abs = path_absolute(rel);
3320 1 ASSERT_NONNULL(abs);
3321 1 char *s = short_filename(abs, home);
3322 1 EXPECT_STREQ(s, rel);
3323 1 free(abs);
3324 1 free(s);
3325
3326 1 s = short_filename("/home/user/subdir/file.txt", home);
3327 1 EXPECT_STREQ(s, "~/subdir/file.txt");
3328 1 free(s);
3329
3330 1 s = short_filename("/x/y/z", home);
3331 1 EXPECT_STREQ(s, "/x/y/z");
3332 1 free(s);
3333 1 }
3334
3335 1 static void test_path_absolute(TestContext *ctx)
3336 {
3337 1 char *path = path_absolute("///dev///");
3338 1 EXPECT_STREQ(path, "/dev");
3339 1 free(path);
3340
3341 1 path = path_absolute("///dev///..///dev//");
3342 1 EXPECT_STREQ(path, "/dev");
3343 1 free(path);
3344
3345 1 path = path_absolute("///dev//n0nexist3nt-file");
3346 1 EXPECT_STREQ(path, "/dev/n0nexist3nt-file");
3347 1 free(path);
3348
3349 1 errno = 0;
3350 1 path = path_absolute("/dev/-n0n-existent-dir-[];/file");
3351 1 EXPECT_EQ(errno, ENOENT);
3352 1 EXPECT_STREQ(path, NULL);
3353 1 free(path);
3354
3355 1 path = path_absolute("///../..//./");
3356 1 EXPECT_STREQ(path, "/");
3357 1 free(path);
3358
3359 1 path = path_absolute("/");
3360 1 EXPECT_STREQ(path, "/");
3361 1 free(path);
3362
3363 1 path = path_absolute("");
3364 1 EXPECT_STREQ(path, NULL);
3365 1 free(path);
3366
3367 1 static const char linkpath[] = "./build/test/../test/test-symlink";
3368
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 22 taken 1 time.
1 if (symlink("../gen/platform.mk", linkpath) != 0) {
3369 TEST_FAIL("symlink() failed: %s", strerror(errno));
3370 return;
3371 }
3372 1 test_pass(ctx);
3373
3374 1 path = path_absolute(linkpath);
3375 1 EXPECT_EQ(unlink(linkpath), 0);
3376 1 ASSERT_NONNULL(path);
3377 1 EXPECT_STREQ(path_basename(path), "platform.mk");
3378 1 free(path);
3379 }
3380
3381 1 static void test_path_join(TestContext *ctx)
3382 {
3383 1 char *p = path_join("/", "file");
3384 1 EXPECT_STREQ(p, "/file");
3385 1 free(p);
3386 1 p = path_join("foo", "bar");
3387 1 EXPECT_STREQ(p, "foo/bar");
3388 1 free(p);
3389 1 p = path_join("foo/", "bar");
3390 1 EXPECT_STREQ(p, "foo/bar");
3391 1 free(p);
3392 1 p = path_join("", "bar");
3393 1 EXPECT_STREQ(p, "bar");
3394 1 free(p);
3395 1 p = path_join("foo", "");
3396 1 EXPECT_STREQ(p, "foo");
3397 1 free(p);
3398 1 p = path_join("", "");
3399 1 EXPECT_STREQ(p, "");
3400 1 free(p);
3401 1 p = path_join("/", "");
3402 1 EXPECT_STREQ(p, "/");
3403 1 free(p);
3404 1 p = path_join("/home/user", ".dte");
3405 1 EXPECT_STREQ(p, "/home/user/.dte");
3406 1 free(p);
3407 1 p = path_join("/home/user/", ".dte");
3408 1 EXPECT_STREQ(p, "/home/user/.dte");
3409 1 free(p);
3410 1 p = path_join("/home/user//", ".dte");
3411 1 EXPECT_STREQ(p, "/home/user//.dte");
3412 1 free(p);
3413 1 p = path_join(NULL, NULL);
3414 1 EXPECT_STREQ(p, "");
3415 1 free(p);
3416
3417 1 p = path_join_sv(strview("foo"), strview("bar"), true);
3418 1 EXPECT_STREQ(p, "foo/bar/");
3419 1 free(p);
3420 1 p = path_join_sv(strview("foo"), strview("bar"), false);
3421 1 EXPECT_STREQ(p, "foo/bar");
3422 1 free(p);
3423 1 p = path_join_sv(strview(""), strview(""), true);
3424 1 EXPECT_STREQ(p, "");
3425 1 free(p);
3426 1 p = path_join_sv(strview("/"), strview(""), true);
3427 1 EXPECT_STREQ(p, "/");
3428 1 free(p);
3429 1 p = path_join_sv(strview(""), strview("file"), true);
3430 1 EXPECT_STREQ(p, "file/");
3431 1 free(p);
3432 1 p = path_join_sv(strview(""), strview("file"), false);
3433 1 EXPECT_STREQ(p, "file");
3434 1 free(p);
3435 1 p = path_join_sv(strview(""), strview("file/"), true);
3436 1 EXPECT_STREQ(p, "file/");
3437 1 free(p);
3438 1 p = path_join_sv(strview(NULL), strview(NULL), false);
3439 1 EXPECT_STREQ(p, "");
3440 1 free(p);
3441 1 }
3442
3443 1 static void test_path_parent(TestContext *ctx)
3444 {
3445 1 StringView sv = STRING_VIEW("/a/foo/bar/etc/file");
3446 1 EXPECT_EQ(sv.length, 19);
3447 1 EXPECT_TRUE(path_parent(&sv));
3448 1 EXPECT_EQ(sv.length, 14);
3449 1 EXPECT_TRUE(path_parent(&sv));
3450 1 EXPECT_EQ(sv.length, 10);
3451 1 EXPECT_TRUE(path_parent(&sv));
3452 1 EXPECT_EQ(sv.length, 6);
3453 1 EXPECT_TRUE(path_parent(&sv));
3454 1 EXPECT_EQ(sv.length, 2);
3455 1 EXPECT_TRUE(path_parent(&sv));
3456 1 EXPECT_EQ(sv.length, 1);
3457 1 EXPECT_FALSE(path_parent(&sv));
3458 1 EXPECT_EQ(sv.length, 1);
3459
3460 1 StringView sv2 = STRING_VIEW("/etc/foo/x/y/");
3461 1 EXPECT_EQ(sv2.length, 13);
3462 1 EXPECT_TRUE(path_parent(&sv2));
3463 1 EXPECT_EQ(sv2.length, 10);
3464 1 EXPECT_TRUE(path_parent(&sv2));
3465 1 EXPECT_EQ(sv2.length, 8);
3466 1 EXPECT_TRUE(path_parent(&sv2));
3467 1 EXPECT_EQ(sv2.length, 4);
3468 1 EXPECT_TRUE(path_parent(&sv2));
3469 1 EXPECT_EQ(sv2.length, 1);
3470 1 EXPECT_FALSE(path_parent(&sv2));
3471 1 EXPECT_EQ(sv2.length, 1);
3472 1 }
3473
3474 1 static void test_wrapping_increment(TestContext *ctx)
3475 {
3476 1 EXPECT_EQ(wrapping_increment(0, 1), 0);
3477 1 EXPECT_EQ(wrapping_increment(3, 5), 4);
3478 1 EXPECT_EQ(wrapping_increment(4, 5), 0);
3479 1 EXPECT_EQ(wrapping_increment(0, 5), 1);
3480
3481
2/2
✓ Branch 15 → 13 taken 8 times.
✓ Branch 15 → 16 taken 1 time.
9 for (size_t m = 1; m < 9; m++) {
3482
2/2
✓ Branch 13 → 11 taken 36 times.
✓ Branch 13 → 14 taken 8 times.
44 for (size_t x = 0; x < m; x++) {
3483 36 EXPECT_EQ(wrapping_increment(x, m), (x + 1) % m);
3484 }
3485 }
3486 1 }
3487
3488 1 static void test_wrapping_decrement(TestContext *ctx)
3489 {
3490 1 EXPECT_EQ(wrapping_decrement(0, 1), 0);
3491 1 EXPECT_EQ(wrapping_decrement(1, 450), 0);
3492 1 EXPECT_EQ(wrapping_decrement(0, 450), 449);
3493 1 EXPECT_EQ(wrapping_decrement(449, 450), 448);
3494
3495
2/2
✓ Branch 19 → 11 taken 8 times.
✓ Branch 19 → 20 taken 1 time.
9 for (size_t m = 1; m < 9; m++) {
3496 8 EXPECT_EQ(wrapping_decrement(0, m), m - 1);
3497
2/2
✓ Branch 17 → 14 taken 28 times.
✓ Branch 17 → 18 taken 8 times.
36 for (size_t x = 1; x < m; x++) {
3498 28 EXPECT_EQ(wrapping_decrement(x, m), (x - 1) % m);
3499 }
3500 }
3501 1 }
3502
3503 1 static void test_saturating_increment(TestContext *ctx)
3504 {
3505 1 EXPECT_UINT_EQ(saturating_increment(0, 0), 0);
3506 1 EXPECT_UINT_EQ(saturating_increment(1, 1), 1);
3507 1 EXPECT_UINT_EQ(saturating_increment(6, 7), 7);
3508 1 EXPECT_UINT_EQ(saturating_increment(7, 7), 7);
3509
3510 1 const size_t m = SIZE_MAX;
3511 1 EXPECT_UINT_EQ(saturating_increment(m - 2, m), m - 1);
3512 1 EXPECT_UINT_EQ(saturating_increment(m - 1, m), m);
3513 1 EXPECT_UINT_EQ(saturating_increment(m, m), m);
3514 1 }
3515
3516 1 static void test_saturating_decrement(TestContext *ctx)
3517 {
3518 1 EXPECT_UINT_EQ(saturating_decrement(0), 0);
3519 1 EXPECT_UINT_EQ(saturating_decrement(1), 0);
3520 1 EXPECT_UINT_EQ(saturating_decrement(2), 1);
3521 1 EXPECT_UINT_EQ(saturating_decrement(3), 2);
3522
3523 1 const size_t m = SIZE_MAX;
3524 1 EXPECT_UINT_EQ(saturating_decrement(m), m - 1);
3525 1 }
3526
3527 1 static void test_saturating_subtract(TestContext *ctx)
3528 {
3529 1 EXPECT_UINT_EQ(saturating_subtract(0, 1), 0);
3530 1 EXPECT_UINT_EQ(saturating_subtract(1, 1), 0);
3531 1 EXPECT_UINT_EQ(saturating_subtract(2, 1), 1);
3532 1 EXPECT_UINT_EQ(saturating_subtract(191, 170), 21);
3533
3534 1 const size_t m = SIZE_MAX;
3535 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m - 2), 1);
3536 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m), 0);
3537 1 EXPECT_UINT_EQ(saturating_subtract(m, m), 0);
3538 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 1), 1);
3539 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 2), 2);
3540 1 EXPECT_UINT_EQ(saturating_subtract(0, m), 0);
3541 1 EXPECT_UINT_EQ(saturating_subtract(1, m), 0);
3542 1 EXPECT_UINT_EQ(saturating_subtract(m, 1), m - 1);
3543 1 }
3544
3545 1 static void test_size_multiply_overflows(TestContext *ctx)
3546 {
3547 1 size_t r = 0;
3548 1 EXPECT_FALSE(size_multiply_overflows(10, 20, &r));
3549 1 EXPECT_UINT_EQ(r, 200);
3550 1 EXPECT_FALSE(size_multiply_overflows(0, 0, &r));
3551 1 EXPECT_UINT_EQ(r, 0);
3552 1 EXPECT_FALSE(size_multiply_overflows(1, 0, &r));
3553 1 EXPECT_UINT_EQ(r, 0);
3554 1 EXPECT_FALSE(size_multiply_overflows(0, 1, &r));
3555 1 EXPECT_UINT_EQ(r, 0);
3556 1 EXPECT_FALSE(size_multiply_overflows(0, SIZE_MAX, &r));
3557 1 EXPECT_UINT_EQ(r, 0);
3558 1 EXPECT_FALSE(size_multiply_overflows(SIZE_MAX, 0, &r));
3559 1 EXPECT_UINT_EQ(r, 0);
3560 1 EXPECT_FALSE(size_multiply_overflows(1, SIZE_MAX, &r));
3561 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3562 1 EXPECT_FALSE(size_multiply_overflows(2, SIZE_MAX / 3, &r));
3563 1 EXPECT_UINT_EQ(r, 2 * (SIZE_MAX / 3));
3564 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, 2, &r));
3565 1 EXPECT_TRUE(size_multiply_overflows(2, SIZE_MAX, &r));
3566 1 EXPECT_TRUE(size_multiply_overflows(3, SIZE_MAX / 2, &r));
3567 1 EXPECT_TRUE(size_multiply_overflows(32767, SIZE_MAX, &r));
3568 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX, &r));
3569 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3570 1 }
3571
3572 1 static void test_size_add_overflows(TestContext *ctx)
3573 {
3574 1 size_t r = 0;
3575 1 EXPECT_FALSE(size_add_overflows(10, 20, &r));
3576 1 EXPECT_UINT_EQ(r, 30);
3577 1 EXPECT_FALSE(size_add_overflows(SIZE_MAX, 0, &r));
3578 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3579 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 1, &r));
3580 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 16, &r));
3581 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX, &r));
3582 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3583 1 }
3584
3585 1 static void test_xmul(TestContext *ctx)
3586 {
3587 1 const size_t halfmax = SIZE_MAX / 2;
3588 1 EXPECT_UINT_EQ(xmul(2, halfmax), 2 * halfmax);
3589 1 EXPECT_UINT_EQ(xmul(8, 8), 64);
3590 1 EXPECT_UINT_EQ(xmul(1, SIZE_MAX), SIZE_MAX);
3591 1 EXPECT_UINT_EQ(xmul(2000, 1), 2000);
3592 1 }
3593
3594 1 static void test_xadd(TestContext *ctx)
3595 {
3596 1 const size_t max = SIZE_MAX;
3597 1 EXPECT_UINT_EQ(xadd(max - 1, 1), max);
3598 1 EXPECT_UINT_EQ(xadd(8, 8), 16);
3599 1 EXPECT_UINT_EQ(xadd(0, 0), 0);
3600
3601 1 EXPECT_UINT_EQ(xadd3(max - 3, 2, 1), max);
3602 1 EXPECT_UINT_EQ(xadd3(11, 9, 5071), 5091);
3603 1 EXPECT_UINT_EQ(xadd3(0, 0, 0), 0);
3604 1 }
3605
3606 1 static void test_mem_intern(TestContext *ctx)
3607 {
3608 1 const char *ptrs[256];
3609 1 char str[8];
3610
2/2
✓ Branch 6 → 3 taken 256 times.
✓ Branch 6 → 7 taken 1 time.
257 for (unsigned int i = 0; i < ARRAYLEN(ptrs); i++) {
3611 256 size_t len = buf_uint_to_str(i, str);
3612 256 ptrs[i] = mem_intern(str, len);
3613 }
3614
3615 1 EXPECT_STREQ(ptrs[0], "0");
3616 1 EXPECT_STREQ(ptrs[1], "1");
3617 1 EXPECT_STREQ(ptrs[101], "101");
3618 1 EXPECT_STREQ(ptrs[255], "255");
3619
3620
2/2
✓ Branch 16 → 12 taken 256 times.
✓ Branch 16 → 17 taken 1 time.
257 for (unsigned int i = 0; i < ARRAYLEN(ptrs); i++) {
3621 256 size_t len = buf_uint_to_str(i, str);
3622 256 const char *ptr = mem_intern(str, len);
3623 256 EXPECT_PTREQ(ptr, ptrs[i]);
3624 }
3625 1 }
3626
3627 1 static void test_read_file(TestContext *ctx)
3628 {
3629 1 char *buf = NULL;
3630 1 ASSERT_EQ(read_file("/dev/null", &buf, 64), 0);
3631 1 ASSERT_NONNULL(buf);
3632 1 EXPECT_UINT_EQ((unsigned char)buf[0], '\0');
3633 1 free(buf);
3634
3635 1 buf = NULL;
3636 1 errno = 0;
3637 1 EXPECT_EQ(read_file("test/data/", &buf, 64), -1);
3638 1 EXPECT_EQ(errno, EISDIR);
3639 1 EXPECT_NULL(buf);
3640 1 free(buf);
3641
3642 1 buf = NULL;
3643 1 errno = 0;
3644 1 EXPECT_EQ(read_file("test/data/3lines.txt", &buf, 1), -1);
3645 1 EXPECT_EQ(errno, EFBIG);
3646 1 EXPECT_NULL(buf);
3647 1 free(buf);
3648
3649 1 ssize_t size = read_file("test/data/3lines.txt", &buf, 512);
3650 1 EXPECT_EQ(size, 26);
3651 1 ASSERT_NONNULL(buf);
3652 1 size_t pos = 0;
3653 1 const char *line = buf_next_line(buf, &pos, size);
3654 1 EXPECT_STREQ(line, "line #1");
3655 1 EXPECT_EQ(pos, 8);
3656 1 line = buf_next_line(buf, &pos, size);
3657 1 EXPECT_STREQ(line, " line #2");
3658 1 EXPECT_EQ(pos, 17);
3659 1 line = buf_next_line(buf, &pos, size);
3660 1 EXPECT_STREQ(line, " line #3");
3661 1 EXPECT_EQ(pos, 26);
3662 1 free(buf);
3663 1 }
3664
3665 1 static void test_xfopen(TestContext *ctx)
3666 {
3667 1 static const char modes[][4] = {"a", "a+", "r", "r+", "w", "w+"};
3668
2/2
✓ Branch 10 → 3 taken 6 times.
✓ Branch 10 → 11 taken 1 time.
7 FOR_EACH_I(i, modes) {
3669 6 FILE *f = xfopen("/dev/null", modes[i], O_CLOEXEC, 0666);
3670 6 IEXPECT_TRUE(f && fclose(f) == 0);
3671 }
3672 1 }
3673
3674 1 static void test_xstdio(TestContext *ctx)
3675 {
3676 1 FILE *f = xfopen("/dev/null", "r+", O_CLOEXEC, 0666);
3677 1 ASSERT_NONNULL(f);
3678
3679 1 char buf[16];
3680 1 EXPECT_NULL(xfgets(buf, sizeof(buf), f));
3681 1 EXPECT_NE(xfputs("str", f), EOF);
3682 1 EXPECT_EQ(xfputc(' ', f), ' ');
3683 1 EXPECT_EQ(xfprintf(f, "fmt %d", 42), 6);
3684 1 EXPECT_EQ(xfflush(f), 0);
3685 1 EXPECT_EQ(fclose(f), 0);
3686 1 }
3687
3688 1 static void test_fd_set_cloexec(TestContext *ctx)
3689 {
3690 1 int fd = xopen("/dev/null", O_RDONLY, 0);
3691 1 ASSERT_TRUE(fd >= 0);
3692 1 int flags = fcntl(fd, F_GETFD);
3693 1 EXPECT_TRUE(flags >= 0);
3694 1 EXPECT_EQ(flags & FD_CLOEXEC, 0);
3695
3696 1 EXPECT_TRUE(fd_set_cloexec(fd, true));
3697 1 flags = fcntl(fd, F_GETFD);
3698 1 EXPECT_TRUE(flags > 0);
3699 1 EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
3700
3701 // This set of tests is repeated twice, in order to check the special
3702 // case where the F_SETFD operation can be omitted because FD_CLOEXEC
3703 // was already set as requested
3704
2/2
✓ Branch 19 → 13 taken 2 times.
✓ Branch 19 → 20 taken 1 time.
3 for (size_t i = 0; i < 2; i++) {
3705 2 IEXPECT_TRUE(fd_set_cloexec(fd, false));
3706 2 flags = fcntl(fd, F_GETFD);
3707 2 IEXPECT_TRUE(flags >= 0);
3708 2 IEXPECT_EQ(flags & FD_CLOEXEC, 0);
3709 }
3710
3711 1 xclose(fd);
3712 1 }
3713
3714 1 static void test_fd_set_nonblock(TestContext *ctx)
3715 {
3716 1 int fd = xopen("/dev/null", O_RDONLY, 0);
3717 1 ASSERT_TRUE(fd >= 0);
3718 1 int flags = fcntl(fd, F_GETFL);
3719 1 EXPECT_TRUE(flags >= 0);
3720 1 EXPECT_EQ(flags & O_NONBLOCK, 0);
3721
3722 1 EXPECT_TRUE(fd_set_nonblock(fd, true));
3723 1 flags = fcntl(fd, F_GETFL);
3724 1 EXPECT_TRUE(flags > 0);
3725 1 EXPECT_EQ(flags & O_NONBLOCK, O_NONBLOCK);
3726
3727
2/2
✓ Branch 19 → 13 taken 2 times.
✓ Branch 19 → 20 taken 1 time.
3 for (size_t i = 0; i < 2; i++) {
3728 2 IEXPECT_TRUE(fd_set_nonblock(fd, false));
3729 2 flags = fcntl(fd, F_GETFL);
3730 2 IEXPECT_TRUE(flags >= 0);
3731 2 IEXPECT_EQ(flags & O_NONBLOCK, 0);
3732 }
3733
3734 1 xclose(fd);
3735 1 }
3736
3737 1 static void test_fork_exec(TestContext *ctx)
3738 {
3739 1 int fd[3];
3740 1 fd[0] = xopen("/dev/null", O_RDWR | O_CLOEXEC, 0);
3741 1 ASSERT_TRUE(fd[0] > 0);
3742 1 fd[1] = fd[0];
3743 1 fd[2] = fd[0];
3744
3745 1 const char *argv[] = {"sh", "-c", "exit 95", NULL};
3746 1 pid_t pid = fork_exec(argv, fd, 0, 0, true);
3747 1 ASSERT_NE(pid, -1);
3748 1 int r = wait_child(pid);
3749 1 EXPECT_EQ(r, 95);
3750
3751 1 argv[0] = "sleep";
3752 1 argv[1] = "5";
3753 1 argv[2] = NULL;
3754 1 pid = fork_exec(argv, fd, 0, 0, true);
3755 1 ASSERT_NE(pid, -1);
3756 1 EXPECT_EQ(kill(pid, SIGINT), 0);
3757 1 r = wait_child(pid);
3758 1 EXPECT_TRUE(r >= 256);
3759 1 EXPECT_EQ(r >> 8, SIGINT);
3760
3761 1 EXPECT_EQ(xclose(fd[0]), 0);
3762 1 }
3763
3764 1 static void test_xmemmem(TestContext *ctx)
3765 {
3766 1 static const char haystack[] = "finding a needle in a haystack";
3767 1 const char *needle = xmemmem(haystack, sizeof(haystack), STRN("needle"));
3768 1 ASSERT_NONNULL(needle);
3769 1 EXPECT_PTREQ(needle, haystack + 10);
3770
3771 1 needle = xmemmem(haystack, sizeof(haystack), "\0", 1);
3772 1 ASSERT_NONNULL(needle);
3773 1 EXPECT_PTREQ(needle, haystack + sizeof(haystack) - 1);
3774
3775 1 needle = xmemmem(haystack, sizeof(haystack) - 1, "\0", 1);
3776 1 EXPECT_NULL(needle);
3777
3778 1 needle = xmemmem(haystack, sizeof(haystack), STRN("in "));
3779 1 ASSERT_NONNULL(needle);
3780 1 EXPECT_PTREQ(needle, haystack + 17);
3781
3782 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystack"));
3783 1 ASSERT_NONNULL(needle);
3784 1 EXPECT_PTREQ(needle, haystack + 22);
3785
3786 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystacks"));
3787 1 EXPECT_NULL(needle);
3788
3789 1 needle = xmemmem(haystack, sizeof(haystack), STRN("haystacks"));
3790 1 EXPECT_NULL(needle);
3791 1 }
3792
3793 1 static void test_xmemrchr(TestContext *ctx)
3794 {
3795 1 static const char str[] = "123456789 abcdefedcba 987654321";
3796 1 EXPECT_PTREQ(xmemrchr(NULL, '1', 0), NULL);
3797 1 EXPECT_PTREQ(xmemrchr(str, '9', sizeof(str) - 1), str + 22);
3798 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 1), str + sizeof(str) - 2);
3799 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 2), str);
3800 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str)), str + sizeof(str) - 1);
3801 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str) - 1), NULL);
3802 1 EXPECT_PTREQ(xmemrchr(str, 'z', sizeof(str) - 1), NULL);
3803 1 }
3804
3805 1 static void test_str_to_bitflags(TestContext *ctx)
3806 {
3807 1 static const char strs[][8] = {"zero", "one", "two", "three"};
3808 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("one,three", strs, true), 1 << 1 | 1 << 3);
3809 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("two,invalid,zero", strs, true), 1 << 2 | 1 << 0);
3810 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("two,invalid,zero", strs, false), 0);
3811 1 }
3812
3813 1 static void test_log_level_from_str(TestContext *ctx)
3814 {
3815 1 EXPECT_EQ(log_level_from_str("none"), LOG_LEVEL_NONE);
3816 1 EXPECT_EQ(log_level_from_str("crit"), LOG_LEVEL_CRITICAL);
3817 1 EXPECT_EQ(log_level_from_str("error"), LOG_LEVEL_ERROR);
3818 1 EXPECT_EQ(log_level_from_str("warning"), LOG_LEVEL_WARNING);
3819 1 EXPECT_EQ(log_level_from_str("notice"), LOG_LEVEL_NOTICE);
3820 1 EXPECT_EQ(log_level_from_str("info"), LOG_LEVEL_INFO);
3821 1 EXPECT_EQ(log_level_from_str("debug"), LOG_LEVEL_DEBUG);
3822 1 EXPECT_EQ(log_level_from_str("trace"), LOG_LEVEL_TRACE);
3823
3824 1 EXPECT_EQ(log_level_from_str("xyz"), LOG_LEVEL_INVALID);
3825 1 EXPECT_EQ(log_level_from_str(" "), LOG_LEVEL_INVALID);
3826 1 EXPECT_EQ(log_level_from_str("warn"), LOG_LEVEL_INVALID);
3827 1 EXPECT_EQ(log_level_from_str("errors"), LOG_LEVEL_INVALID);
3828
3829 1 LogLevel default_level = log_level_default();
3830 1 EXPECT_EQ(log_level_from_str(""), default_level);
3831 1 EXPECT_EQ(log_level_from_str(NULL), default_level);
3832 1 }
3833
3834 1 static void test_log_level_to_str(TestContext *ctx)
3835 {
3836 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NONE), "none");
3837 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_CRITICAL), "crit");
3838 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_ERROR), "error");
3839 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_WARNING), "warning");
3840 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NOTICE), "notice");
3841 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_INFO), "info");
3842 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_DEBUG), "debug");
3843 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_TRACE), "trace");
3844 1 }
3845
3846 1 static void test_timespec_subtract(TestContext *ctx)
3847 {
3848 1 struct timespec a = {.tv_sec = 3, .tv_nsec = 5497};
3849 1 struct timespec b = {.tv_sec = 1, .tv_nsec = NS_PER_SECOND - 1};
3850 1 struct timespec r = timespec_subtract(&a, &b);
3851 1 EXPECT_EQ(r.tv_sec, 1);
3852 1 EXPECT_EQ(r.tv_nsec, 5498);
3853
3854 1 b.tv_nsec = 501;
3855 1 r = timespec_subtract(&a, &b);
3856 1 EXPECT_EQ(r.tv_sec, 2);
3857 1 EXPECT_EQ(r.tv_nsec, 4996);
3858 1 }
3859
3860 1 static void test_timespec_to_str(TestContext *ctx)
3861 {
3862 1 char buf[TIME_STR_BUFSIZE] = "";
3863 1 struct timespec ts = {.tv_sec = 0};
3864 1 EXPECT_TRUE(timespecs_equal(&ts, &ts));
3865
3866 1 errno = 0;
3867 1 ts.tv_nsec = NS_PER_SECOND;
3868 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3869 1 EXPECT_EQ(errno, EINVAL);
3870
3871 1 errno = 0;
3872 1 ts.tv_nsec = -1;
3873 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3874 1 EXPECT_EQ(errno, EINVAL);
3875
3876 // Note: $TZ is set to "UTC" in test_init()
3877 1 ts.tv_sec = 4321;
3878 1 ts.tv_nsec = 9876;
3879 1 const char *r = timespec_to_str(&ts, buf);
3880 1 EXPECT_STREQ(r, "1970-01-01 01:12:01.9876 +0000");
3881 1 EXPECT_PTREQ(r, buf);
3882
3883 1 ts.tv_sec = -1;
3884 1 ts.tv_nsec = NS_PER_SECOND - 1;
3885 1 r = timespec_to_str(&ts, buf);
3886 1 EXPECT_STREQ(r, "1969-12-31 23:59:59.999999999 +0000");
3887 1 }
3888
3889 1 static void test_progname(TestContext *ctx)
3890 {
3891 1 const char *const args[] = {"arg0", "", NULL};
3892 1 char **arg0 = (char**)args;
3893 1 char **arg1 = arg0 + 1;
3894 1 char **arg2 = arg0 + 2;
3895 1 EXPECT_STREQ(progname(1, arg0, "1"), "arg0");
3896 1 EXPECT_STREQ(progname(1, NULL, "2"), "2");
3897 1 EXPECT_STREQ(progname(0, arg0, "3"), "3");
3898 1 EXPECT_STREQ(progname(1, arg1, "4"), "4");
3899 1 EXPECT_STREQ(progname(1, arg2, "5"), "5");
3900 1 EXPECT_STREQ(progname(0, NULL, NULL), "_PROG_");
3901 1 }
3902
3903 static const TestEntry tests[] = {
3904 TEST(test_util_macros),
3905 TEST(test_is_power_of_2),
3906 TEST(test_xmalloc),
3907 TEST(test_xstreq),
3908 TEST(test_xstrrchr),
3909 TEST(test_xmempcpy),
3910 TEST(test_str_has_strn_prefix),
3911 TEST(test_str_has_prefix),
3912 TEST(test_str_has_suffix),
3913 TEST(test_hex_decode),
3914 TEST(test_hex_encode_byte),
3915 TEST(test_ascii),
3916 TEST(test_mem_equal),
3917 TEST(test_mem_equal_icase),
3918 TEST(test_base64_decode),
3919 TEST(test_base64_encode_block),
3920 TEST(test_base64_encode_final),
3921 TEST(test_string),
3922 TEST(test_string_view),
3923 TEST(test_strview_has_suffix),
3924 TEST(test_strview_remove_matching),
3925 TEST(test_get_delim),
3926 TEST(test_get_delim_str),
3927 TEST(test_str_replace_byte),
3928 TEST(test_strn_replace_byte),
3929 TEST(test_string_array_concat),
3930 TEST(test_size_str_width),
3931 TEST(test_buf_parse_uintmax),
3932 TEST(test_buf_parse_ulong),
3933 TEST(test_buf_parse_size),
3934 TEST(test_buf_parse_hex_uint),
3935 TEST(test_str_to_int),
3936 TEST(test_str_to_size),
3937 TEST(test_str_to_filepos),
3938 TEST(test_parse_file_line_col),
3939 TEST(test_buf_umax_to_hex_str),
3940 TEST(test_parse_filesize),
3941 TEST(test_umax_to_str),
3942 TEST(test_uint_to_str),
3943 TEST(test_ulong_to_str),
3944 TEST(test_buf_umax_to_str),
3945 TEST(test_buf_uint_to_str),
3946 TEST(test_buf_u8_to_str),
3947 TEST(test_file_permissions_to_str),
3948 TEST(test_human_readable_size),
3949 TEST(test_filesize_to_str),
3950 TEST(test_filesize_to_str_precise),
3951 TEST(test_u_char_size),
3952 TEST(test_u_char_width),
3953 TEST(test_u_to_lower),
3954 TEST(test_u_to_upper),
3955 TEST(test_u_is_lower),
3956 TEST(test_u_is_upper),
3957 TEST(test_u_is_ascii_upper),
3958 TEST(test_u_is_cntrl),
3959 TEST(test_u_is_unicode),
3960 TEST(test_u_is_zero_width),
3961 TEST(test_u_is_special_whitespace),
3962 TEST(test_u_is_unprintable),
3963 TEST(test_u_str_width),
3964 TEST(test_u_set_char_raw),
3965 TEST(test_u_set_char),
3966 TEST(test_u_make_printable),
3967 TEST(test_u_get_char),
3968 TEST(test_u_prev_char),
3969 TEST(test_u_skip_chars),
3970 TEST(test_ptr_array),
3971 TEST(test_ptr_array_move),
3972 TEST(test_ptr_array_insert),
3973 TEST(test_list),
3974 TEST(test_hashmap),
3975 TEST(test_hashset),
3976 TEST(test_intmap),
3977 TEST(test_next_multiple),
3978 TEST(test_next_pow2),
3979 TEST(test_popcount),
3980 TEST(test_ctz),
3981 TEST(test_ffs),
3982 TEST(test_lsbit),
3983 TEST(test_msbit),
3984 TEST(test_clz),
3985 TEST(test_umax_bitwidth),
3986 TEST(test_umax_count_base16_digits),
3987 TEST(test_path_dirname_basename),
3988 TEST(test_path_relative),
3989 TEST(test_path_slice_relative),
3990 TEST(test_short_filename_cwd),
3991 TEST(test_short_filename),
3992 TEST(test_path_absolute),
3993 TEST(test_path_join),
3994 TEST(test_path_parent),
3995 TEST(test_wrapping_increment),
3996 TEST(test_wrapping_decrement),
3997 TEST(test_saturating_increment),
3998 TEST(test_saturating_decrement),
3999 TEST(test_saturating_subtract),
4000 TEST(test_size_multiply_overflows),
4001 TEST(test_size_add_overflows),
4002 TEST(test_xmul),
4003 TEST(test_xadd),
4004 TEST(test_mem_intern),
4005 TEST(test_read_file),
4006 TEST(test_xfopen),
4007 TEST(test_xstdio),
4008 TEST(test_fd_set_cloexec),
4009 TEST(test_fd_set_nonblock),
4010 TEST(test_fork_exec),
4011 TEST(test_xmemmem),
4012 TEST(test_xmemrchr),
4013 TEST(test_str_to_bitflags),
4014 TEST(test_log_level_from_str),
4015 TEST(test_log_level_to_str),
4016 TEST(test_timespec_subtract),
4017 TEST(test_timespec_to_str),
4018 TEST(test_progname),
4019 };
4020
4021 const TestGroup util_tests = TEST_GROUP(tests);
4022