dte test coverage


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

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