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