dte test coverage


Directory: ./
File: test/util.c
Date: 2025-07-10 06:26:10
Exec Total Coverage
Lines: 2948 2949 99.9%
Functions: 113 113 100.0%
Branches: 99 100 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 >> 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 i = 1; i < 70; i++) {
3045 69 uint32_t lsb = u32_lsbit(i);
3046 69 IEXPECT_TRUE(IS_POWER_OF_2(lsb));
3047 69 IEXPECT_TRUE(lsb & i);
3048 }
3049 1 }
3050
3051 1 static void test_msbit(TestContext *ctx)
3052 {
3053 1 EXPECT_EQ(size_msbit(0), 0);
3054 1 EXPECT_EQ(size_msbit(1), 1);
3055 1 EXPECT_EQ(size_msbit(2), 2);
3056 1 EXPECT_EQ(size_msbit(3), 2);
3057 1 EXPECT_EQ(size_msbit(4), 4);
3058 1 EXPECT_EQ(size_msbit(7), 4);
3059 1 EXPECT_EQ(size_msbit(8), 8);
3060 1 EXPECT_EQ(size_msbit(255), 128);
3061 1 EXPECT_EQ(size_msbit(256), 256);
3062 1 EXPECT_UINT_EQ(size_msbit(0x1FFFu), 0x1000u);
3063 1 EXPECT_UINT_EQ(size_msbit(0xFFFFu), 0x8000u);
3064
3065 1 const size_t max = SIZE_MAX;
3066 1 const size_t max_pow2 = ~(max >> 1);
3067 1 EXPECT_UINT_EQ(size_msbit(max), max_pow2);
3068 1 EXPECT_UINT_EQ(size_msbit(max - 1), max_pow2);
3069 1 EXPECT_UINT_EQ(size_msbit(max_pow2), max_pow2);
3070 1 EXPECT_UINT_EQ(size_msbit(max_pow2 - 1), max_pow2 >> 1);
3071 1 EXPECT_UINT_EQ(size_msbit(max_pow2 + 1), max_pow2);
3072
3073
2/2
✓ Branch 0 (25→19) taken 69 times.
✓ Branch 1 (25→26) taken 1 times.
70 for (size_t i = 1; i < 70; i++) {
3074 69 size_t msb = size_msbit(i);
3075 69 IEXPECT_TRUE(IS_POWER_OF_2(msb));
3076 69 IEXPECT_TRUE(msb & i);
3077 }
3078 1 }
3079
3080 1 static void test_clz(TestContext *ctx)
3081 {
3082 1 EXPECT_EQ(u64_clz(1), 63);
3083 1 EXPECT_EQ(u64_clz(2), 62);
3084 1 EXPECT_EQ(u64_clz(3), 62);
3085 1 EXPECT_EQ(u64_clz(1ULL << 10), 53);
3086 1 EXPECT_EQ(u64_clz(1ULL << 55), 8);
3087 1 EXPECT_EQ(u64_clz(1ULL << 63), 0);
3088 1 EXPECT_EQ(u64_clz(UINT64_MAX), 0);
3089 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 1), 1);
3090 1 EXPECT_EQ(u64_clz(UINT64_MAX >> 3), 3);
3091 1 }
3092
3093 1 static void test_umax_bitwidth(TestContext *ctx)
3094 {
3095 1 EXPECT_EQ(umax_bitwidth(0), 0);
3096 1 EXPECT_EQ(umax_bitwidth(1), 1);
3097 1 EXPECT_EQ(umax_bitwidth(2), 2);
3098 1 EXPECT_EQ(umax_bitwidth(3), 2);
3099 1 EXPECT_EQ(umax_bitwidth(0x80), 8);
3100 1 EXPECT_EQ(umax_bitwidth(0xFF), 8);
3101 1 EXPECT_EQ(umax_bitwidth(0x10081), 17);
3102 1 EXPECT_EQ(umax_bitwidth(1ULL << 62), 63);
3103 1 EXPECT_EQ(umax_bitwidth(0xFFFFFFFFFFFFFFFFULL), 64);
3104 1 }
3105
3106 1 static void test_umax_count_base16_digits(TestContext *ctx)
3107 {
3108 1 EXPECT_EQ(umax_count_base16_digits(0x0), 1);
3109 1 EXPECT_EQ(umax_count_base16_digits(0x1), 1);
3110 1 EXPECT_EQ(umax_count_base16_digits(0x2), 1);
3111 1 EXPECT_EQ(umax_count_base16_digits(0x3), 1);
3112 1 EXPECT_EQ(umax_count_base16_digits(0x4), 1);
3113 1 EXPECT_EQ(umax_count_base16_digits(0x5), 1);
3114 1 EXPECT_EQ(umax_count_base16_digits(0x6), 1);
3115 1 EXPECT_EQ(umax_count_base16_digits(0x7), 1);
3116 1 EXPECT_EQ(umax_count_base16_digits(0x8), 1);
3117 1 EXPECT_EQ(umax_count_base16_digits(0x9), 1);
3118 1 EXPECT_EQ(umax_count_base16_digits(0xA), 1);
3119 1 EXPECT_EQ(umax_count_base16_digits(0xB), 1);
3120 1 EXPECT_EQ(umax_count_base16_digits(0xF), 1);
3121 1 EXPECT_EQ(umax_count_base16_digits(0x10), 2);
3122 1 EXPECT_EQ(umax_count_base16_digits(0x111), 3);
3123 1 EXPECT_EQ(umax_count_base16_digits(0xFF11), 4);
3124 1 EXPECT_EQ(umax_count_base16_digits(0x80000000ULL), 8);
3125 1 EXPECT_EQ(umax_count_base16_digits(0x800000000ULL), 9);
3126 1 EXPECT_EQ(umax_count_base16_digits(0X98EA412F0ULL), 9);
3127 1 EXPECT_EQ(umax_count_base16_digits(0x8000000000000000ULL), 16);
3128 1 EXPECT_EQ(umax_count_base16_digits(0xFFFFFFFFFFFFFFFFULL), 16);
3129 1 }
3130
3131 1 static void test_path_dirname_basename(TestContext *ctx)
3132 {
3133 1 static const struct {
3134 const char *path;
3135 const char *dirname;
3136 const char *basename;
3137 } tests[] = {
3138 {"/home/user/example.txt", "/home/user", "example.txt"},
3139 {"./../dir/example.txt", "./../dir", "example.txt"},
3140 {"/usr/bin/", "/usr/bin", ""},
3141 {"example.txt", ".", "example.txt"},
3142 {"/usr/lib", "/usr", "lib"},
3143 {"/usr", "/", "usr"},
3144 {"usr", ".", "usr"},
3145 {"/", "/", ""},
3146 {".", ".", "."},
3147 {"..", ".", ".."},
3148 {"", ".", ""},
3149 };
3150
2/2
✓ Branch 0 (7→3) taken 11 times.
✓ Branch 1 (7→8) taken 1 times.
12 FOR_EACH_I(i, tests) {
3151 11 char *dir = path_dirname(tests[i].path);
3152 11 IEXPECT_STREQ(dir, tests[i].dirname);
3153 11 free(dir);
3154 11 IEXPECT_STREQ(path_basename(tests[i].path), tests[i].basename);
3155 }
3156 1 }
3157
3158 1 static void test_path_relative(TestContext *ctx)
3159 {
3160 1 static const struct {
3161 const char *cwd;
3162 const char *path;
3163 const char *result;
3164 } tests[] = { // NOTE: at most 2 ".." components allowed in relative name
3165 { "/", "/", "/" },
3166 { "/", "/file", "file" },
3167 { "/a/b/c/d", "/a/b/file", "../../file" },
3168 { "/a/b/c/d/e", "/a/b/file", "/a/b/file" },
3169 { "/a/foobar", "/a/foo/file", "../foo/file" },
3170 { "/home/user", "/home/userx", "../userx"},
3171 { "/home/user", "/home/use", "../use"},
3172 { "/home/user", "/home/user", "."},
3173 { "/home", "/home/user", "user"},
3174 };
3175
2/2
✓ Branch 0 (6→3) taken 9 times.
✓ Branch 1 (6→7) taken 1 times.
10 FOR_EACH_I(i, tests) {
3176 9 char *result = path_relative(tests[i].path, tests[i].cwd);
3177 9 IEXPECT_STREQ(tests[i].result, result);
3178 9 free(result);
3179 }
3180 1 }
3181
3182 1 static void test_path_slice_relative(TestContext *ctx)
3183 {
3184 1 static const char abs[] = "/a/b/c/d";
3185 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c/d/e"), abs);
3186 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/file"), abs);
3187 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c/d"), ".");
3188 1 EXPECT_STREQ(path_slice_relative(abs, "/a/b/c"), "d");
3189 1 EXPECT_STREQ(path_slice_relative(abs, "/"), "a/b/c/d");
3190 1 EXPECT_PTREQ(path_slice_relative(abs, "/a/b/c"), abs + STRLEN("/a/b/c/"));
3191 1 EXPECT_STREQ(path_slice_relative("/", "/"), "/");
3192 1 EXPECT_STREQ(path_slice_relative("/aa/bb/ccX", "/aa/bb/cc"), "/aa/bb/ccX");
3193 1 }
3194
3195 1 static void test_short_filename_cwd(TestContext *ctx)
3196 {
3197 1 const StringView home = STRING_VIEW("/home/user");
3198 1 char *s = short_filename_cwd("/home/user", "/home/user", &home);
3199 1 EXPECT_STREQ(s, ".");
3200 1 free(s);
3201
3202 1 s = short_filename_cwd("/home/use", "/home/user", &home);
3203 1 EXPECT_STREQ(s, "../use");
3204 1 free(s);
3205
3206 1 s = short_filename_cwd("/a/b/c/d", "/a/x/y/file", &home);
3207 1 EXPECT_STREQ(s, "/a/b/c/d");
3208 1 free(s);
3209
3210 1 s = short_filename_cwd("/home/user/file", "/home/user/cwd", &home);
3211 1 EXPECT_STREQ(s, "~/file");
3212 1 free(s);
3213
3214 1 static const char abs[] = "/a/b";
3215 1 static const char cwd[] = "/a/x/c";
3216 1 char *rel = path_relative(abs, cwd);
3217 1 EXPECT_TRUE(strlen(abs) < strlen(rel));
3218 1 EXPECT_STREQ(rel, "../../b");
3219 1 free(rel);
3220 1 s = short_filename_cwd(abs, cwd, &home);
3221 1 EXPECT_STREQ(s, "/a/b");
3222 1 free(s);
3223 1 }
3224
3225 1 static void test_short_filename(TestContext *ctx)
3226 {
3227 1 const StringView home = STRING_VIEW("/home/user");
3228 1 static const char rel[] = "test/main.c";
3229 1 char *abs = path_absolute(rel);
3230 1 ASSERT_NONNULL(abs);
3231 1 char *s = short_filename(abs, &home);
3232 1 EXPECT_STREQ(s, rel);
3233 1 free(abs);
3234 1 free(s);
3235
3236 1 s = short_filename("/home/user/subdir/file.txt", &home);
3237 1 EXPECT_STREQ(s, "~/subdir/file.txt");
3238 1 free(s);
3239
3240 1 s = short_filename("/x/y/z", &home);
3241 1 EXPECT_STREQ(s, "/x/y/z");
3242 1 free(s);
3243 1 }
3244
3245 1 static void test_path_absolute(TestContext *ctx)
3246 {
3247 1 char *path = path_absolute("///dev///");
3248 1 EXPECT_STREQ(path, "/dev");
3249 1 free(path);
3250
3251 1 path = path_absolute("///dev///..///dev//");
3252 1 EXPECT_STREQ(path, "/dev");
3253 1 free(path);
3254
3255 1 path = path_absolute("///dev//n0nexist3nt-file");
3256 1 EXPECT_STREQ(path, "/dev/n0nexist3nt-file");
3257 1 free(path);
3258
3259 1 errno = 0;
3260 1 path = path_absolute("/dev/-n0n-existent-dir-[];/file");
3261 1 EXPECT_EQ(errno, ENOENT);
3262 1 EXPECT_STREQ(path, NULL);
3263 1 free(path);
3264
3265 1 path = path_absolute("///../..//./");
3266 1 EXPECT_STREQ(path, "/");
3267 1 free(path);
3268
3269 1 path = path_absolute("/");
3270 1 EXPECT_STREQ(path, "/");
3271 1 free(path);
3272
3273 1 path = path_absolute("");
3274 1 EXPECT_STREQ(path, NULL);
3275 1 free(path);
3276
3277 1 static const char linkpath[] = "./build/test/../test/test-symlink";
3278
1/2
✗ Branch 0 (18→19) not taken.
✓ Branch 1 (18→22) taken 1 times.
1 if (symlink("../gen/platform.mk", linkpath) != 0) {
3279 TEST_FAIL("symlink() failed: %s", strerror(errno));
3280 return;
3281 }
3282 1 test_pass(ctx);
3283
3284 1 path = path_absolute(linkpath);
3285 1 EXPECT_EQ(unlink(linkpath), 0);
3286 1 ASSERT_NONNULL(path);
3287 1 EXPECT_STREQ(path_basename(path), "platform.mk");
3288 1 free(path);
3289 }
3290
3291 1 static void test_path_join(TestContext *ctx)
3292 {
3293 1 char *p = path_join("/", "file");
3294 1 EXPECT_STREQ(p, "/file");
3295 1 free(p);
3296 1 p = path_join("foo", "bar");
3297 1 EXPECT_STREQ(p, "foo/bar");
3298 1 free(p);
3299 1 p = path_join("foo/", "bar");
3300 1 EXPECT_STREQ(p, "foo/bar");
3301 1 free(p);
3302 1 p = path_join("", "bar");
3303 1 EXPECT_STREQ(p, "bar");
3304 1 free(p);
3305 1 p = path_join("foo", "");
3306 1 EXPECT_STREQ(p, "foo");
3307 1 free(p);
3308 1 p = path_join("", "");
3309 1 EXPECT_STREQ(p, "");
3310 1 free(p);
3311 1 p = path_join("/", "");
3312 1 EXPECT_STREQ(p, "/");
3313 1 free(p);
3314 1 p = path_join("/home/user", ".dte");
3315 1 EXPECT_STREQ(p, "/home/user/.dte");
3316 1 free(p);
3317 1 p = path_join("/home/user/", ".dte");
3318 1 EXPECT_STREQ(p, "/home/user/.dte");
3319 1 free(p);
3320 1 p = path_join("/home/user//", ".dte");
3321 1 EXPECT_STREQ(p, "/home/user//.dte");
3322 1 free(p);
3323
3324 1 p = path_joinx("foo", "bar", true);
3325 1 EXPECT_STREQ(p, "foo/bar/");
3326 1 free(p);
3327 1 p = path_joinx("foo", "bar", false);
3328 1 EXPECT_STREQ(p, "foo/bar");
3329 1 free(p);
3330 1 p = path_joinx("", "", true);
3331 1 EXPECT_STREQ(p, "");
3332 1 free(p);
3333 1 p = path_joinx("/", "", true);
3334 1 EXPECT_STREQ(p, "/");
3335 1 free(p);
3336 1 p = path_joinx("", "file", true);
3337 1 EXPECT_STREQ(p, "file/");
3338 1 free(p);
3339 1 p = path_joinx("", "file", false);
3340 1 EXPECT_STREQ(p, "file");
3341 1 free(p);
3342 1 p = path_joinx("", "file/", true);
3343 1 EXPECT_STREQ(p, "file/");
3344 1 free(p);
3345 1 }
3346
3347 1 static void test_path_parent(TestContext *ctx)
3348 {
3349 1 StringView sv = STRING_VIEW("/a/foo/bar/etc/file");
3350 1 EXPECT_EQ(sv.length, 19);
3351 1 EXPECT_TRUE(path_parent(&sv));
3352 1 EXPECT_EQ(sv.length, 14);
3353 1 EXPECT_TRUE(path_parent(&sv));
3354 1 EXPECT_EQ(sv.length, 10);
3355 1 EXPECT_TRUE(path_parent(&sv));
3356 1 EXPECT_EQ(sv.length, 6);
3357 1 EXPECT_TRUE(path_parent(&sv));
3358 1 EXPECT_EQ(sv.length, 2);
3359 1 EXPECT_TRUE(path_parent(&sv));
3360 1 EXPECT_EQ(sv.length, 1);
3361 1 EXPECT_FALSE(path_parent(&sv));
3362 1 EXPECT_EQ(sv.length, 1);
3363
3364 1 StringView sv2 = STRING_VIEW("/etc/foo/x/y/");
3365 1 EXPECT_EQ(sv2.length, 13);
3366 1 EXPECT_TRUE(path_parent(&sv2));
3367 1 EXPECT_EQ(sv2.length, 10);
3368 1 EXPECT_TRUE(path_parent(&sv2));
3369 1 EXPECT_EQ(sv2.length, 8);
3370 1 EXPECT_TRUE(path_parent(&sv2));
3371 1 EXPECT_EQ(sv2.length, 4);
3372 1 EXPECT_TRUE(path_parent(&sv2));
3373 1 EXPECT_EQ(sv2.length, 1);
3374 1 EXPECT_FALSE(path_parent(&sv2));
3375 1 EXPECT_EQ(sv2.length, 1);
3376 1 }
3377
3378 1 static void test_wrapping_increment(TestContext *ctx)
3379 {
3380 1 EXPECT_EQ(wrapping_increment(0, 1), 0);
3381 1 EXPECT_EQ(wrapping_increment(3, 5), 4);
3382 1 EXPECT_EQ(wrapping_increment(4, 5), 0);
3383 1 EXPECT_EQ(wrapping_increment(0, 5), 1);
3384
3385
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++) {
3386
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++) {
3387 36 EXPECT_EQ(wrapping_increment(x, m), (x + 1) % m);
3388 }
3389 }
3390 1 }
3391
3392 1 static void test_wrapping_decrement(TestContext *ctx)
3393 {
3394 1 EXPECT_EQ(wrapping_decrement(0, 1), 0);
3395 1 EXPECT_EQ(wrapping_decrement(1, 450), 0);
3396 1 EXPECT_EQ(wrapping_decrement(0, 450), 449);
3397 1 EXPECT_EQ(wrapping_decrement(449, 450), 448);
3398
3399
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++) {
3400 8 EXPECT_EQ(wrapping_decrement(0, m), m - 1);
3401
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++) {
3402 28 EXPECT_EQ(wrapping_decrement(x, m), (x - 1) % m);
3403 }
3404 }
3405 1 }
3406
3407 1 static void test_saturating_increment(TestContext *ctx)
3408 {
3409 1 EXPECT_UINT_EQ(saturating_increment(0, 0), 0);
3410 1 EXPECT_UINT_EQ(saturating_increment(1, 1), 1);
3411 1 EXPECT_UINT_EQ(saturating_increment(6, 7), 7);
3412 1 EXPECT_UINT_EQ(saturating_increment(7, 7), 7);
3413
3414 1 const size_t m = SIZE_MAX;
3415 1 EXPECT_UINT_EQ(saturating_increment(m - 2, m), m - 1);
3416 1 EXPECT_UINT_EQ(saturating_increment(m - 1, m), m);
3417 1 EXPECT_UINT_EQ(saturating_increment(m, m), m);
3418 1 }
3419
3420 1 static void test_saturating_decrement(TestContext *ctx)
3421 {
3422 1 EXPECT_UINT_EQ(saturating_decrement(0), 0);
3423 1 EXPECT_UINT_EQ(saturating_decrement(1), 0);
3424 1 EXPECT_UINT_EQ(saturating_decrement(2), 1);
3425 1 EXPECT_UINT_EQ(saturating_decrement(3), 2);
3426
3427 1 const size_t m = SIZE_MAX;
3428 1 EXPECT_UINT_EQ(saturating_decrement(m), m - 1);
3429 1 }
3430
3431 1 static void test_saturating_subtract(TestContext *ctx)
3432 {
3433 1 EXPECT_UINT_EQ(saturating_subtract(0, 1), 0);
3434 1 EXPECT_UINT_EQ(saturating_subtract(1, 1), 0);
3435 1 EXPECT_UINT_EQ(saturating_subtract(2, 1), 1);
3436 1 EXPECT_UINT_EQ(saturating_subtract(191, 170), 21);
3437
3438 1 const size_t m = SIZE_MAX;
3439 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m - 2), 1);
3440 1 EXPECT_UINT_EQ(saturating_subtract(m - 1, m), 0);
3441 1 EXPECT_UINT_EQ(saturating_subtract(m, m), 0);
3442 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 1), 1);
3443 1 EXPECT_UINT_EQ(saturating_subtract(m, m - 2), 2);
3444 1 EXPECT_UINT_EQ(saturating_subtract(0, m), 0);
3445 1 EXPECT_UINT_EQ(saturating_subtract(1, m), 0);
3446 1 EXPECT_UINT_EQ(saturating_subtract(m, 1), m - 1);
3447 1 }
3448
3449 1 static void test_size_multiply_overflows(TestContext *ctx)
3450 {
3451 1 size_t r = 0;
3452 1 EXPECT_FALSE(size_multiply_overflows(10, 20, &r));
3453 1 EXPECT_UINT_EQ(r, 200);
3454 1 EXPECT_FALSE(size_multiply_overflows(0, 0, &r));
3455 1 EXPECT_UINT_EQ(r, 0);
3456 1 EXPECT_FALSE(size_multiply_overflows(1, 0, &r));
3457 1 EXPECT_UINT_EQ(r, 0);
3458 1 EXPECT_FALSE(size_multiply_overflows(0, 1, &r));
3459 1 EXPECT_UINT_EQ(r, 0);
3460 1 EXPECT_FALSE(size_multiply_overflows(0, SIZE_MAX, &r));
3461 1 EXPECT_UINT_EQ(r, 0);
3462 1 EXPECT_FALSE(size_multiply_overflows(SIZE_MAX, 0, &r));
3463 1 EXPECT_UINT_EQ(r, 0);
3464 1 EXPECT_FALSE(size_multiply_overflows(1, SIZE_MAX, &r));
3465 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3466 1 EXPECT_FALSE(size_multiply_overflows(2, SIZE_MAX / 3, &r));
3467 1 EXPECT_UINT_EQ(r, 2 * (SIZE_MAX / 3));
3468 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, 2, &r));
3469 1 EXPECT_TRUE(size_multiply_overflows(2, SIZE_MAX, &r));
3470 1 EXPECT_TRUE(size_multiply_overflows(3, SIZE_MAX / 2, &r));
3471 1 EXPECT_TRUE(size_multiply_overflows(32767, SIZE_MAX, &r));
3472 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX, &r));
3473 1 EXPECT_TRUE(size_multiply_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3474 1 }
3475
3476 1 static void test_size_add_overflows(TestContext *ctx)
3477 {
3478 1 size_t r = 0;
3479 1 EXPECT_FALSE(size_add_overflows(10, 20, &r));
3480 1 EXPECT_UINT_EQ(r, 30);
3481 1 EXPECT_FALSE(size_add_overflows(SIZE_MAX, 0, &r));
3482 1 EXPECT_UINT_EQ(r, SIZE_MAX);
3483 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 1, &r));
3484 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, 16, &r));
3485 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX, &r));
3486 1 EXPECT_TRUE(size_add_overflows(SIZE_MAX, SIZE_MAX / 2, &r));
3487 1 }
3488
3489 1 static void test_xmul(TestContext *ctx)
3490 {
3491 1 const size_t halfmax = SIZE_MAX / 2;
3492 1 EXPECT_UINT_EQ(xmul(2, halfmax), 2 * halfmax);
3493 1 EXPECT_UINT_EQ(xmul(8, 8), 64);
3494 1 EXPECT_UINT_EQ(xmul(1, SIZE_MAX), SIZE_MAX);
3495 1 EXPECT_UINT_EQ(xmul(2000, 1), 2000);
3496 1 }
3497
3498 1 static void test_xadd(TestContext *ctx)
3499 {
3500 1 const size_t max = SIZE_MAX;
3501 1 EXPECT_UINT_EQ(xadd(max - 1, 1), max);
3502 1 EXPECT_UINT_EQ(xadd(8, 8), 16);
3503 1 EXPECT_UINT_EQ(xadd(0, 0), 0);
3504
3505 1 EXPECT_UINT_EQ(xadd3(max - 3, 2, 1), max);
3506 1 EXPECT_UINT_EQ(xadd3(11, 9, 5071), 5091);
3507 1 EXPECT_UINT_EQ(xadd3(0, 0, 0), 0);
3508 1 }
3509
3510 1 static void test_mem_intern(TestContext *ctx)
3511 {
3512 1 const char *ptrs[256];
3513 1 char str[8];
3514
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++) {
3515 256 size_t len = buf_uint_to_str(i, str);
3516 256 ptrs[i] = mem_intern(str, len);
3517 }
3518
3519 1 EXPECT_STREQ(ptrs[0], "0");
3520 1 EXPECT_STREQ(ptrs[1], "1");
3521 1 EXPECT_STREQ(ptrs[101], "101");
3522 1 EXPECT_STREQ(ptrs[255], "255");
3523
3524
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++) {
3525 256 size_t len = buf_uint_to_str(i, str);
3526 256 const char *ptr = mem_intern(str, len);
3527 256 EXPECT_PTREQ(ptr, ptrs[i]);
3528 }
3529 1 }
3530
3531 1 static void test_read_file(TestContext *ctx)
3532 {
3533 1 char *buf = NULL;
3534 1 ASSERT_EQ(read_file("/dev/null", &buf, 64), 0);
3535 1 ASSERT_NONNULL(buf);
3536 1 EXPECT_UINT_EQ((unsigned char)buf[0], '\0');
3537 1 free(buf);
3538
3539 1 buf = NULL;
3540 1 errno = 0;
3541 1 EXPECT_EQ(read_file("test/data/", &buf, 64), -1);
3542 1 EXPECT_EQ(errno, EISDIR);
3543 1 EXPECT_NULL(buf);
3544 1 free(buf);
3545
3546 1 buf = NULL;
3547 1 errno = 0;
3548 1 EXPECT_EQ(read_file("test/data/3lines.txt", &buf, 1), -1);
3549 1 EXPECT_EQ(errno, EFBIG);
3550 1 EXPECT_NULL(buf);
3551 1 free(buf);
3552
3553 1 ssize_t size = read_file("test/data/3lines.txt", &buf, 512);
3554 1 EXPECT_EQ(size, 26);
3555 1 ASSERT_NONNULL(buf);
3556 1 size_t pos = 0;
3557 1 const char *line = buf_next_line(buf, &pos, size);
3558 1 EXPECT_STREQ(line, "line #1");
3559 1 EXPECT_EQ(pos, 8);
3560 1 line = buf_next_line(buf, &pos, size);
3561 1 EXPECT_STREQ(line, " line #2");
3562 1 EXPECT_EQ(pos, 17);
3563 1 line = buf_next_line(buf, &pos, size);
3564 1 EXPECT_STREQ(line, " line #3");
3565 1 EXPECT_EQ(pos, 26);
3566 1 free(buf);
3567 1 }
3568
3569 1 static void test_xfopen(TestContext *ctx)
3570 {
3571 1 static const char modes[][4] = {"a", "a+", "r", "r+", "w", "w+"};
3572
2/2
✓ Branch 0 (10→3) taken 6 times.
✓ Branch 1 (10→11) taken 1 times.
7 FOR_EACH_I(i, modes) {
3573 6 FILE *f = xfopen("/dev/null", modes[i], O_CLOEXEC, 0666);
3574 6 IEXPECT_TRUE(f && fclose(f) == 0);
3575 }
3576 1 }
3577
3578 1 static void test_xstdio(TestContext *ctx)
3579 {
3580 1 FILE *f = xfopen("/dev/null", "r+", O_CLOEXEC, 0666);
3581 1 ASSERT_NONNULL(f);
3582
3583 1 char buf[16];
3584 1 EXPECT_NULL(xfgets(buf, sizeof(buf), f));
3585 1 EXPECT_NE(xfputs("str", f), EOF);
3586 1 EXPECT_EQ(xfputc(' ', f), ' ');
3587 1 EXPECT_EQ(xfprintf(f, "fmt %d", 42), 6);
3588 1 EXPECT_EQ(xfflush(f), 0);
3589 1 EXPECT_EQ(fclose(f), 0);
3590 1 }
3591
3592 1 static void test_fd_set_cloexec(TestContext *ctx)
3593 {
3594 1 int fd = open("/dev/null", O_RDONLY);
3595 1 ASSERT_TRUE(fd >= 0);
3596 1 int flags = fcntl(fd, F_GETFD);
3597 1 EXPECT_TRUE(flags >= 0);
3598 1 EXPECT_EQ(flags & FD_CLOEXEC, 0);
3599
3600 1 EXPECT_TRUE(fd_set_cloexec(fd, true));
3601 1 flags = fcntl(fd, F_GETFD);
3602 1 EXPECT_TRUE(flags > 0);
3603 1 EXPECT_EQ(flags & FD_CLOEXEC, FD_CLOEXEC);
3604
3605 // This set of tests is repeated twice, in order to check the special
3606 // case where the F_SETFD operation can be omitted because FD_CLOEXEC
3607 // was already set as requested
3608
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++) {
3609 2 IEXPECT_TRUE(fd_set_cloexec(fd, false));
3610 2 flags = fcntl(fd, F_GETFD);
3611 2 IEXPECT_TRUE(flags >= 0);
3612 2 IEXPECT_EQ(flags & FD_CLOEXEC, 0);
3613 }
3614
3615 1 close(fd);
3616 1 }
3617
3618 1 static void test_fd_set_nonblock(TestContext *ctx)
3619 {
3620 1 int fd = open("/dev/null", O_RDONLY);
3621 1 ASSERT_TRUE(fd >= 0);
3622 1 int flags = fcntl(fd, F_GETFL);
3623 1 EXPECT_TRUE(flags >= 0);
3624 1 EXPECT_EQ(flags & O_NONBLOCK, 0);
3625
3626 1 EXPECT_TRUE(fd_set_nonblock(fd, true));
3627 1 flags = fcntl(fd, F_GETFL);
3628 1 EXPECT_TRUE(flags > 0);
3629 1 EXPECT_EQ(flags & O_NONBLOCK, O_NONBLOCK);
3630
3631
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++) {
3632 2 IEXPECT_TRUE(fd_set_nonblock(fd, false));
3633 2 flags = fcntl(fd, F_GETFL);
3634 2 IEXPECT_TRUE(flags >= 0);
3635 2 IEXPECT_EQ(flags & O_NONBLOCK, 0);
3636 }
3637
3638 1 close(fd);
3639 1 }
3640
3641 1 static void test_fork_exec(TestContext *ctx)
3642 {
3643 1 int fd[3];
3644 1 fd[0] = open("/dev/null", O_RDWR | O_CLOEXEC);
3645 1 ASSERT_TRUE(fd[0] > 0);
3646 1 fd[1] = fd[0];
3647 1 fd[2] = fd[0];
3648
3649 1 const char *argv[] = {"sh", "-c", "exit 95", NULL};
3650 1 pid_t pid = fork_exec(argv, fd, 0, 0, true);
3651 1 ASSERT_NE(pid, -1);
3652 1 int r = wait_child(pid);
3653 1 EXPECT_EQ(r, 95);
3654
3655 1 argv[0] = "sleep";
3656 1 argv[1] = "5";
3657 1 argv[2] = NULL;
3658 1 pid = fork_exec(argv, fd, 0, 0, true);
3659 1 ASSERT_NE(pid, -1);
3660 1 EXPECT_EQ(kill(pid, SIGINT), 0);
3661 1 r = wait_child(pid);
3662 1 EXPECT_TRUE(r >= 256);
3663 1 EXPECT_EQ(r >> 8, SIGINT);
3664
3665 1 EXPECT_EQ(xclose(fd[0]), 0);
3666 1 }
3667
3668 1 static void test_xmemmem(TestContext *ctx)
3669 {
3670 1 static const char haystack[] = "finding a needle in a haystack";
3671 1 const char *needle = xmemmem(haystack, sizeof(haystack), STRN("needle"));
3672 1 ASSERT_NONNULL(needle);
3673 1 EXPECT_PTREQ(needle, haystack + 10);
3674
3675 1 needle = xmemmem(haystack, sizeof(haystack), "\0", 1);
3676 1 ASSERT_NONNULL(needle);
3677 1 EXPECT_PTREQ(needle, haystack + sizeof(haystack) - 1);
3678
3679 1 needle = xmemmem(haystack, sizeof(haystack) - 1, "\0", 1);
3680 1 EXPECT_NULL(needle);
3681
3682 1 needle = xmemmem(haystack, sizeof(haystack), STRN("in "));
3683 1 ASSERT_NONNULL(needle);
3684 1 EXPECT_PTREQ(needle, haystack + 17);
3685
3686 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystack"));
3687 1 ASSERT_NONNULL(needle);
3688 1 EXPECT_PTREQ(needle, haystack + 22);
3689
3690 1 needle = xmemmem(haystack, sizeof(haystack) - 1, STRN("haystacks"));
3691 1 EXPECT_NULL(needle);
3692
3693 1 needle = xmemmem(haystack, sizeof(haystack), STRN("haystacks"));
3694 1 EXPECT_NULL(needle);
3695 1 }
3696
3697 1 static void test_xmemrchr(TestContext *ctx)
3698 {
3699 1 static const char str[] = "123456789 abcdefedcba 987654321";
3700 1 EXPECT_PTREQ(xmemrchr(str, '9', sizeof(str) - 1), str + 22);
3701 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 1), str + sizeof(str) - 2);
3702 1 EXPECT_PTREQ(xmemrchr(str, '1', sizeof(str) - 2), str);
3703 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str)), str + sizeof(str) - 1);
3704 1 EXPECT_PTREQ(xmemrchr(str, '\0', sizeof(str) - 1), NULL);
3705 1 EXPECT_PTREQ(xmemrchr(str, 'z', sizeof(str) - 1), NULL);
3706 1 }
3707
3708 1 static void test_str_to_bitflags(TestContext *ctx)
3709 {
3710 1 static const char strs[][8] = {"zero", "one", "two", "three"};
3711 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("one,three", strs, true), 1 << 1 | 1 << 3);
3712 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("two,invalid,zero", strs, true), 1 << 2 | 1 << 0);
3713 1 EXPECT_UINT_EQ(STR_TO_BITFLAGS("two,invalid,zero", strs, false), 0);
3714 1 }
3715
3716 1 static void test_log_level_from_str(TestContext *ctx)
3717 {
3718 1 EXPECT_EQ(log_level_from_str("none"), LOG_LEVEL_NONE);
3719 1 EXPECT_EQ(log_level_from_str("crit"), LOG_LEVEL_CRITICAL);
3720 1 EXPECT_EQ(log_level_from_str("error"), LOG_LEVEL_ERROR);
3721 1 EXPECT_EQ(log_level_from_str("warning"), LOG_LEVEL_WARNING);
3722 1 EXPECT_EQ(log_level_from_str("notice"), LOG_LEVEL_NOTICE);
3723 1 EXPECT_EQ(log_level_from_str("info"), LOG_LEVEL_INFO);
3724 1 EXPECT_EQ(log_level_from_str("debug"), LOG_LEVEL_DEBUG);
3725 1 EXPECT_EQ(log_level_from_str("trace"), LOG_LEVEL_TRACE);
3726
3727 1 EXPECT_EQ(log_level_from_str("xyz"), LOG_LEVEL_INVALID);
3728 1 EXPECT_EQ(log_level_from_str(" "), LOG_LEVEL_INVALID);
3729 1 EXPECT_EQ(log_level_from_str("warn"), LOG_LEVEL_INVALID);
3730 1 EXPECT_EQ(log_level_from_str("errors"), LOG_LEVEL_INVALID);
3731
3732 1 LogLevel default_level = log_level_default();
3733 1 EXPECT_EQ(log_level_from_str(""), default_level);
3734 1 EXPECT_EQ(log_level_from_str(NULL), default_level);
3735 1 }
3736
3737 1 static void test_log_level_to_str(TestContext *ctx)
3738 {
3739 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NONE), "none");
3740 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_CRITICAL), "crit");
3741 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_ERROR), "error");
3742 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_WARNING), "warning");
3743 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_NOTICE), "notice");
3744 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_INFO), "info");
3745 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_DEBUG), "debug");
3746 1 EXPECT_STREQ(log_level_to_str(LOG_LEVEL_TRACE), "trace");
3747 1 }
3748
3749 1 static void test_timespec_subtract(TestContext *ctx)
3750 {
3751 1 struct timespec a = {.tv_sec = 3, .tv_nsec = 5497};
3752 1 struct timespec b = {.tv_sec = 1, .tv_nsec = NS_PER_SECOND - 1};
3753 1 struct timespec r = timespec_subtract(&a, &b);
3754 1 EXPECT_EQ(r.tv_sec, 1);
3755 1 EXPECT_EQ(r.tv_nsec, 5498);
3756
3757 1 b.tv_nsec = 501;
3758 1 r = timespec_subtract(&a, &b);
3759 1 EXPECT_EQ(r.tv_sec, 2);
3760 1 EXPECT_EQ(r.tv_nsec, 4996);
3761 1 }
3762
3763 1 static void test_timespec_to_str(TestContext *ctx)
3764 {
3765 1 char buf[TIME_STR_BUFSIZE] = "";
3766 1 struct timespec ts = {.tv_sec = 0};
3767 1 EXPECT_TRUE(timespecs_equal(&ts, &ts));
3768
3769 1 errno = 0;
3770 1 ts.tv_nsec = NS_PER_SECOND;
3771 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3772 1 EXPECT_EQ(errno, EINVAL);
3773
3774 1 errno = 0;
3775 1 ts.tv_nsec = -1;
3776 1 EXPECT_NULL(timespec_to_str(&ts, buf));
3777 1 EXPECT_EQ(errno, EINVAL);
3778
3779 // Note: $TZ is set to "UTC" in test_init()
3780 1 ts.tv_sec = 4321;
3781 1 ts.tv_nsec = 9876;
3782 1 const char *r = timespec_to_str(&ts, buf);
3783 1 EXPECT_STREQ(r, "1970-01-01 01:12:01.9876 +0000");
3784 1 EXPECT_PTREQ(r, buf);
3785
3786 1 ts.tv_sec = -1;
3787 1 ts.tv_nsec = NS_PER_SECOND - 1;
3788 1 r = timespec_to_str(&ts, buf);
3789 1 EXPECT_STREQ(r, "1969-12-31 23:59:59.999999999 +0000");
3790 1 }
3791
3792 1 static void test_progname(TestContext *ctx)
3793 {
3794 1 const char *const args[] = {"arg0", "", NULL};
3795 1 char **arg0 = (char**)args;
3796 1 char **arg1 = arg0 + 1;
3797 1 char **arg2 = arg0 + 2;
3798 1 EXPECT_STREQ(progname(1, arg0, "1"), "arg0");
3799 1 EXPECT_STREQ(progname(1, NULL, "2"), "2");
3800 1 EXPECT_STREQ(progname(0, arg0, "3"), "3");
3801 1 EXPECT_STREQ(progname(1, arg1, "4"), "4");
3802 1 EXPECT_STREQ(progname(1, arg2, "5"), "5");
3803 1 EXPECT_STREQ(progname(0, NULL, NULL), "_PROG_");
3804 1 }
3805
3806 static const TestEntry tests[] = {
3807 TEST(test_util_macros),
3808 TEST(test_is_power_of_2),
3809 TEST(test_xmalloc),
3810 TEST(test_xstreq),
3811 TEST(test_xstrrchr),
3812 TEST(test_str_has_strn_prefix),
3813 TEST(test_str_has_prefix),
3814 TEST(test_str_has_suffix),
3815 TEST(test_hex_decode),
3816 TEST(test_hex_encode_byte),
3817 TEST(test_ascii),
3818 TEST(test_mem_equal),
3819 TEST(test_mem_equal_icase),
3820 TEST(test_base64_decode),
3821 TEST(test_base64_encode_block),
3822 TEST(test_base64_encode_final),
3823 TEST(test_string),
3824 TEST(test_string_view),
3825 TEST(test_strview_has_suffix),
3826 TEST(test_strview_remove_matching),
3827 TEST(test_get_delim),
3828 TEST(test_get_delim_str),
3829 TEST(test_str_replace_byte),
3830 TEST(test_strn_replace_byte),
3831 TEST(test_string_array_concat),
3832 TEST(test_size_str_width),
3833 TEST(test_buf_parse_uintmax),
3834 TEST(test_buf_parse_ulong),
3835 TEST(test_buf_parse_size),
3836 TEST(test_buf_parse_hex_uint),
3837 TEST(test_str_to_int),
3838 TEST(test_str_to_size),
3839 TEST(test_str_to_filepos),
3840 TEST(test_buf_umax_to_hex_str),
3841 TEST(test_parse_filesize),
3842 TEST(test_umax_to_str),
3843 TEST(test_uint_to_str),
3844 TEST(test_ulong_to_str),
3845 TEST(test_buf_umax_to_str),
3846 TEST(test_buf_uint_to_str),
3847 TEST(test_buf_u8_to_str),
3848 TEST(test_file_permissions_to_str),
3849 TEST(test_human_readable_size),
3850 TEST(test_filesize_to_str),
3851 TEST(test_filesize_to_str_precise),
3852 TEST(test_u_char_size),
3853 TEST(test_u_char_width),
3854 TEST(test_u_to_lower),
3855 TEST(test_u_to_upper),
3856 TEST(test_u_is_lower),
3857 TEST(test_u_is_upper),
3858 TEST(test_u_is_ascii_upper),
3859 TEST(test_u_is_cntrl),
3860 TEST(test_u_is_unicode),
3861 TEST(test_u_is_zero_width),
3862 TEST(test_u_is_special_whitespace),
3863 TEST(test_u_is_unprintable),
3864 TEST(test_u_str_width),
3865 TEST(test_u_set_char_raw),
3866 TEST(test_u_set_char),
3867 TEST(test_u_make_printable),
3868 TEST(test_u_get_char),
3869 TEST(test_u_prev_char),
3870 TEST(test_u_skip_chars),
3871 TEST(test_ptr_array),
3872 TEST(test_ptr_array_move),
3873 TEST(test_ptr_array_insert),
3874 TEST(test_list),
3875 TEST(test_hashmap),
3876 TEST(test_hashset),
3877 TEST(test_intmap),
3878 TEST(test_next_multiple),
3879 TEST(test_next_pow2),
3880 TEST(test_popcount),
3881 TEST(test_ctz),
3882 TEST(test_ffs),
3883 TEST(test_lsbit),
3884 TEST(test_msbit),
3885 TEST(test_clz),
3886 TEST(test_umax_bitwidth),
3887 TEST(test_umax_count_base16_digits),
3888 TEST(test_path_dirname_basename),
3889 TEST(test_path_relative),
3890 TEST(test_path_slice_relative),
3891 TEST(test_short_filename_cwd),
3892 TEST(test_short_filename),
3893 TEST(test_path_absolute),
3894 TEST(test_path_join),
3895 TEST(test_path_parent),
3896 TEST(test_wrapping_increment),
3897 TEST(test_wrapping_decrement),
3898 TEST(test_saturating_increment),
3899 TEST(test_saturating_decrement),
3900 TEST(test_saturating_subtract),
3901 TEST(test_size_multiply_overflows),
3902 TEST(test_size_add_overflows),
3903 TEST(test_xmul),
3904 TEST(test_xadd),
3905 TEST(test_mem_intern),
3906 TEST(test_read_file),
3907 TEST(test_xfopen),
3908 TEST(test_xstdio),
3909 TEST(test_fd_set_cloexec),
3910 TEST(test_fd_set_nonblock),
3911 TEST(test_fork_exec),
3912 TEST(test_xmemmem),
3913 TEST(test_xmemrchr),
3914 TEST(test_str_to_bitflags),
3915 TEST(test_log_level_from_str),
3916 TEST(test_log_level_to_str),
3917 TEST(test_timespec_subtract),
3918 TEST(test_timespec_to_str),
3919 TEST(test_progname),
3920 };
3921
3922 const TestGroup util_tests = TEST_GROUP(tests);
3923