dte test coverage


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