dte test coverage


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