dte test coverage


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

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