dte test coverage


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

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