dte test coverage


Directory: ./
File: test/util.c
Date: 2025-05-08 15:05:54
Exec Total Coverage
Lines: 2805 2806 99.9%
Functions: 107 107 100.0%
Branches: 85 86 98.8%

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