dte test coverage


Directory: ./
File: test/util.c
Date: 2025-07-03 15:44:24
Exec Total Coverage
Lines: 2924 2925 99.9%
Functions: 112 112 100.0%
Branches: 97 98 99.0%

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