dte test coverage


Directory: ./
File: test/util.c
Date: 2026-01-27 12:16:02
Coverage Exec Excl Total
Lines: 99.9% 2993 1 2995
Functions: 100.0% 115 0 115
Branches: 99.0% 101 0 102

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