dte test coverage


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