diff options
Diffstat (limited to '')
-rw-r--r-- | src/util_test.cc | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/src/util_test.cc b/src/util_test.cc new file mode 100644 index 0000000..0ac0f1d --- /dev/null +++ b/src/util_test.cc @@ -0,0 +1,707 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2013 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "util_test.h" + +#include <cstring> +#include <iostream> +#include <random> + +#include <CUnit/CUnit.h> + +#include <nghttp2/nghttp2.h> + +#include "util.h" +#include "template.h" + +using namespace nghttp2; + +namespace shrpx { + +void test_util_streq(void) { + CU_ASSERT( + util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); + CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), + StringRef::from_lit("alphabravo"))); + CU_ASSERT(!util::streq(StringRef::from_lit("alphabravo"), + StringRef::from_lit("alpha"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); + CU_ASSERT(!util::streq(StringRef{}, StringRef::from_lit("a"))); + CU_ASSERT(util::streq(StringRef{}, StringRef{})); + CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), StringRef{})); + + CU_ASSERT( + !util::streq(StringRef::from_lit("alph"), StringRef::from_lit("alpha"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alph"))); + CU_ASSERT( + !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); + + CU_ASSERT(util::streq_l("alpha", "alpha", 5)); + CU_ASSERT(util::streq_l("alpha", "alphabravo", 5)); + CU_ASSERT(!util::streq_l("alpha", "alphabravo", 6)); + CU_ASSERT(!util::streq_l("alphabravo", "alpha", 5)); + CU_ASSERT(!util::streq_l("alpha", "alphA", 5)); + CU_ASSERT(!util::streq_l("", "a", 1)); + CU_ASSERT(util::streq_l("", "", 0)); + CU_ASSERT(!util::streq_l("alpha", "", 0)); +} + +void test_util_strieq(void) { + CU_ASSERT(util::strieq(std::string("alpha"), std::string("alpha"))); + CU_ASSERT(util::strieq(std::string("alpha"), std::string("AlPhA"))); + CU_ASSERT(util::strieq(std::string(), std::string())); + CU_ASSERT(!util::strieq(std::string("alpha"), std::string("AlPhA "))); + CU_ASSERT(!util::strieq(std::string(), std::string("AlPhA "))); + + CU_ASSERT( + util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); + CU_ASSERT( + util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("AlPhA"))); + CU_ASSERT(util::strieq(StringRef{}, StringRef{})); + CU_ASSERT(!util::strieq(StringRef::from_lit("alpha"), + StringRef::from_lit("AlPhA "))); + CU_ASSERT( + !util::strieq(StringRef::from_lit(""), StringRef::from_lit("AlPhA "))); + + CU_ASSERT(util::strieq_l("alpha", "alpha", 5)); + CU_ASSERT(util::strieq_l("alpha", "AlPhA", 5)); + CU_ASSERT(util::strieq_l("", static_cast<const char *>(nullptr), 0)); + CU_ASSERT(!util::strieq_l("alpha", "AlPhA ", 6)); + CU_ASSERT(!util::strieq_l("", "AlPhA ", 6)); + + CU_ASSERT(util::strieq_l("alpha", StringRef::from_lit("alpha"))); + CU_ASSERT(util::strieq_l("alpha", StringRef::from_lit("AlPhA"))); + CU_ASSERT(util::strieq_l("", StringRef{})); + CU_ASSERT(!util::strieq_l("alpha", StringRef::from_lit("AlPhA "))); + CU_ASSERT(!util::strieq_l("", StringRef::from_lit("AlPhA "))); +} + +void test_util_inp_strlower(void) { + std::string a("alPha"); + util::inp_strlower(a); + CU_ASSERT("alpha" == a); + + a = "ALPHA123BRAVO"; + util::inp_strlower(a); + CU_ASSERT("alpha123bravo" == a); + + a = ""; + util::inp_strlower(a); + CU_ASSERT("" == a); +} + +void test_util_to_base64(void) { + BlockAllocator balloc(4096, 4096); + + CU_ASSERT("AAA++B/=" == + util::to_base64(balloc, StringRef::from_lit("AAA--B_"))); + CU_ASSERT("AAA++B/B" == + util::to_base64(balloc, StringRef::from_lit("AAA--B_B"))); +} + +void test_util_to_token68(void) { + std::string x = "AAA++B/="; + util::to_token68(x); + CU_ASSERT("AAA--B_" == x); + + x = "AAA++B/B"; + util::to_token68(x); + CU_ASSERT("AAA--B_B" == x); +} + +void test_util_percent_encode_token(void) { + BlockAllocator balloc(4096, 4096); + CU_ASSERT("h2" == + util::percent_encode_token(balloc, StringRef::from_lit("h2"))); + CU_ASSERT("h3~" == + util::percent_encode_token(balloc, StringRef::from_lit("h3~"))); + CU_ASSERT("100%25" == + util::percent_encode_token(balloc, StringRef::from_lit("100%"))); + CU_ASSERT("http%202" == + util::percent_encode_token(balloc, StringRef::from_lit("http 2"))); +} + +void test_util_percent_decode(void) { + { + std::string s = "%66%6F%6f%62%61%72"; + CU_ASSERT("foobar" == util::percent_decode(std::begin(s), std::end(s))); + } + { + std::string s = "%66%6"; + CU_ASSERT("f%6" == util::percent_decode(std::begin(s), std::end(s))); + } + { + std::string s = "%66%"; + CU_ASSERT("f%" == util::percent_decode(std::begin(s), std::end(s))); + } + BlockAllocator balloc(1024, 1024); + + CU_ASSERT("foobar" == util::percent_decode( + balloc, StringRef::from_lit("%66%6F%6f%62%61%72"))); + + CU_ASSERT("f%6" == + util::percent_decode(balloc, StringRef::from_lit("%66%6"))); + + CU_ASSERT("f%" == util::percent_decode(balloc, StringRef::from_lit("%66%"))); +} + +void test_util_quote_string(void) { + BlockAllocator balloc(4096, 4096); + CU_ASSERT("alpha" == + util::quote_string(balloc, StringRef::from_lit("alpha"))); + CU_ASSERT("" == util::quote_string(balloc, StringRef::from_lit(""))); + CU_ASSERT("\\\"alpha\\\"" == + util::quote_string(balloc, StringRef::from_lit("\"alpha\""))); +} + +void test_util_utox(void) { + CU_ASSERT("0" == util::utox(0)); + CU_ASSERT("1" == util::utox(1)); + CU_ASSERT("F" == util::utox(15)); + CU_ASSERT("10" == util::utox(16)); + CU_ASSERT("3B9ACA07" == util::utox(1000000007)); + CU_ASSERT("100000000" == util::utox(1LL << 32)); +} + +void test_util_http_date(void) { + CU_ASSERT("Thu, 01 Jan 1970 00:00:00 GMT" == util::http_date(0)); + CU_ASSERT("Wed, 29 Feb 2012 09:15:16 GMT" == util::http_date(1330506916)); + + std::array<char, 30> http_buf; + + CU_ASSERT("Thu, 01 Jan 1970 00:00:00 GMT" == + util::format_http_date(http_buf.data(), + std::chrono::system_clock::time_point())); + CU_ASSERT("Wed, 29 Feb 2012 09:15:16 GMT" == + util::format_http_date(http_buf.data(), + std::chrono::system_clock::time_point( + std::chrono::seconds(1330506916)))); +} + +void test_util_select_h2(void) { + const unsigned char *out = nullptr; + unsigned char outlen = 0; + + // Check single entry and select it. + const unsigned char t1[] = "\x2h2"; + CU_ASSERT(util::select_h2(&out, &outlen, t1, sizeof(t1) - 1)); + CU_ASSERT( + memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0); + CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen); + + out = nullptr; + outlen = 0; + + // Check the case where id is correct but length is invalid and too + // long. + const unsigned char t2[] = "\x6h2-14"; + CU_ASSERT(!util::select_h2(&out, &outlen, t2, sizeof(t2) - 1)); + + // Check the case where h2 is located after bogus ID. + const unsigned char t3[] = "\x2h3\x2h2"; + CU_ASSERT(util::select_h2(&out, &outlen, t3, sizeof(t3) - 1)); + + CU_ASSERT( + memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0); + CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen); + + out = nullptr; + outlen = 0; + + // Check the case that last entry's length is invalid and too long. + const unsigned char t4[] = "\x2h3\x6h2-14"; + CU_ASSERT(!util::select_h2(&out, &outlen, t4, sizeof(t4) - 1)); + + // Check the case that all entries are not supported. + const unsigned char t5[] = "\x2h3\x2h4"; + CU_ASSERT(!util::select_h2(&out, &outlen, t5, sizeof(t5) - 1)); + + // Check the case where 2 values are eligible, but last one is + // picked up because it has precedence over the other. + const unsigned char t6[] = "\x5h2-14\x5h2-16"; + CU_ASSERT(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1)); + CU_ASSERT(util::streq(NGHTTP2_H2_16, StringRef{out, outlen})); +} + +void test_util_ipv6_numeric_addr(void) { + CU_ASSERT(util::ipv6_numeric_addr("::1")); + CU_ASSERT(util::ipv6_numeric_addr("2001:0db8:85a3:0042:1000:8a2e:0370:7334")); + // IPv4 + CU_ASSERT(!util::ipv6_numeric_addr("127.0.0.1")); + // not numeric address + CU_ASSERT(!util::ipv6_numeric_addr("localhost")); +} + +void test_util_utos(void) { + uint8_t buf[32]; + + CU_ASSERT(("0" == StringRef{buf, util::utos(buf, 0)})); + CU_ASSERT(("123" == StringRef{buf, util::utos(buf, 123)})); + CU_ASSERT(("18446744073709551615" == + StringRef{buf, util::utos(buf, 18446744073709551615ULL)})); +} + +void test_util_make_string_ref_uint(void) { + BlockAllocator balloc(1024, 1024); + + CU_ASSERT("0" == util::make_string_ref_uint(balloc, 0)); + CU_ASSERT("123" == util::make_string_ref_uint(balloc, 123)); + CU_ASSERT("18446744073709551615" == + util::make_string_ref_uint(balloc, 18446744073709551615ULL)); +} + +void test_util_utos_unit(void) { + CU_ASSERT("0" == util::utos_unit(0)); + CU_ASSERT("1023" == util::utos_unit(1023)); + CU_ASSERT("1K" == util::utos_unit(1024)); + CU_ASSERT("1K" == util::utos_unit(1025)); + CU_ASSERT("1M" == util::utos_unit(1 << 20)); + CU_ASSERT("1G" == util::utos_unit(1 << 30)); + CU_ASSERT("1024G" == util::utos_unit(1LL << 40)); +} + +void test_util_utos_funit(void) { + CU_ASSERT("0" == util::utos_funit(0)); + CU_ASSERT("1023" == util::utos_funit(1023)); + CU_ASSERT("1.00K" == util::utos_funit(1024)); + CU_ASSERT("1.00K" == util::utos_funit(1025)); + CU_ASSERT("1.09K" == util::utos_funit(1119)); + CU_ASSERT("1.27K" == util::utos_funit(1300)); + CU_ASSERT("1.00M" == util::utos_funit(1 << 20)); + CU_ASSERT("1.18M" == util::utos_funit(1234567)); + CU_ASSERT("1.00G" == util::utos_funit(1 << 30)); + CU_ASSERT("4492450797.23G" == util::utos_funit(4823732313248234343LL)); + CU_ASSERT("1024.00G" == util::utos_funit(1LL << 40)); +} + +void test_util_parse_uint_with_unit(void) { + CU_ASSERT(0 == util::parse_uint_with_unit("0")); + CU_ASSERT(1023 == util::parse_uint_with_unit("1023")); + CU_ASSERT(1024 == util::parse_uint_with_unit("1k")); + CU_ASSERT(2048 == util::parse_uint_with_unit("2K")); + CU_ASSERT(1 << 20 == util::parse_uint_with_unit("1m")); + CU_ASSERT(1 << 21 == util::parse_uint_with_unit("2M")); + CU_ASSERT(1 << 30 == util::parse_uint_with_unit("1g")); + CU_ASSERT(1LL << 31 == util::parse_uint_with_unit("2G")); + CU_ASSERT(9223372036854775807LL == + util::parse_uint_with_unit("9223372036854775807")); + // check overflow case + CU_ASSERT(-1 == util::parse_uint_with_unit("9223372036854775808")); + CU_ASSERT(-1 == util::parse_uint_with_unit("10000000000000000000")); + CU_ASSERT(-1 == util::parse_uint_with_unit("9223372036854775807G")); + // bad characters + CU_ASSERT(-1 == util::parse_uint_with_unit("1.1")); + CU_ASSERT(-1 == util::parse_uint_with_unit("1a")); + CU_ASSERT(-1 == util::parse_uint_with_unit("a1")); + CU_ASSERT(-1 == util::parse_uint_with_unit("1T")); + CU_ASSERT(-1 == util::parse_uint_with_unit("")); +} + +void test_util_parse_uint(void) { + CU_ASSERT(0 == util::parse_uint("0")); + CU_ASSERT(1023 == util::parse_uint("1023")); + CU_ASSERT(-1 == util::parse_uint("1k")); + CU_ASSERT(9223372036854775807LL == util::parse_uint("9223372036854775807")); + // check overflow case + CU_ASSERT(-1 == util::parse_uint("9223372036854775808")); + CU_ASSERT(-1 == util::parse_uint("10000000000000000000")); + // bad characters + CU_ASSERT(-1 == util::parse_uint("1.1")); + CU_ASSERT(-1 == util::parse_uint("1a")); + CU_ASSERT(-1 == util::parse_uint("a1")); + CU_ASSERT(-1 == util::parse_uint("1T")); + CU_ASSERT(-1 == util::parse_uint("")); +} + +void test_util_parse_duration_with_unit(void) { + CU_ASSERT(0. == util::parse_duration_with_unit("0")); + CU_ASSERT(123. == util::parse_duration_with_unit("123")); + CU_ASSERT(123. == util::parse_duration_with_unit("123s")); + CU_ASSERT(0.500 == util::parse_duration_with_unit("500ms")); + CU_ASSERT(123. == util::parse_duration_with_unit("123S")); + CU_ASSERT(0.500 == util::parse_duration_with_unit("500MS")); + CU_ASSERT(180 == util::parse_duration_with_unit("3m")); + CU_ASSERT(3600 * 5 == util::parse_duration_with_unit("5h")); + + auto err = std::numeric_limits<double>::infinity(); + // check overflow case + CU_ASSERT(err == util::parse_duration_with_unit("9223372036854775808")); + // bad characters + CU_ASSERT(err == util::parse_duration_with_unit("0u")); + CU_ASSERT(err == util::parse_duration_with_unit("0xs")); + CU_ASSERT(err == util::parse_duration_with_unit("0mt")); + CU_ASSERT(err == util::parse_duration_with_unit("0mss")); + CU_ASSERT(err == util::parse_duration_with_unit("s")); + CU_ASSERT(err == util::parse_duration_with_unit("ms")); +} + +void test_util_duration_str(void) { + CU_ASSERT("0" == util::duration_str(0.)); + CU_ASSERT("1s" == util::duration_str(1.)); + CU_ASSERT("500ms" == util::duration_str(0.5)); + CU_ASSERT("1500ms" == util::duration_str(1.5)); + CU_ASSERT("2m" == util::duration_str(120.)); + CU_ASSERT("121s" == util::duration_str(121.)); + CU_ASSERT("1h" == util::duration_str(3600.)); +} + +void test_util_format_duration(void) { + CU_ASSERT("0us" == util::format_duration(std::chrono::microseconds(0))); + CU_ASSERT("999us" == util::format_duration(std::chrono::microseconds(999))); + CU_ASSERT("1.00ms" == util::format_duration(std::chrono::microseconds(1000))); + CU_ASSERT("1.09ms" == util::format_duration(std::chrono::microseconds(1090))); + CU_ASSERT("1.01ms" == util::format_duration(std::chrono::microseconds(1009))); + CU_ASSERT("999.99ms" == + util::format_duration(std::chrono::microseconds(999990))); + CU_ASSERT("1.00s" == + util::format_duration(std::chrono::microseconds(1000000))); + CU_ASSERT("1.05s" == + util::format_duration(std::chrono::microseconds(1050000))); + + CU_ASSERT("0us" == util::format_duration(0.)); + CU_ASSERT("999us" == util::format_duration(0.000999)); + CU_ASSERT("1.00ms" == util::format_duration(0.001)); + CU_ASSERT("1.09ms" == util::format_duration(0.00109)); + CU_ASSERT("1.01ms" == util::format_duration(0.001009)); + CU_ASSERT("999.99ms" == util::format_duration(0.99999)); + CU_ASSERT("1.00s" == util::format_duration(1.)); + CU_ASSERT("1.05s" == util::format_duration(1.05)); +} + +void test_util_starts_with(void) { + CU_ASSERT(util::starts_with(StringRef::from_lit("foo"), + StringRef::from_lit("foo"))); + CU_ASSERT(util::starts_with(StringRef::from_lit("fooo"), + StringRef::from_lit("foo"))); + CU_ASSERT(util::starts_with(StringRef::from_lit("ofoo"), StringRef{})); + CU_ASSERT(!util::starts_with(StringRef::from_lit("ofoo"), + StringRef::from_lit("foo"))); + + CU_ASSERT(util::istarts_with(StringRef::from_lit("FOO"), + StringRef::from_lit("fOO"))); + CU_ASSERT(util::istarts_with(StringRef::from_lit("ofoo"), StringRef{})); + CU_ASSERT(util::istarts_with(StringRef::from_lit("fOOo"), + StringRef::from_lit("Foo"))); + CU_ASSERT(!util::istarts_with(StringRef::from_lit("ofoo"), + StringRef::from_lit("foo"))); + + CU_ASSERT(util::istarts_with_l(StringRef::from_lit("fOOo"), "Foo")); + CU_ASSERT(!util::istarts_with_l(StringRef::from_lit("ofoo"), "foo")); +} + +void test_util_ends_with(void) { + CU_ASSERT( + util::ends_with(StringRef::from_lit("foo"), StringRef::from_lit("foo"))); + CU_ASSERT(util::ends_with(StringRef::from_lit("foo"), StringRef{})); + CU_ASSERT( + util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("foo"))); + CU_ASSERT( + !util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("fo"))); + + CU_ASSERT( + util::iends_with(StringRef::from_lit("fOo"), StringRef::from_lit("Foo"))); + CU_ASSERT(util::iends_with(StringRef::from_lit("foo"), StringRef{})); + CU_ASSERT(util::iends_with(StringRef::from_lit("oFoo"), + StringRef::from_lit("fOO"))); + CU_ASSERT(!util::iends_with(StringRef::from_lit("ofoo"), + StringRef::from_lit("fo"))); + + CU_ASSERT(util::iends_with_l(StringRef::from_lit("oFoo"), "fOO")); + CU_ASSERT(!util::iends_with_l(StringRef::from_lit("ofoo"), "fo")); +} + +void test_util_parse_http_date(void) { + CU_ASSERT(1001939696 == util::parse_http_date(StringRef::from_lit( + "Mon, 1 Oct 2001 12:34:56 GMT"))); +} + +void test_util_localtime_date(void) { + auto tz = getenv("TZ"); + if (tz) { + tz = strdup(tz); + } +#ifdef __linux__ + setenv("TZ", "NZST-12:00:00:00", 1); +#else // !__linux__ + setenv("TZ", ":Pacific/Auckland", 1); +#endif // !__linux__ + tzset(); + + CU_ASSERT_STRING_EQUAL("02/Oct/2001:00:34:56 +1200", + util::common_log_date(1001939696).c_str()); + CU_ASSERT_STRING_EQUAL("2001-10-02T00:34:56.123+12:00", + util::iso8601_date(1001939696000LL + 123).c_str()); + + std::array<char, 27> common_buf; + + CU_ASSERT("02/Oct/2001:00:34:56 +1200" == + util::format_common_log(common_buf.data(), + std::chrono::system_clock::time_point( + std::chrono::seconds(1001939696)))); + + std::array<char, 30> iso8601_buf; + + CU_ASSERT( + "2001-10-02T00:34:56.123+12:00" == + util::format_iso8601(iso8601_buf.data(), + std::chrono::system_clock::time_point( + std::chrono::milliseconds(1001939696123LL)))); + + if (tz) { + setenv("TZ", tz, 1); + free(tz); + } else { + unsetenv("TZ"); + } + tzset(); +} + +void test_util_get_uint64(void) { + { + auto v = std::array<unsigned char, 8>{ + {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc}}; + + auto n = util::get_uint64(v.data()); + + CU_ASSERT(0x01123456ff9aabbcULL == n); + } + { + auto v = std::array<unsigned char, 8>{ + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; + + auto n = util::get_uint64(v.data()); + + CU_ASSERT(0xffffffffffffffffULL == n); + } +} + +void test_util_parse_config_str_list(void) { + auto res = util::parse_config_str_list(StringRef::from_lit("a")); + CU_ASSERT(1 == res.size()); + CU_ASSERT("a" == res[0]); + + res = util::parse_config_str_list(StringRef::from_lit("a,")); + CU_ASSERT(2 == res.size()); + CU_ASSERT("a" == res[0]); + CU_ASSERT("" == res[1]); + + res = util::parse_config_str_list(StringRef::from_lit(":a::"), ':'); + CU_ASSERT(4 == res.size()); + CU_ASSERT("" == res[0]); + CU_ASSERT("a" == res[1]); + CU_ASSERT("" == res[2]); + CU_ASSERT("" == res[3]); + + res = util::parse_config_str_list(StringRef{}); + CU_ASSERT(1 == res.size()); + CU_ASSERT("" == res[0]); + + res = util::parse_config_str_list(StringRef::from_lit("alpha,bravo,charlie")); + CU_ASSERT(3 == res.size()); + CU_ASSERT("alpha" == res[0]); + CU_ASSERT("bravo" == res[1]); + CU_ASSERT("charlie" == res[2]); +} + +void test_util_make_http_hostport(void) { + BlockAllocator balloc(4096, 4096); + + CU_ASSERT("localhost" == util::make_http_hostport( + balloc, StringRef::from_lit("localhost"), 80)); + CU_ASSERT("[::1]" == + util::make_http_hostport(balloc, StringRef::from_lit("::1"), 443)); + CU_ASSERT( + "localhost:3000" == + util::make_http_hostport(balloc, StringRef::from_lit("localhost"), 3000)); +} + +void test_util_make_hostport(void) { + std::array<char, util::max_hostport> hostport_buf; + CU_ASSERT("localhost:80" == + util::make_hostport(std::begin(hostport_buf), + StringRef::from_lit("localhost"), 80)); + CU_ASSERT("[::1]:443" == util::make_hostport(std::begin(hostport_buf), + StringRef::from_lit("::1"), + 443)); + + BlockAllocator balloc(4096, 4096); + CU_ASSERT("localhost:80" == + util::make_hostport(balloc, StringRef::from_lit("localhost"), 80)); + CU_ASSERT("[::1]:443" == + util::make_hostport(balloc, StringRef::from_lit("::1"), 443)); +} + +void test_util_strifind(void) { + CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), + StringRef::from_lit("gzip"))); + + CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), + StringRef::from_lit("dEflate"))); + + CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), + StringRef::from_lit("BZIP2"))); + + CU_ASSERT(util::strifind(StringRef::from_lit("nghttp2"), StringRef{})); + + // Be aware this fact + CU_ASSERT(!util::strifind(StringRef{}, StringRef{})); + + CU_ASSERT(!util::strifind(StringRef::from_lit("nghttp2"), + StringRef::from_lit("http1"))); +} + +void test_util_random_alpha_digit(void) { + std::random_device rd; + std::mt19937 gen(rd()); + std::array<uint8_t, 19> data; + + auto p = util::random_alpha_digit(std::begin(data), std::end(data), gen); + + CU_ASSERT(std::end(data) == p); + + for (auto b : data) { + CU_ASSERT(('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') || + ('0' <= b && b <= '9')); + } +} + +void test_util_format_hex(void) { + BlockAllocator balloc(4096, 4096); + + CU_ASSERT("0ff0" == + util::format_hex(balloc, StringRef::from_lit("\x0f\xf0"))); + CU_ASSERT("" == util::format_hex(balloc, StringRef::from_lit(""))); +} + +void test_util_is_hex_string(void) { + CU_ASSERT(util::is_hex_string(StringRef{})); + CU_ASSERT(util::is_hex_string(StringRef::from_lit("0123456789abcdef"))); + CU_ASSERT(util::is_hex_string(StringRef::from_lit("0123456789ABCDEF"))); + CU_ASSERT(!util::is_hex_string(StringRef::from_lit("000"))); + CU_ASSERT(!util::is_hex_string(StringRef::from_lit("XX"))); +} + +void test_util_decode_hex(void) { + BlockAllocator balloc(4096, 4096); + + CU_ASSERT("\x0f\xf0" == + util::decode_hex(balloc, StringRef::from_lit("0ff0"))); + CU_ASSERT("" == util::decode_hex(balloc, StringRef{})); +} + +void test_util_extract_host(void) { + CU_ASSERT(StringRef::from_lit("foo") == + util::extract_host(StringRef::from_lit("foo"))); + CU_ASSERT(StringRef::from_lit("foo") == + util::extract_host(StringRef::from_lit("foo:"))); + CU_ASSERT(StringRef::from_lit("foo") == + util::extract_host(StringRef::from_lit("foo:0"))); + CU_ASSERT(StringRef::from_lit("[::1]") == + util::extract_host(StringRef::from_lit("[::1]"))); + CU_ASSERT(StringRef::from_lit("[::1]") == + util::extract_host(StringRef::from_lit("[::1]:"))); + + CU_ASSERT(util::extract_host(StringRef::from_lit(":foo")).empty()); + CU_ASSERT(util::extract_host(StringRef::from_lit("[::1")).empty()); + CU_ASSERT(util::extract_host(StringRef::from_lit("[::1]0")).empty()); + CU_ASSERT(util::extract_host(StringRef{}).empty()); +} + +void test_util_split_hostport(void) { + CU_ASSERT(std::make_pair(StringRef::from_lit("foo"), StringRef{}) == + util::split_hostport(StringRef::from_lit("foo"))); + CU_ASSERT( + std::make_pair(StringRef::from_lit("foo"), StringRef::from_lit("80")) == + util::split_hostport(StringRef::from_lit("foo:80"))); + CU_ASSERT( + std::make_pair(StringRef::from_lit("::1"), StringRef::from_lit("80")) == + util::split_hostport(StringRef::from_lit("[::1]:80"))); + CU_ASSERT(std::make_pair(StringRef::from_lit("::1"), StringRef{}) == + util::split_hostport(StringRef::from_lit("[::1]"))); + + CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) == + util::split_hostport(StringRef{})); + CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) == + util::split_hostport(StringRef::from_lit("[::1]:"))); + CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) == + util::split_hostport(StringRef::from_lit("foo:"))); + CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) == + util::split_hostport(StringRef::from_lit("[::1:"))); + CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) == + util::split_hostport(StringRef::from_lit("[::1]80"))); +} + +void test_util_split_str(void) { + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("")} == + util::split_str(StringRef::from_lit(""), ',')); + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("alpha")} == + util::split_str(StringRef::from_lit("alpha"), ',')); + CU_ASSERT((std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("")}) == + util::split_str(StringRef::from_lit("alpha,"), ',')); + CU_ASSERT((std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("bravo")}) == + util::split_str(StringRef::from_lit("alpha,bravo"), ',')); + CU_ASSERT((std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("bravo"), + StringRef::from_lit("charlie")}) == + util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',')); + CU_ASSERT( + (std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("bravo"), + StringRef::from_lit("charlie")}) == + util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 0)); + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("")} == + util::split_str(StringRef::from_lit(""), ',', 1)); + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("")} == + util::split_str(StringRef::from_lit(""), ',', 2)); + CU_ASSERT( + (std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("bravo,charlie")}) == + util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 2)); + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("alpha")} == + util::split_str(StringRef::from_lit("alpha"), ',', 2)); + CU_ASSERT((std::vector<StringRef>{StringRef::from_lit("alpha"), + StringRef::from_lit("")}) == + util::split_str(StringRef::from_lit("alpha,"), ',', 2)); + CU_ASSERT(std::vector<StringRef>{StringRef::from_lit("alpha")} == + util::split_str(StringRef::from_lit("alpha"), ',', 0)); + CU_ASSERT( + std::vector<StringRef>{StringRef::from_lit("alpha,bravo,charlie")} == + util::split_str(StringRef::from_lit("alpha,bravo,charlie"), ',', 1)); +} + +void test_util_rstrip(void) { + BlockAllocator balloc(4096, 4096); + + CU_ASSERT("alpha" == util::rstrip(balloc, StringRef::from_lit("alpha"))); + CU_ASSERT("alpha" == util::rstrip(balloc, StringRef::from_lit("alpha "))); + CU_ASSERT("alpha" == util::rstrip(balloc, StringRef::from_lit("alpha \t"))); + CU_ASSERT("" == util::rstrip(balloc, StringRef::from_lit(""))); + CU_ASSERT("" == util::rstrip(balloc, StringRef::from_lit("\t\t\t "))); +} + +} // namespace shrpx |