• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(
215       "Wed, 29 Feb 2012 09:15:16 GMT"sv,
216       util::format_http_date(http_buf.data(),
217                              std::chrono::system_clock::time_point(
218                                  std::chrono::seconds(1330506916))));
219 }
220 
test_util_select_h2(void)221 void test_util_select_h2(void) {
222   const unsigned char *out = nullptr;
223   unsigned char outlen = 0;
224 
225   // Check single entry and select it.
226   const unsigned char t1[] = "\x2h2";
227   assert_true(util::select_h2(&out, &outlen, t1, sizeof(t1) - 1));
228   assert_memory_equal(NGHTTP2_PROTO_VERSION_ID_LEN, NGHTTP2_PROTO_VERSION_ID,
229                       out);
230   assert_uchar(NGHTTP2_PROTO_VERSION_ID_LEN, ==, outlen);
231 
232   out = nullptr;
233   outlen = 0;
234 
235   // Check the case where id is correct but length is invalid and too
236   // long.
237   const unsigned char t2[] = "\x6h2-14";
238   assert_false(util::select_h2(&out, &outlen, t2, sizeof(t2) - 1));
239 
240   // Check the case where h2 is located after bogus ID.
241   const unsigned char t3[] = "\x2h3\x2h2";
242   assert_true(util::select_h2(&out, &outlen, t3, sizeof(t3) - 1));
243 
244   assert_memory_equal(NGHTTP2_PROTO_VERSION_ID_LEN, NGHTTP2_PROTO_VERSION_ID,
245                       out);
246   assert_uchar(NGHTTP2_PROTO_VERSION_ID_LEN, ==, outlen);
247 
248   out = nullptr;
249   outlen = 0;
250 
251   // Check the case that last entry's length is invalid and too long.
252   const unsigned char t4[] = "\x2h3\x6h2-14";
253   assert_false(util::select_h2(&out, &outlen, t4, sizeof(t4) - 1));
254 
255   // Check the case that all entries are not supported.
256   const unsigned char t5[] = "\x2h3\x2h4";
257   assert_false(util::select_h2(&out, &outlen, t5, sizeof(t5) - 1));
258 
259   // Check the case where 2 values are eligible, but last one is
260   // picked up because it has precedence over the other.
261   const unsigned char t6[] = "\x5h2-14\x5h2-16";
262   assert_true(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1));
263   assert_stdsv_equal(NGHTTP2_H2_16, (StringRef{out, outlen}));
264 }
265 
test_util_ipv6_numeric_addr(void)266 void test_util_ipv6_numeric_addr(void) {
267   assert_true(util::ipv6_numeric_addr("::1"));
268   assert_true(
269       util::ipv6_numeric_addr("2001:0db8:85a3:0042:1000:8a2e:0370:7334"));
270   // IPv4
271   assert_false(util::ipv6_numeric_addr("127.0.0.1"));
272   // not numeric address
273   assert_false(util::ipv6_numeric_addr("localhost"));
274 }
275 
test_util_utos(void)276 void test_util_utos(void) {
277   uint8_t buf[32];
278 
279   assert_stdstring_equal("0", (std::string{buf, util::utos(buf, 0)}));
280   assert_stdstring_equal("123", (std::string{buf, util::utos(buf, 123)}));
281   assert_stdstring_equal(
282       "18446744073709551615",
283       (std::string{buf, util::utos(buf, 18446744073709551615ULL)}));
284 }
285 
test_util_make_string_ref_uint(void)286 void test_util_make_string_ref_uint(void) {
287   BlockAllocator balloc(1024, 1024);
288 
289   assert_stdsv_equal("0"sv, util::make_string_ref_uint(balloc, 0));
290   assert_stdsv_equal("123"sv, util::make_string_ref_uint(balloc, 123));
291   assert_stdsv_equal(
292       "18446744073709551615"sv,
293       util::make_string_ref_uint(balloc, 18446744073709551615ULL));
294 }
295 
test_util_utos_unit(void)296 void test_util_utos_unit(void) {
297   assert_stdstring_equal("0", util::utos_unit(0));
298   assert_stdstring_equal("1023", util::utos_unit(1023));
299   assert_stdstring_equal("1K", util::utos_unit(1024));
300   assert_stdstring_equal("1K", util::utos_unit(1025));
301   assert_stdstring_equal("1M", util::utos_unit(1 << 20));
302   assert_stdstring_equal("1G", util::utos_unit(1 << 30));
303   assert_stdstring_equal("1024G", util::utos_unit(1LL << 40));
304 }
305 
test_util_utos_funit(void)306 void test_util_utos_funit(void) {
307   assert_stdstring_equal("0", util::utos_funit(0));
308   assert_stdstring_equal("1023", util::utos_funit(1023));
309   assert_stdstring_equal("1.00K", util::utos_funit(1024));
310   assert_stdstring_equal("1.00K", util::utos_funit(1025));
311   assert_stdstring_equal("1.09K", util::utos_funit(1119));
312   assert_stdstring_equal("1.27K", util::utos_funit(1300));
313   assert_stdstring_equal("1.00M", util::utos_funit(1 << 20));
314   assert_stdstring_equal("1.18M", util::utos_funit(1234567));
315   assert_stdstring_equal("1.00G", util::utos_funit(1 << 30));
316   assert_stdstring_equal("4492450797.23G",
317                          util::utos_funit(4823732313248234343LL));
318   assert_stdstring_equal("1024.00G", util::utos_funit(1LL << 40));
319 }
320 
test_util_parse_uint_with_unit(void)321 void test_util_parse_uint_with_unit(void) {
322   assert_int64(0, ==, util::parse_uint_with_unit("0").value_or(-1));
323   assert_int64(1023, ==, util::parse_uint_with_unit("1023").value_or(-1));
324   assert_int64(1024, ==, util::parse_uint_with_unit("1k").value_or(-1));
325   assert_int64(2048, ==, util::parse_uint_with_unit("2K").value_or(-1));
326   assert_int64(1 << 20, ==, util::parse_uint_with_unit("1m").value_or(-1));
327   assert_int64(1 << 21, ==, util::parse_uint_with_unit("2M").value_or(-1));
328   assert_int64(1 << 30, ==, util::parse_uint_with_unit("1g").value_or(-1));
329   assert_int64(1LL << 31, ==, util::parse_uint_with_unit("2G").value_or(-1));
330   assert_int64(9223372036854775807LL, ==,
331                util::parse_uint_with_unit("9223372036854775807").value_or(-1));
332   // check overflow case
333   assert_false(util::parse_uint_with_unit("9223372036854775808"));
334   assert_false(util::parse_uint_with_unit("10000000000000000000"));
335   assert_false(util::parse_uint_with_unit("9223372036854775807G"));
336   // bad characters
337   assert_false(util::parse_uint_with_unit("1.1"));
338   assert_false(util::parse_uint_with_unit("1a"));
339   assert_false(util::parse_uint_with_unit("a1"));
340   assert_false(util::parse_uint_with_unit("1T"));
341   assert_false(util::parse_uint_with_unit(""));
342 }
343 
test_util_parse_uint(void)344 void test_util_parse_uint(void) {
345   assert_int64(0, ==, util::parse_uint("0").value_or(-1));
346   assert_int64(1023, ==, util::parse_uint("1023").value_or(-1));
347   assert_false(util::parse_uint("1k"));
348   assert_int64(9223372036854775807LL, ==,
349                util::parse_uint("9223372036854775807").value_or(-1));
350   // check overflow case
351   assert_false(util::parse_uint("9223372036854775808"));
352   assert_false(util::parse_uint("10000000000000000000"));
353   // bad characters
354   assert_false(util::parse_uint("1.1"));
355   assert_false(util::parse_uint("1a"));
356   assert_false(util::parse_uint("a1"));
357   assert_false(util::parse_uint("1T"));
358   assert_false(util::parse_uint(""));
359 }
360 
test_util_parse_duration_with_unit(void)361 void test_util_parse_duration_with_unit(void) {
362   auto inf = std::numeric_limits<double>::infinity();
363 
364   assert_double(0., ==, util::parse_duration_with_unit("0").value_or(inf));
365   assert_double(123., ==, util::parse_duration_with_unit("123").value_or(inf));
366   assert_double(123., ==, util::parse_duration_with_unit("123s").value_or(inf));
367   assert_double(0.500, ==,
368                 util::parse_duration_with_unit("500ms").value_or(inf));
369   assert_double(123., ==, util::parse_duration_with_unit("123S").value_or(inf));
370   assert_double(0.500, ==,
371                 util::parse_duration_with_unit("500MS").value_or(inf));
372   assert_double(180, ==, util::parse_duration_with_unit("3m").value_or(inf));
373   assert_double(3600 * 5, ==,
374                 util::parse_duration_with_unit("5h").value_or(inf));
375 
376   // check overflow case
377   assert_false(util::parse_duration_with_unit("9223372036854775808"));
378   // bad characters
379   assert_false(util::parse_duration_with_unit("0u"));
380   assert_false(util::parse_duration_with_unit("0xs"));
381   assert_false(util::parse_duration_with_unit("0mt"));
382   assert_false(util::parse_duration_with_unit("0mss"));
383   assert_false(util::parse_duration_with_unit("s"));
384   assert_false(util::parse_duration_with_unit("ms"));
385 }
386 
test_util_duration_str(void)387 void test_util_duration_str(void) {
388   assert_stdstring_equal("0", util::duration_str(0.));
389   assert_stdstring_equal("1s", util::duration_str(1.));
390   assert_stdstring_equal("500ms", util::duration_str(0.5));
391   assert_stdstring_equal("1500ms", util::duration_str(1.5));
392   assert_stdstring_equal("2m", util::duration_str(120.));
393   assert_stdstring_equal("121s", util::duration_str(121.));
394   assert_stdstring_equal("1h", util::duration_str(3600.));
395 }
396 
test_util_format_duration(void)397 void test_util_format_duration(void) {
398   assert_stdstring_equal("0us",
399                          util::format_duration(std::chrono::microseconds(0)));
400   assert_stdstring_equal("999us",
401                          util::format_duration(std::chrono::microseconds(999)));
402   assert_stdstring_equal(
403       "1.00ms", util::format_duration(std::chrono::microseconds(1000)));
404   assert_stdstring_equal(
405       "1.09ms", util::format_duration(std::chrono::microseconds(1090)));
406   assert_stdstring_equal(
407       "1.01ms", util::format_duration(std::chrono::microseconds(1009)));
408   assert_stdstring_equal(
409       "999.99ms", util::format_duration(std::chrono::microseconds(999990)));
410   assert_stdstring_equal(
411       "1.00s", util::format_duration(std::chrono::microseconds(1000000)));
412   assert_stdstring_equal(
413       "1.05s", util::format_duration(std::chrono::microseconds(1050000)));
414 
415   assert_stdstring_equal("0us", util::format_duration(0.));
416   assert_stdstring_equal("999us", util::format_duration(0.000999));
417   assert_stdstring_equal("1.00ms", util::format_duration(0.001));
418   assert_stdstring_equal("1.09ms", util::format_duration(0.00109));
419   assert_stdstring_equal("1.01ms", util::format_duration(0.001009));
420   assert_stdstring_equal("999.99ms", util::format_duration(0.99999));
421   assert_stdstring_equal("1.00s", util::format_duration(1.));
422   assert_stdstring_equal("1.05s", util::format_duration(1.05));
423 }
424 
test_util_starts_with(void)425 void test_util_starts_with(void) {
426   assert_true(util::starts_with("foo"_sr, "foo"_sr));
427   assert_true(util::starts_with("fooo"_sr, "foo"_sr));
428   assert_true(util::starts_with("ofoo"_sr, StringRef{}));
429   assert_false(util::starts_with("ofoo"_sr, "foo"_sr));
430 
431   assert_true(util::istarts_with("FOO"_sr, "fOO"_sr));
432   assert_true(util::istarts_with("ofoo"_sr, StringRef{}));
433   assert_true(util::istarts_with("fOOo"_sr, "Foo"_sr));
434   assert_false(util::istarts_with("ofoo"_sr, "foo"_sr));
435 }
436 
test_util_ends_with(void)437 void test_util_ends_with(void) {
438   assert_true(util::ends_with("foo"_sr, "foo"_sr));
439   assert_true(util::ends_with("foo"_sr, StringRef{}));
440   assert_true(util::ends_with("ofoo"_sr, "foo"_sr));
441   assert_false(util::ends_with("ofoo"_sr, "fo"_sr));
442 
443   assert_true(util::iends_with("fOo"_sr, "Foo"_sr));
444   assert_true(util::iends_with("foo"_sr, StringRef{}));
445   assert_true(util::iends_with("oFoo"_sr, "fOO"_sr));
446   assert_false(util::iends_with("ofoo"_sr, "fo"_sr));
447 }
448 
test_util_parse_http_date(void)449 void test_util_parse_http_date(void) {
450   assert_int64(1001939696, ==,
451                util::parse_http_date("Mon, 1 Oct 2001 12:34:56 GMT"_sr));
452 }
453 
test_util_localtime_date(void)454 void test_util_localtime_date(void) {
455   auto tz = getenv("TZ");
456   if (tz) {
457     tz = strdup(tz);
458   }
459 #ifdef __linux__
460   setenv("TZ", "NZST-12:00:00:00", 1);
461 #else  // !__linux__
462   setenv("TZ", ":Pacific/Auckland", 1);
463 #endif // !__linux__
464   tzset();
465 
466   assert_stdstring_equal("02/Oct/2001:00:34:56 +1200",
467                          util::common_log_date(1001939696));
468   assert_stdstring_equal("2001-10-02T00:34:56.123+12:00",
469                          util::iso8601_date(1001939696000LL + 123));
470 
471   std::array<char, 27> common_buf;
472 
473   assert_stdsv_equal(
474       "02/Oct/2001:00:34:56 +1200"sv,
475       util::format_common_log(common_buf.data(),
476                               std::chrono::system_clock::time_point(
477                                   std::chrono::seconds(1001939696))));
478 
479   std::array<char, 30> iso8601_buf;
480 
481   assert_stdsv_equal(
482       "2001-10-02T00:34:56.123+12:00"sv,
483       util::format_iso8601(iso8601_buf.data(),
484                            std::chrono::system_clock::time_point(
485                                std::chrono::milliseconds(1001939696123LL))));
486 
487   if (tz) {
488     setenv("TZ", tz, 1);
489     free(tz);
490   } else {
491     unsetenv("TZ");
492   }
493   tzset();
494 }
495 
test_util_get_uint64(void)496 void test_util_get_uint64(void) {
497   {
498     auto v = std::to_array<unsigned char>(
499         {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc});
500 
501     auto n = util::get_uint64(v.data());
502 
503     assert_uint64(0x01123456ff9aabbcULL, ==, n);
504   }
505   {
506     auto v = std::to_array<unsigned char>(
507         {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff});
508 
509     auto n = util::get_uint64(v.data());
510 
511     assert_uint64(0xffffffffffffffffULL, ==, n);
512   }
513 }
514 
test_util_parse_config_str_list(void)515 void test_util_parse_config_str_list(void) {
516   auto res = util::parse_config_str_list("a"_sr);
517   assert_size(1, ==, res.size());
518   assert_stdstring_equal("a", res[0]);
519 
520   res = util::parse_config_str_list("a,"_sr);
521   assert_size(2, ==, res.size());
522   assert_stdstring_equal("a", res[0]);
523   assert_stdstring_equal("", res[1]);
524 
525   res = util::parse_config_str_list(":a::"_sr, ':');
526   assert_size(4, ==, res.size());
527   assert_stdstring_equal("", res[0]);
528   assert_stdstring_equal("a", res[1]);
529   assert_stdstring_equal("", res[2]);
530   assert_stdstring_equal("", res[3]);
531 
532   res = util::parse_config_str_list(StringRef{});
533   assert_size(1, ==, res.size());
534   assert_stdstring_equal("", res[0]);
535 
536   res = util::parse_config_str_list("alpha,bravo,charlie"_sr);
537   assert_size(3, ==, res.size());
538   assert_stdstring_equal("alpha", res[0]);
539   assert_stdstring_equal("bravo", res[1]);
540   assert_stdstring_equal("charlie", res[2]);
541 }
542 
test_util_make_http_hostport(void)543 void test_util_make_http_hostport(void) {
544   BlockAllocator balloc(4096, 4096);
545 
546   assert_stdsv_equal("localhost"sv,
547                      util::make_http_hostport(balloc, "localhost"_sr, 80));
548   assert_stdsv_equal("[::1]"sv,
549                      util::make_http_hostport(balloc, "::1"_sr, 443));
550   assert_stdsv_equal("localhost:3000"sv,
551                      util::make_http_hostport(balloc, "localhost"_sr, 3000));
552 }
553 
test_util_make_hostport(void)554 void test_util_make_hostport(void) {
555   std::array<char, util::max_hostport> hostport_buf;
556   assert_stdsv_equal(
557       "localhost:80"sv,
558       util::make_hostport(std::begin(hostport_buf), "localhost"_sr, 80));
559   assert_stdsv_equal(
560       "[::1]:443"sv,
561       util::make_hostport(std::begin(hostport_buf), "::1"_sr, 443));
562 
563   BlockAllocator balloc(4096, 4096);
564   assert_stdsv_equal("localhost:80"sv,
565                      util::make_hostport(balloc, "localhost"_sr, 80));
566   assert_stdsv_equal("[::1]:443"sv, util::make_hostport(balloc, "::1"_sr, 443));
567 }
568 
test_util_random_alpha_digit(void)569 void test_util_random_alpha_digit(void) {
570   std::random_device rd;
571   std::mt19937 gen(rd());
572   std::array<uint8_t, 19> data;
573 
574   auto p = util::random_alpha_digit(std::begin(data), std::end(data), gen);
575 
576   assert_true(std::end(data) == p);
577 
578   for (auto b : data) {
579     assert_true(('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') ||
580                 ('0' <= b && b <= '9'));
581   }
582 }
583 
test_util_format_hex(void)584 void test_util_format_hex(void) {
585   BlockAllocator balloc(4096, 4096);
586 
587   assert_stdsv_equal("0ff0"sv,
588                      util::format_hex(balloc, std::span{"\x0f\xf0"_sr}));
589   assert_stdsv_equal(""sv,
590                      util::format_hex(balloc, std::span<const uint8_t>{}));
591 
592   union T {
593     uint16_t x;
594     uint8_t y[2];
595   };
596 
597   auto t = T{.y = {0xbe, 0xef}};
598 
599   assert_stdstring_equal("beef", util::format_hex(std::span{&t.x, 1}));
600 
601   std::string o;
602   o.resize(4);
603 
604   assert_true(std::end(o) ==
605               util::format_hex(std::begin(o), std::span{&t.x, 1}));
606   assert_stdstring_equal("beef", o);
607 
608   struct S {
609     uint8_t x[8];
610   };
611 
612   auto s = S{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf8}};
613 
614   assert_stdstring_equal("01020304050607f8", util::format_hex(s.x));
615 }
616 
test_util_is_hex_string(void)617 void test_util_is_hex_string(void) {
618   assert_true(util::is_hex_string(StringRef{}));
619   assert_true(util::is_hex_string("0123456789abcdef"_sr));
620   assert_true(util::is_hex_string("0123456789ABCDEF"_sr));
621   assert_false(util::is_hex_string("000"_sr));
622   assert_false(util::is_hex_string("XX"_sr));
623 }
624 
test_util_decode_hex(void)625 void test_util_decode_hex(void) {
626   BlockAllocator balloc(4096, 4096);
627 
628   assert_stdsv_equal("\x0f\xf0"sv,
629                      StringRef{util::decode_hex(balloc, "0ff0"_sr)});
630   assert_stdsv_equal(""sv, StringRef{util::decode_hex(balloc, StringRef{})});
631 }
632 
test_util_extract_host(void)633 void test_util_extract_host(void) {
634   assert_stdsv_equal("foo"sv, util::extract_host("foo"_sr));
635   assert_stdsv_equal("foo"sv, util::extract_host("foo:"_sr));
636   assert_stdsv_equal("foo"sv, util::extract_host("foo:0"_sr));
637   assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]"_sr));
638   assert_stdsv_equal("[::1]"sv, util::extract_host("[::1]:"_sr));
639 
640   assert_true(util::extract_host(":foo"_sr).empty());
641   assert_true(util::extract_host("[::1"_sr).empty());
642   assert_true(util::extract_host("[::1]0"_sr).empty());
643   assert_true(util::extract_host(StringRef{}).empty());
644 }
645 
test_util_split_hostport(void)646 void test_util_split_hostport(void) {
647   assert_true(std::make_pair("foo"_sr, StringRef{}) ==
648               util::split_hostport("foo"_sr));
649   assert_true(std::make_pair("foo"_sr, "80"_sr) ==
650               util::split_hostport("foo:80"_sr));
651   assert_true(std::make_pair("::1"_sr, "80"_sr) ==
652               util::split_hostport("[::1]:80"_sr));
653   assert_true(std::make_pair("::1"_sr, StringRef{}) ==
654               util::split_hostport("[::1]"_sr));
655 
656   assert_true(std::make_pair(StringRef{}, StringRef{}) ==
657               util::split_hostport(StringRef{}));
658   assert_true(std::make_pair(StringRef{}, StringRef{}) ==
659               util::split_hostport("[::1]:"_sr));
660   assert_true(std::make_pair(StringRef{}, StringRef{}) ==
661               util::split_hostport("foo:"_sr));
662   assert_true(std::make_pair(StringRef{}, StringRef{}) ==
663               util::split_hostport("[::1:"_sr));
664   assert_true(std::make_pair(StringRef{}, StringRef{}) ==
665               util::split_hostport("[::1]80"_sr));
666 }
667 
test_util_split_str(void)668 void test_util_split_str(void) {
669   assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ','));
670   assert_true(std::vector<StringRef>{"alpha"_sr} ==
671               util::split_str("alpha"_sr, ','));
672   assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) ==
673               util::split_str("alpha,"_sr, ','));
674   assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr}) ==
675               util::split_str("alpha,bravo"_sr, ','));
676   assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) ==
677               util::split_str("alpha,bravo,charlie"_sr, ','));
678   assert_true((std::vector<StringRef>{"alpha"_sr, "bravo"_sr, "charlie"_sr}) ==
679               util::split_str("alpha,bravo,charlie"_sr, ',', 0));
680   assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 1));
681   assert_true(std::vector<StringRef>{""_sr} == util::split_str(""_sr, ',', 2));
682   assert_true((std::vector<StringRef>{"alpha"_sr, "bravo,charlie"_sr}) ==
683               util::split_str("alpha,bravo,charlie"_sr, ',', 2));
684   assert_true(std::vector<StringRef>{"alpha"_sr} ==
685               util::split_str("alpha"_sr, ',', 2));
686   assert_true((std::vector<StringRef>{"alpha"_sr, ""_sr}) ==
687               util::split_str("alpha,"_sr, ',', 2));
688   assert_true(std::vector<StringRef>{"alpha"_sr} ==
689               util::split_str("alpha"_sr, ',', 0));
690   assert_true(std::vector<StringRef>{"alpha,bravo,charlie"_sr} ==
691               util::split_str("alpha,bravo,charlie"_sr, ',', 1));
692 }
693 
test_util_rstrip(void)694 void test_util_rstrip(void) {
695   BlockAllocator balloc(4096, 4096);
696 
697   assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha"_sr));
698   assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha "_sr));
699   assert_stdsv_equal("alpha"sv, util::rstrip(balloc, "alpha \t"_sr));
700   assert_stdsv_equal(""sv, util::rstrip(balloc, ""_sr));
701   assert_stdsv_equal(""sv, util::rstrip(balloc, "\t\t\t   "_sr));
702 }
703 
704 } // namespace shrpx
705