1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "util_test.h"
26
27 #include <cstring>
28 #include <iostream>
29 #include <random>
30
31 #include "munitxx.h"
32
33 #include <nghttp2/nghttp2.h>
34
35 #include "util.h"
36 #include "template.h"
37
38 using namespace nghttp2;
39 using namespace std::literals;
40
41 namespace shrpx {
42
43 namespace {
44 const MunitTest tests[]{
45 munit_void_test(test_util_streq),
46 munit_void_test(test_util_strieq),
47 munit_void_test(test_util_inp_strlower),
48 munit_void_test(test_util_to_base64),
49 munit_void_test(test_util_to_token68),
50 munit_void_test(test_util_percent_encode_token),
51 munit_void_test(test_util_percent_decode),
52 munit_void_test(test_util_quote_string),
53 munit_void_test(test_util_utox),
54 munit_void_test(test_util_http_date),
55 munit_void_test(test_util_select_h2),
56 munit_void_test(test_util_ipv6_numeric_addr),
57 munit_void_test(test_util_utos),
58 munit_void_test(test_util_make_string_ref_uint),
59 munit_void_test(test_util_utos_unit),
60 munit_void_test(test_util_utos_funit),
61 munit_void_test(test_util_parse_uint_with_unit),
62 munit_void_test(test_util_parse_uint),
63 munit_void_test(test_util_parse_duration_with_unit),
64 munit_void_test(test_util_duration_str),
65 munit_void_test(test_util_format_duration),
66 munit_void_test(test_util_starts_with),
67 munit_void_test(test_util_ends_with),
68 munit_void_test(test_util_parse_http_date),
69 munit_void_test(test_util_localtime_date),
70 munit_void_test(test_util_get_uint64),
71 munit_void_test(test_util_parse_config_str_list),
72 munit_void_test(test_util_make_http_hostport),
73 munit_void_test(test_util_make_hostport),
74 munit_void_test(test_util_random_alpha_digit),
75 munit_void_test(test_util_format_hex),
76 munit_void_test(test_util_is_hex_string),
77 munit_void_test(test_util_decode_hex),
78 munit_void_test(test_util_extract_host),
79 munit_void_test(test_util_split_hostport),
80 munit_void_test(test_util_split_str),
81 munit_void_test(test_util_rstrip),
82 munit_test_end(),
83 };
84 } // namespace
85
86 const MunitSuite util_suite{
87 "/util", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
88 };
89
test_util_streq(void)90 void test_util_streq(void) {
91 assert_true(util::streq("alpha"_sr, "alpha"_sr, 5));
92 assert_true(util::streq("alpha"_sr, "alphabravo"_sr, 5));
93 assert_false(util::streq("alpha"_sr, "alphabravo"_sr, 6));
94 assert_false(util::streq("alphabravo"_sr, "alpha"_sr, 5));
95 assert_false(util::streq("alpha"_sr, "alphA"_sr, 5));
96 assert_false(util::streq(""_sr, "a"_sr, 1));
97 assert_true(util::streq(""_sr, ""_sr, 0));
98 assert_false(util::streq("alpha"_sr, ""_sr, 0));
99 }
100
test_util_strieq(void)101 void test_util_strieq(void) {
102 assert_true(util::strieq(std::string("alpha"), std::string("alpha")));
103 assert_true(util::strieq(std::string("alpha"), std::string("AlPhA")));
104 assert_true(util::strieq(std::string(), std::string()));
105 assert_false(util::strieq(std::string("alpha"), std::string("AlPhA ")));
106 assert_false(util::strieq(std::string(), std::string("AlPhA ")));
107
108 assert_true(util::strieq("alpha"_sr, "alpha"_sr));
109 assert_true(util::strieq("alpha"_sr, "AlPhA"_sr));
110 assert_true(util::strieq(StringRef{}, StringRef{}));
111 assert_false(util::strieq("alpha"_sr, "AlPhA "_sr));
112 assert_false(util::strieq(""_sr, "AlPhA "_sr));
113
114 assert_true(util::strieq("alpha"_sr, "alpha"_sr, 5));
115 assert_true(util::strieq("alpha"_sr, "AlPhA"_sr, 5));
116 assert_false(util::strieq("alpha"_sr, "AlPhA "_sr, 6));
117 assert_false(util::strieq(""_sr, "AlPhA "_sr, 6));
118 }
119
test_util_inp_strlower(void)120 void test_util_inp_strlower(void) {
121 std::string a("alPha");
122 util::inp_strlower(a);
123 assert_stdstring_equal("alpha", a);
124
125 a = "ALPHA123BRAVO";
126 util::inp_strlower(a);
127 assert_stdstring_equal("alpha123bravo", a);
128
129 a = "";
130 util::inp_strlower(a);
131 assert_stdstring_equal("", a);
132 }
133
test_util_to_base64(void)134 void test_util_to_base64(void) {
135 BlockAllocator balloc(4096, 4096);
136
137 assert_stdsv_equal("AAA++B/="sv, util::to_base64(balloc, "AAA--B_"_sr));
138 assert_stdsv_equal("AAA++B/B"sv, util::to_base64(balloc, "AAA--B_B"_sr));
139 }
140
test_util_to_token68(void)141 void test_util_to_token68(void) {
142 std::string x = "AAA++B/=";
143 util::to_token68(x);
144 assert_stdstring_equal("AAA--B_", x);
145
146 x = "AAA++B/B";
147 util::to_token68(x);
148 assert_stdstring_equal("AAA--B_B", x);
149 }
150
test_util_percent_encode_token(void)151 void test_util_percent_encode_token(void) {
152 BlockAllocator balloc(4096, 4096);
153 assert_stdsv_equal("h2"sv, util::percent_encode_token(balloc, "h2"_sr));
154 assert_stdsv_equal("h3~"sv, util::percent_encode_token(balloc, "h3~"_sr));
155 assert_stdsv_equal("100%25"sv, util::percent_encode_token(balloc, "100%"_sr));
156 assert_stdsv_equal("http%202"sv,
157 util::percent_encode_token(balloc, "http 2"_sr));
158 }
159
test_util_percent_decode(void)160 void test_util_percent_decode(void) {
161 {
162 std::string s = "%66%6F%6f%62%61%72";
163 assert_stdstring_equal("foobar",
164 util::percent_decode(std::begin(s), std::end(s)));
165 }
166 {
167 std::string s = "%66%6";
168 assert_stdstring_equal("f%6",
169 util::percent_decode(std::begin(s), std::end(s)));
170 }
171 {
172 std::string s = "%66%";
173 assert_stdstring_equal("f%",
174 util::percent_decode(std::begin(s), std::end(s)));
175 }
176 BlockAllocator balloc(1024, 1024);
177
178 assert_stdsv_equal("foobar"sv,
179 util::percent_decode(balloc, "%66%6F%6f%62%61%72"_sr));
180
181 assert_stdsv_equal("f%6"sv, util::percent_decode(balloc, "%66%6"_sr));
182
183 assert_stdsv_equal("f%"sv, util::percent_decode(balloc, "%66%"_sr));
184 }
185
test_util_quote_string(void)186 void test_util_quote_string(void) {
187 BlockAllocator balloc(4096, 4096);
188 assert_stdsv_equal("alpha"sv, util::quote_string(balloc, "alpha"_sr));
189 assert_stdsv_equal(""sv, util::quote_string(balloc, ""_sr));
190 assert_stdsv_equal("\\\"alpha\\\""sv,
191 util::quote_string(balloc, "\"alpha\""_sr));
192 }
193
test_util_utox(void)194 void test_util_utox(void) {
195 assert_stdstring_equal("0", util::utox(0));
196 assert_stdstring_equal("1", util::utox(1));
197 assert_stdstring_equal("F", util::utox(15));
198 assert_stdstring_equal("10", util::utox(16));
199 assert_stdstring_equal("3B9ACA07", util::utox(1000000007));
200 assert_stdstring_equal("100000000", util::utox(1LL << 32));
201 }
202
test_util_http_date(void)203 void test_util_http_date(void) {
204 assert_stdstring_equal("Thu, 01 Jan 1970 00:00:00 GMT", util::http_date(0));
205 assert_stdstring_equal("Wed, 29 Feb 2012 09:15:16 GMT",
206 util::http_date(1330506916));
207
208 std::array<char, 30> http_buf;
209
210 assert_stdsv_equal(
211 "Thu, 01 Jan 1970 00:00:00 GMT"sv,
212 util::format_http_date(http_buf.data(),
213 std::chrono::system_clock::time_point()));
214 assert_stdsv_equal("Wed, 29 Feb 2012 09:15:16 GMT"sv,
215 util::format_http_date(
216 http_buf.data(), std::chrono::system_clock::time_point(
217 std::chrono::seconds(1330506916))));
218 }
219
test_util_select_h2(void)220 void test_util_select_h2(void) {
221 const unsigned char *out = nullptr;
222 unsigned char outlen = 0;
223
224 // Check single entry and select it.
225 const unsigned char t1[] = "\x2h2";
226 assert_true(util::select_h2(&out, &outlen, t1, sizeof(t1) - 1));
227 assert_memory_equal(NGHTTP2_PROTO_VERSION_ID_LEN, NGHTTP2_PROTO_VERSION_ID,
228 out);
229 assert_uchar(NGHTTP2_PROTO_VERSION_ID_LEN, ==, outlen);
230
231 out = nullptr;
232 outlen = 0;
233
234 // Check the case where id is correct but length is invalid and too
235 // long.
236 const unsigned char t2[] = "\x6h2-14";
237 assert_false(util::select_h2(&out, &outlen, t2, sizeof(t2) - 1));
238
239 // Check the case where h2 is located after bogus ID.
240 const unsigned char t3[] = "\x2h3\x2h2";
241 assert_true(util::select_h2(&out, &outlen, t3, sizeof(t3) - 1));
242
243 assert_memory_equal(NGHTTP2_PROTO_VERSION_ID_LEN, NGHTTP2_PROTO_VERSION_ID,
244 out);
245 assert_uchar(NGHTTP2_PROTO_VERSION_ID_LEN, ==, outlen);
246
247 out = nullptr;
248 outlen = 0;
249
250 // Check the case that last entry's length is invalid and too long.
251 const unsigned char t4[] = "\x2h3\x6h2-14";
252 assert_false(util::select_h2(&out, &outlen, t4, sizeof(t4) - 1));
253
254 // Check the case that all entries are not supported.
255 const unsigned char t5[] = "\x2h3\x2h4";
256 assert_false(util::select_h2(&out, &outlen, t5, sizeof(t5) - 1));
257
258 // Check the case where 2 values are eligible, but last one is
259 // picked up because it has precedence over the other.
260 const unsigned char t6[] = "\x5h2-14\x5h2-16";
261 assert_true(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1));
262 assert_stdsv_equal(NGHTTP2_H2_16, (StringRef{out, outlen}));
263 }
264
test_util_ipv6_numeric_addr(void)265 void test_util_ipv6_numeric_addr(void) {
266 assert_true(util::ipv6_numeric_addr("::1"));
267 assert_true(
268 util::ipv6_numeric_addr("2001:0db8:85a3:0042:1000:8a2e:0370:7334"));
269 // IPv4
270 assert_false(util::ipv6_numeric_addr("127.0.0.1"));
271 // not numeric address
272 assert_false(util::ipv6_numeric_addr("localhost"));
273 }
274
test_util_utos(void)275 void test_util_utos(void) {
276 uint8_t buf[32];
277
278 assert_stdstring_equal("0", (std::string{buf, util::utos(buf, 0)}));
279 assert_stdstring_equal("123", (std::string{buf, util::utos(buf, 123)}));
280 assert_stdstring_equal(
281 "18446744073709551615",
282 (std::string{buf, util::utos(buf, 18446744073709551615ULL)}));
283 }
284
test_util_make_string_ref_uint(void)285 void test_util_make_string_ref_uint(void) {
286 BlockAllocator balloc(1024, 1024);
287
288 assert_stdsv_equal("0"sv, util::make_string_ref_uint(balloc, 0));
289 assert_stdsv_equal("123"sv, util::make_string_ref_uint(balloc, 123));
290 assert_stdsv_equal(
291 "18446744073709551615"sv,
292 util::make_string_ref_uint(balloc, 18446744073709551615ULL));
293 }
294
test_util_utos_unit(void)295 void test_util_utos_unit(void) {
296 assert_stdstring_equal("0", util::utos_unit(0));
297 assert_stdstring_equal("1023", util::utos_unit(1023));
298 assert_stdstring_equal("1K", util::utos_unit(1024));
299 assert_stdstring_equal("1K", util::utos_unit(1025));
300 assert_stdstring_equal("1M", util::utos_unit(1 << 20));
301 assert_stdstring_equal("1G", util::utos_unit(1 << 30));
302 assert_stdstring_equal("1024G", util::utos_unit(1LL << 40));
303 }
304
test_util_utos_funit(void)305 void test_util_utos_funit(void) {
306 assert_stdstring_equal("0", util::utos_funit(0));
307 assert_stdstring_equal("1023", util::utos_funit(1023));
308 assert_stdstring_equal("1.00K", util::utos_funit(1024));
309 assert_stdstring_equal("1.00K", util::utos_funit(1025));
310 assert_stdstring_equal("1.09K", util::utos_funit(1119));
311 assert_stdstring_equal("1.27K", util::utos_funit(1300));
312 assert_stdstring_equal("1.00M", util::utos_funit(1 << 20));
313 assert_stdstring_equal("1.18M", util::utos_funit(1234567));
314 assert_stdstring_equal("1.00G", util::utos_funit(1 << 30));
315 assert_stdstring_equal("4492450797.23G",
316 util::utos_funit(4823732313248234343LL));
317 assert_stdstring_equal("1024.00G", util::utos_funit(1LL << 40));
318 }
319
test_util_parse_uint_with_unit(void)320 void test_util_parse_uint_with_unit(void) {
321 assert_int64(0, ==, util::parse_uint_with_unit("0").value_or(-1));
322 assert_int64(1023, ==, util::parse_uint_with_unit("1023").value_or(-1));
323 assert_int64(1024, ==, util::parse_uint_with_unit("1k").value_or(-1));
324 assert_int64(2048, ==, util::parse_uint_with_unit("2K").value_or(-1));
325 assert_int64(1 << 20, ==, util::parse_uint_with_unit("1m").value_or(-1));
326 assert_int64(1 << 21, ==, util::parse_uint_with_unit("2M").value_or(-1));
327 assert_int64(1 << 30, ==, util::parse_uint_with_unit("1g").value_or(-1));
328 assert_int64(1LL << 31, ==, util::parse_uint_with_unit("2G").value_or(-1));
329 assert_int64(9223372036854775807LL, ==,
330 util::parse_uint_with_unit("9223372036854775807").value_or(-1));
331 // check overflow case
332 assert_false(util::parse_uint_with_unit("9223372036854775808"));
333 assert_false(util::parse_uint_with_unit("10000000000000000000"));
334 assert_false(util::parse_uint_with_unit("9223372036854775807G"));
335 // bad characters
336 assert_false(util::parse_uint_with_unit("1.1"));
337 assert_false(util::parse_uint_with_unit("1a"));
338 assert_false(util::parse_uint_with_unit("a1"));
339 assert_false(util::parse_uint_with_unit("1T"));
340 assert_false(util::parse_uint_with_unit(""));
341 }
342
test_util_parse_uint(void)343 void test_util_parse_uint(void) {
344 assert_int64(0, ==, util::parse_uint("0").value_or(-1));
345 assert_int64(1023, ==, util::parse_uint("1023").value_or(-1));
346 assert_false(util::parse_uint("1k"));
347 assert_int64(9223372036854775807LL, ==,
348 util::parse_uint("9223372036854775807").value_or(-1));
349 // check overflow case
350 assert_false(util::parse_uint("9223372036854775808"));
351 assert_false(util::parse_uint("10000000000000000000"));
352 // bad characters
353 assert_false(util::parse_uint("1.1"));
354 assert_false(util::parse_uint("1a"));
355 assert_false(util::parse_uint("a1"));
356 assert_false(util::parse_uint("1T"));
357 assert_false(util::parse_uint(""));
358 }
359
test_util_parse_duration_with_unit(void)360 void test_util_parse_duration_with_unit(void) {
361 auto inf = std::numeric_limits<double>::infinity();
362
363 assert_double(0., ==, util::parse_duration_with_unit("0").value_or(inf));
364 assert_double(123., ==, util::parse_duration_with_unit("123").value_or(inf));
365 assert_double(123., ==, util::parse_duration_with_unit("123s").value_or(inf));
366 assert_double(0.500, ==,
367 util::parse_duration_with_unit("500ms").value_or(inf));
368 assert_double(123., ==, util::parse_duration_with_unit("123S").value_or(inf));
369 assert_double(0.500, ==,
370 util::parse_duration_with_unit("500MS").value_or(inf));
371 assert_double(180, ==, util::parse_duration_with_unit("3m").value_or(inf));
372 assert_double(3600 * 5, ==,
373 util::parse_duration_with_unit("5h").value_or(inf));
374
375 // check overflow case
376 assert_false(util::parse_duration_with_unit("9223372036854775808"));
377 // bad characters
378 assert_false(util::parse_duration_with_unit("0u"));
379 assert_false(util::parse_duration_with_unit("0xs"));
380 assert_false(util::parse_duration_with_unit("0mt"));
381 assert_false(util::parse_duration_with_unit("0mss"));
382 assert_false(util::parse_duration_with_unit("s"));
383 assert_false(util::parse_duration_with_unit("ms"));
384 }
385
test_util_duration_str(void)386 void test_util_duration_str(void) {
387 assert_stdstring_equal("0", util::duration_str(0.));
388 assert_stdstring_equal("1s", util::duration_str(1.));
389 assert_stdstring_equal("500ms", util::duration_str(0.5));
390 assert_stdstring_equal("1500ms", util::duration_str(1.5));
391 assert_stdstring_equal("2m", util::duration_str(120.));
392 assert_stdstring_equal("121s", util::duration_str(121.));
393 assert_stdstring_equal("1h", util::duration_str(3600.));
394 }
395
test_util_format_duration(void)396 void test_util_format_duration(void) {
397 assert_stdstring_equal("0us",
398 util::format_duration(std::chrono::microseconds(0)));
399 assert_stdstring_equal("999us",
400 util::format_duration(std::chrono::microseconds(999)));
401 assert_stdstring_equal(
402 "1.00ms", util::format_duration(std::chrono::microseconds(1000)));
403 assert_stdstring_equal(
404 "1.09ms", util::format_duration(std::chrono::microseconds(1090)));
405 assert_stdstring_equal(
406 "1.01ms", util::format_duration(std::chrono::microseconds(1009)));
407 assert_stdstring_equal(
408 "999.99ms", util::format_duration(std::chrono::microseconds(999990)));
409 assert_stdstring_equal(
410 "1.00s", util::format_duration(std::chrono::microseconds(1000000)));
411 assert_stdstring_equal(
412 "1.05s", util::format_duration(std::chrono::microseconds(1050000)));
413
414 assert_stdstring_equal("0us", util::format_duration(0.));
415 assert_stdstring_equal("999us", util::format_duration(0.000999));
416 assert_stdstring_equal("1.00ms", util::format_duration(0.001));
417 assert_stdstring_equal("1.09ms", util::format_duration(0.00109));
418 assert_stdstring_equal("1.01ms", util::format_duration(0.001009));
419 assert_stdstring_equal("999.99ms", util::format_duration(0.99999));
420 assert_stdstring_equal("1.00s", util::format_duration(1.));
421 assert_stdstring_equal("1.05s", util::format_duration(1.05));
422 }
423
test_util_starts_with(void)424 void test_util_starts_with(void) {
425 assert_true(util::starts_with("foo"_sr, "foo"_sr));
426 assert_true(util::starts_with("fooo"_sr, "foo"_sr));
427 assert_true(util::starts_with("ofoo"_sr, StringRef{}));
428 assert_false(util::starts_with("ofoo"_sr, "foo"_sr));
429
430 assert_true(util::istarts_with("FOO"_sr, "fOO"_sr));
431 assert_true(util::istarts_with("ofoo"_sr, StringRef{}));
432 assert_true(util::istarts_with("fOOo"_sr, "Foo"_sr));
433 assert_false(util::istarts_with("ofoo"_sr, "foo"_sr));
434 }
435
test_util_ends_with(void)436 void test_util_ends_with(void) {
437 assert_true(util::ends_with("foo"_sr, "foo"_sr));
438 assert_true(util::ends_with("foo"_sr, StringRef{}));
439 assert_true(util::ends_with("ofoo"_sr, "foo"_sr));
440 assert_false(util::ends_with("ofoo"_sr, "fo"_sr));
441
442 assert_true(util::iends_with("fOo"_sr, "Foo"_sr));
443 assert_true(util::iends_with("foo"_sr, StringRef{}));
444 assert_true(util::iends_with("oFoo"_sr, "fOO"_sr));
445 assert_false(util::iends_with("ofoo"_sr, "fo"_sr));
446 }
447
test_util_parse_http_date(void)448 void test_util_parse_http_date(void) {
449 assert_int64(1001939696, ==,
450 util::parse_http_date("Mon, 1 Oct 2001 12:34:56 GMT"_sr));
451 }
452
test_util_localtime_date(void)453 void test_util_localtime_date(void) {
454 auto tz = getenv("TZ");
455 if (tz) {
456 tz = strdup(tz);
457 }
458 #ifdef __linux__
459 setenv("TZ", "NZST-12:00:00:00", 1);
460 #else // !__linux__
461 setenv("TZ", ":Pacific/Auckland", 1);
462 #endif // !__linux__
463 tzset();
464
465 assert_stdstring_equal("02/Oct/2001:00:34:56 +1200",
466 util::common_log_date(1001939696));
467 assert_stdstring_equal("2001-10-02T00:34:56.123+12:00",
468 util::iso8601_date(1001939696000LL + 123));
469
470 std::array<char, 27> common_buf;
471
472 assert_stdsv_equal("02/Oct/2001:00:34:56 +1200"sv,
473 util::format_common_log(
474 common_buf.data(), std::chrono::system_clock::time_point(
475 std::chrono::seconds(1001939696))));
476
477 std::array<char, 30> iso8601_buf;
478
479 assert_stdsv_equal(
480 "2001-10-02T00:34:56.123+12:00"sv,
481 util::format_iso8601(iso8601_buf.data(),
482 std::chrono::system_clock::time_point(
483 std::chrono::milliseconds(1001939696123LL))));
484
485 if (tz) {
486 setenv("TZ", tz, 1);
487 free(tz);
488 } else {
489 unsetenv("TZ");
490 }
491 tzset();
492 }
493
test_util_get_uint64(void)494 void test_util_get_uint64(void) {
495 {
496 auto v = std::to_array<unsigned char>(
497 {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc});
498
499 auto n = util::get_uint64(v.data());
500
501 assert_uint64(0x01123456ff9aabbcULL, ==, n);
502 }
503 {
504 auto v = std::to_array<unsigned char>(
505 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff});
506
507 auto n = util::get_uint64(v.data());
508
509 assert_uint64(0xffffffffffffffffULL, ==, n);
510 }
511 }
512
test_util_parse_config_str_list(void)513 void test_util_parse_config_str_list(void) {
514 auto res = util::parse_config_str_list("a"_sr);
515 assert_size(1, ==, res.size());
516 assert_stdstring_equal("a", res[0]);
517
518 res = util::parse_config_str_list("a,"_sr);
519 assert_size(2, ==, res.size());
520 assert_stdstring_equal("a", res[0]);
521 assert_stdstring_equal("", res[1]);
522
523 res = util::parse_config_str_list(":a::"_sr, ':');
524 assert_size(4, ==, res.size());
525 assert_stdstring_equal("", res[0]);
526 assert_stdstring_equal("a", res[1]);
527 assert_stdstring_equal("", res[2]);
528 assert_stdstring_equal("", res[3]);
529
530 res = util::parse_config_str_list(StringRef{});
531 assert_size(1, ==, res.size());
532 assert_stdstring_equal("", res[0]);
533
534 res = util::parse_config_str_list("alpha,bravo,charlie"_sr);
535 assert_size(3, ==, res.size());
536 assert_stdstring_equal("alpha", res[0]);
537 assert_stdstring_equal("bravo", res[1]);
538 assert_stdstring_equal("charlie", res[2]);
539 }
540
test_util_make_http_hostport(void)541 void test_util_make_http_hostport(void) {
542 BlockAllocator balloc(4096, 4096);
543
544 assert_stdsv_equal("localhost"sv,
545 util::make_http_hostport(balloc, "localhost"_sr, 80));
546 assert_stdsv_equal("[::1]"sv,
547 util::make_http_hostport(balloc, "::1"_sr, 443));
548 assert_stdsv_equal("localhost:3000"sv,
549 util::make_http_hostport(balloc, "localhost"_sr, 3000));
550 }
551
test_util_make_hostport(void)552 void test_util_make_hostport(void) {
553 std::array<char, util::max_hostport> hostport_buf;
554 assert_stdsv_equal(
555 "localhost:80"sv,
556 util::make_hostport(std::begin(hostport_buf), "localhost"_sr, 80));
557 assert_stdsv_equal("[::1]:443"sv, util::make_hostport(
558 std::begin(hostport_buf), "::1"_sr, 443));
559
560 BlockAllocator balloc(4096, 4096);
561 assert_stdsv_equal("localhost:80"sv,
562 util::make_hostport(balloc, "localhost"_sr, 80));
563 assert_stdsv_equal("[::1]:443"sv, util::make_hostport(balloc, "::1"_sr, 443));
564 }
565
test_util_random_alpha_digit(void)566 void test_util_random_alpha_digit(void) {
567 std::random_device rd;
568 std::mt19937 gen(rd());
569 std::array<uint8_t, 19> data;
570
571 auto p = util::random_alpha_digit(std::begin(data), std::end(data), gen);
572
573 assert_true(std::end(data) == p);
574
575 for (auto b : data) {
576 assert_true(('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') ||
577 ('0' <= b && b <= '9'));
578 }
579 }
580
test_util_format_hex(void)581 void test_util_format_hex(void) {
582 BlockAllocator balloc(4096, 4096);
583
584 assert_stdsv_equal("0ff0"sv,
585 util::format_hex(balloc, std::span{"\x0f\xf0"_sr}));
586 assert_stdsv_equal(""sv,
587 util::format_hex(balloc, std::span<const uint8_t>{}));
588
589 union T {
590 uint16_t x;
591 uint8_t y[2];
592 };
593
594 auto t = T{.y = {0xbe, 0xef}};
595
596 assert_stdstring_equal("beef", util::format_hex(std::span{&t.x, 1}));
597
598 std::string o;
599 o.resize(4);
600
601 assert_true(std::end(o) ==
602 util::format_hex(std::begin(o), std::span{&t.x, 1}));
603 assert_stdstring_equal("beef", o);
604
605 struct S {
606 uint8_t x[8];
607 };
608
609 auto s = S{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf8}};
610
611 assert_stdstring_equal("01020304050607f8", util::format_hex(s.x));
612 }
613
test_util_is_hex_string(void)614 void test_util_is_hex_string(void) {
615 assert_true(util::is_hex_string(StringRef{}));
616 assert_true(util::is_hex_string("0123456789abcdef"_sr));
617 assert_true(util::is_hex_string("0123456789ABCDEF"_sr));
618 assert_false(util::is_hex_string("000"_sr));
619 assert_false(util::is_hex_string("XX"_sr));
620 }
621
test_util_decode_hex(void)622 void test_util_decode_hex(void) {
623 BlockAllocator balloc(4096, 4096);
624
625 assert_stdsv_equal("\x0f\xf0"sv,
626 StringRef{util::decode_hex(balloc, "0ff0"_sr)});
627 assert_stdsv_equal(""sv, StringRef{util::decode_hex(balloc, StringRef{})});
628 }
629
test_util_extract_host(void)630 void test_util_extract_host(void) {
631 assert_stdsv_equal("foo"sv, util::extract_host("foo"_sr));
632 assert_stdsv_equal("foo"sv, util::extract_host("foo:"_sr));
633 assert_stdsv_equal("foo"sv, util::extract_host("foo:0"_sr));
634 assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]"_sr));
635 assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]:"_sr));
636
637 assert_true(util::extract_host(":foo"_sr).empty());
638 assert_true(util::extract_host("[::1"_sr).empty());
639 assert_true(util::extract_host("[::1]0"_sr).empty());
640 assert_true(util::extract_host(StringRef{}).empty());
641 }
642
test_util_split_hostport(void)643 void test_util_split_hostport(void) {
644 assert_true(std::make_pair("foo"_sr, StringRef{}) ==
645 util::split_hostport("foo"_sr));
646 assert_true(std::make_pair("foo"_sr, "80"_sr) ==
647 util::split_hostport("foo:80"_sr));
648 assert_true(std::make_pair("::1"_sr, "80"_sr) ==
649 util::split_hostport("[::1]:80"_sr));
650 assert_true(std::make_pair("::1"_sr, StringRef{}) ==
651 util::split_hostport("[::1]"_sr));
652
653 assert_true(std::make_pair(StringRef{}, StringRef{}) ==
654 util::split_hostport(StringRef{}));
655 assert_true(std::make_pair(StringRef{}, StringRef{}) ==
656 util::split_hostport("[::1]:"_sr));
657 assert_true(std::make_pair(StringRef{}, StringRef{}) ==
658 util::split_hostport("foo:"_sr));
659 assert_true(std::make_pair(StringRef{}, StringRef{}) ==
660 util::split_hostport("[::1:"_sr));
661 assert_true(std::make_pair(StringRef{}, StringRef{}) ==
662 util::split_hostport("[::1]80"_sr));
663 }
664
test_util_split_str(void)665 void test_util_split_str(void) {
666 assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ','));
667 assert_true(std::vector<StringRef>{"alpha"_sr} ==
668 util::split_str("alpha"_sr, ','));
669 assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) ==
670 util::split_str("alpha,"_sr, ','));
671 assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr}) ==
672 util::split_str("alpha,bravo"_sr, ','));
673 assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) ==
674 util::split_str("alpha,bravo,charlie"_sr, ','));
675 assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) ==
676 util::split_str("alpha,bravo,charlie"_sr, ',', 0));
677 assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 1));
678 assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 2));
679 assert_true((std::vector<StringRef>{"alpha"_sr, "bravo,charlie"_sr}) ==
680 util::split_str("alpha,bravo,charlie"_sr, ',', 2));
681 assert_true(std::vector<StringRef>{"alpha"_sr} ==
682 util::split_str("alpha"_sr, ',', 2));
683 assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) ==
684 util::split_str("alpha,"_sr, ',', 2));
685 assert_true(std::vector<StringRef>{"alpha"_sr} ==
686 util::split_str("alpha"_sr, ',', 0));
687 assert_true(std::vector<StringRef>{"alpha,bravo,charlie"_sr} ==
688 util::split_str("alpha,bravo,charlie"_sr, ',', 1));
689 }
690
test_util_rstrip(void)691 void test_util_rstrip(void) {
692 BlockAllocator balloc(4096, 4096);
693
694 assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha"_sr));
695 assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha "_sr));
696 assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha \t"_sr));
697 assert_stdsv_equal(""sv, util::rstrip(balloc, ""_sr));
698 assert_stdsv_equal(""sv, util::rstrip(balloc, "\t\t\t "_sr));
699 }
700
701 } // namespace shrpx
702