12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2013 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "http2_test.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#include <cassert>
282c593315Sopenharmony_ci#include <cstring>
292c593315Sopenharmony_ci#include <iostream>
302c593315Sopenharmony_ci
312c593315Sopenharmony_ci#include <CUnit/CUnit.h>
322c593315Sopenharmony_ci
332c593315Sopenharmony_ci#include "url-parser/url_parser.h"
342c593315Sopenharmony_ci
352c593315Sopenharmony_ci#include "http2.h"
362c593315Sopenharmony_ci#include "util.h"
372c593315Sopenharmony_ci
382c593315Sopenharmony_ciusing namespace nghttp2;
392c593315Sopenharmony_ci
402c593315Sopenharmony_ci#define MAKE_NV(K, V)                                                          \
412c593315Sopenharmony_ci  {                                                                            \
422c593315Sopenharmony_ci    (uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1,                  \
432c593315Sopenharmony_ci        NGHTTP2_NV_FLAG_NONE                                                   \
442c593315Sopenharmony_ci  }
452c593315Sopenharmony_ci
462c593315Sopenharmony_cinamespace shrpx {
472c593315Sopenharmony_ci
482c593315Sopenharmony_cinamespace {
492c593315Sopenharmony_civoid check_nv(const HeaderRef &a, const nghttp2_nv *b) {
502c593315Sopenharmony_ci  CU_ASSERT(a.name.size() == b->namelen);
512c593315Sopenharmony_ci  CU_ASSERT(a.value.size() == b->valuelen);
522c593315Sopenharmony_ci  CU_ASSERT(memcmp(a.name.c_str(), b->name, b->namelen) == 0);
532c593315Sopenharmony_ci  CU_ASSERT(memcmp(a.value.c_str(), b->value, b->valuelen) == 0);
542c593315Sopenharmony_ci}
552c593315Sopenharmony_ci} // namespace
562c593315Sopenharmony_ci
572c593315Sopenharmony_civoid test_http2_add_header(void) {
582c593315Sopenharmony_ci  auto nva = Headers();
592c593315Sopenharmony_ci
602c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3,
612c593315Sopenharmony_ci                    false, -1);
622c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]);
632c593315Sopenharmony_ci  CU_ASSERT(!nva[0].no_index);
642c593315Sopenharmony_ci
652c593315Sopenharmony_ci  nva.clear();
662c593315Sopenharmony_ci
672c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0,
682c593315Sopenharmony_ci                    true, -1);
692c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("alpha", "") == nva[0]);
702c593315Sopenharmony_ci  CU_ASSERT(nva[0].no_index);
712c593315Sopenharmony_ci
722c593315Sopenharmony_ci  nva.clear();
732c593315Sopenharmony_ci
742c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2,
752c593315Sopenharmony_ci                    false, -1);
762c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
772c593315Sopenharmony_ci
782c593315Sopenharmony_ci  nva.clear();
792c593315Sopenharmony_ci
802c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2,
812c593315Sopenharmony_ci                    false, -1);
822c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
832c593315Sopenharmony_ci
842c593315Sopenharmony_ci  nva.clear();
852c593315Sopenharmony_ci
862c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"  b  ", 5,
872c593315Sopenharmony_ci                    false, -1);
882c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
892c593315Sopenharmony_ci
902c593315Sopenharmony_ci  nva.clear();
912c593315Sopenharmony_ci
922c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"  bravo  ",
932c593315Sopenharmony_ci                    9, false, -1);
942c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("a", "bravo") == nva[0]);
952c593315Sopenharmony_ci
962c593315Sopenharmony_ci  nva.clear();
972c593315Sopenharmony_ci
982c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"    ", 4,
992c593315Sopenharmony_ci                    false, -1);
1002c593315Sopenharmony_ci  CU_ASSERT(Headers::value_type("a", "") == nva[0]);
1012c593315Sopenharmony_ci
1022c593315Sopenharmony_ci  nva.clear();
1032c593315Sopenharmony_ci
1042c593315Sopenharmony_ci  http2::add_header(nva, (const uint8_t *)"te", 2, (const uint8_t *)"trailers",
1052c593315Sopenharmony_ci                    8, false, http2::HD_TE);
1062c593315Sopenharmony_ci  CU_ASSERT(http2::HD_TE == nva[0].token);
1072c593315Sopenharmony_ci}
1082c593315Sopenharmony_ci
1092c593315Sopenharmony_civoid test_http2_get_header(void) {
1102c593315Sopenharmony_ci  auto nva = Headers{{"alpha", "1"},         {"bravo", "2"}, {"bravo", "3"},
1112c593315Sopenharmony_ci                     {"charlie", "4"},       {"delta", "5"}, {"echo", "6"},
1122c593315Sopenharmony_ci                     {"content-length", "7"}};
1132c593315Sopenharmony_ci  const Headers::value_type *rv;
1142c593315Sopenharmony_ci  rv = http2::get_header(nva, "delta");
1152c593315Sopenharmony_ci  CU_ASSERT(rv != nullptr);
1162c593315Sopenharmony_ci  CU_ASSERT("delta" == rv->name);
1172c593315Sopenharmony_ci
1182c593315Sopenharmony_ci  rv = http2::get_header(nva, "bravo");
1192c593315Sopenharmony_ci  CU_ASSERT(rv != nullptr);
1202c593315Sopenharmony_ci  CU_ASSERT("bravo" == rv->name);
1212c593315Sopenharmony_ci
1222c593315Sopenharmony_ci  rv = http2::get_header(nva, "foxtrot");
1232c593315Sopenharmony_ci  CU_ASSERT(rv == nullptr);
1242c593315Sopenharmony_ci
1252c593315Sopenharmony_ci  http2::HeaderIndex hdidx;
1262c593315Sopenharmony_ci  http2::init_hdidx(hdidx);
1272c593315Sopenharmony_ci  hdidx[http2::HD_CONTENT_LENGTH] = 6;
1282c593315Sopenharmony_ci  rv = http2::get_header(hdidx, http2::HD_CONTENT_LENGTH, nva);
1292c593315Sopenharmony_ci  CU_ASSERT("content-length" == rv->name);
1302c593315Sopenharmony_ci}
1312c593315Sopenharmony_ci
1322c593315Sopenharmony_cinamespace {
1332c593315Sopenharmony_ciauto headers = HeaderRefs{
1342c593315Sopenharmony_ci    {StringRef::from_lit("alpha"), StringRef::from_lit("0"), true},
1352c593315Sopenharmony_ci    {StringRef::from_lit("bravo"), StringRef::from_lit("1")},
1362c593315Sopenharmony_ci    {StringRef::from_lit("connection"), StringRef::from_lit("2"), false,
1372c593315Sopenharmony_ci     http2::HD_CONNECTION},
1382c593315Sopenharmony_ci    {StringRef::from_lit("connection"), StringRef::from_lit("3"), false,
1392c593315Sopenharmony_ci     http2::HD_CONNECTION},
1402c593315Sopenharmony_ci    {StringRef::from_lit("delta"), StringRef::from_lit("4")},
1412c593315Sopenharmony_ci    {StringRef::from_lit("expect"), StringRef::from_lit("5")},
1422c593315Sopenharmony_ci    {StringRef::from_lit("foxtrot"), StringRef::from_lit("6")},
1432c593315Sopenharmony_ci    {StringRef::from_lit("tango"), StringRef::from_lit("7")},
1442c593315Sopenharmony_ci    {StringRef::from_lit("te"), StringRef::from_lit("8"), false, http2::HD_TE},
1452c593315Sopenharmony_ci    {StringRef::from_lit("te"), StringRef::from_lit("9"), false, http2::HD_TE},
1462c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("10"), false,
1472c593315Sopenharmony_ci     http2::HD_X_FORWARDED_FOR},
1482c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("11"), false,
1492c593315Sopenharmony_ci     http2::HD_X_FORWARDED_FOR},
1502c593315Sopenharmony_ci    {StringRef::from_lit("zulu"), StringRef::from_lit("12")}};
1512c593315Sopenharmony_ci} // namespace
1522c593315Sopenharmony_ci
1532c593315Sopenharmony_cinamespace {
1542c593315Sopenharmony_ciauto headers2 = HeaderRefs{
1552c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff1"), false,
1562c593315Sopenharmony_ci     http2::HD_X_FORWARDED_FOR},
1572c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff2"), false,
1582c593315Sopenharmony_ci     http2::HD_X_FORWARDED_FOR},
1592c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp1"),
1602c593315Sopenharmony_ci     false, http2::HD_X_FORWARDED_PROTO},
1612c593315Sopenharmony_ci    {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp2"),
1622c593315Sopenharmony_ci     false, http2::HD_X_FORWARDED_PROTO},
1632c593315Sopenharmony_ci    {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd1"), false,
1642c593315Sopenharmony_ci     http2::HD_FORWARDED},
1652c593315Sopenharmony_ci    {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd2"), false,
1662c593315Sopenharmony_ci     http2::HD_FORWARDED},
1672c593315Sopenharmony_ci    {StringRef::from_lit("via"), StringRef::from_lit("via1"), false,
1682c593315Sopenharmony_ci     http2::HD_VIA},
1692c593315Sopenharmony_ci    {StringRef::from_lit("via"), StringRef::from_lit("via2"), false,
1702c593315Sopenharmony_ci     http2::HD_VIA},
1712c593315Sopenharmony_ci};
1722c593315Sopenharmony_ci} // namespace
1732c593315Sopenharmony_ci
1742c593315Sopenharmony_civoid test_http2_copy_headers_to_nva(void) {
1752c593315Sopenharmony_ci  auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12};
1762c593315Sopenharmony_ci  std::vector<nghttp2_nv> nva;
1772c593315Sopenharmony_ci
1782c593315Sopenharmony_ci  http2::copy_headers_to_nva_nocopy(nva, headers,
1792c593315Sopenharmony_ci                                    http2::HDOP_STRIP_X_FORWARDED_FOR);
1802c593315Sopenharmony_ci  CU_ASSERT(7 == nva.size());
1812c593315Sopenharmony_ci  for (size_t i = 0; i < ans.size(); ++i) {
1822c593315Sopenharmony_ci    check_nv(headers[ans[i]], &nva[i]);
1832c593315Sopenharmony_ci
1842c593315Sopenharmony_ci    if (ans[i] == 0) {
1852c593315Sopenharmony_ci      CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE |
1862c593315Sopenharmony_ci                 NGHTTP2_NV_FLAG_NO_INDEX) == nva[i].flags);
1872c593315Sopenharmony_ci    } else {
1882c593315Sopenharmony_ci      CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME |
1892c593315Sopenharmony_ci                 NGHTTP2_NV_FLAG_NO_COPY_VALUE) == nva[i].flags);
1902c593315Sopenharmony_ci    }
1912c593315Sopenharmony_ci  }
1922c593315Sopenharmony_ci
1932c593315Sopenharmony_ci  nva.clear();
1942c593315Sopenharmony_ci  http2::copy_headers_to_nva(nva, headers, http2::HDOP_STRIP_X_FORWARDED_FOR);
1952c593315Sopenharmony_ci  CU_ASSERT(7 == nva.size());
1962c593315Sopenharmony_ci  for (size_t i = 0; i < ans.size(); ++i) {
1972c593315Sopenharmony_ci    check_nv(headers[ans[i]], &nva[i]);
1982c593315Sopenharmony_ci
1992c593315Sopenharmony_ci    if (ans[i] == 0) {
2002c593315Sopenharmony_ci      CU_ASSERT(nva[i].flags & NGHTTP2_NV_FLAG_NO_INDEX);
2012c593315Sopenharmony_ci    } else {
2022c593315Sopenharmony_ci      CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
2032c593315Sopenharmony_ci    }
2042c593315Sopenharmony_ci  }
2052c593315Sopenharmony_ci
2062c593315Sopenharmony_ci  nva.clear();
2072c593315Sopenharmony_ci
2082c593315Sopenharmony_ci  auto ans2 = std::vector<int>{0, 2, 4, 6};
2092c593315Sopenharmony_ci  http2::copy_headers_to_nva(nva, headers2, http2::HDOP_NONE);
2102c593315Sopenharmony_ci  CU_ASSERT(ans2.size() == nva.size());
2112c593315Sopenharmony_ci  for (size_t i = 0; i < ans2.size(); ++i) {
2122c593315Sopenharmony_ci    check_nv(headers2[ans2[i]], &nva[i]);
2132c593315Sopenharmony_ci  }
2142c593315Sopenharmony_ci
2152c593315Sopenharmony_ci  nva.clear();
2162c593315Sopenharmony_ci
2172c593315Sopenharmony_ci  http2::copy_headers_to_nva(nva, headers2, http2::HDOP_STRIP_ALL);
2182c593315Sopenharmony_ci  CU_ASSERT(nva.empty());
2192c593315Sopenharmony_ci}
2202c593315Sopenharmony_ci
2212c593315Sopenharmony_civoid test_http2_build_http1_headers_from_headers(void) {
2222c593315Sopenharmony_ci  MemchunkPool pool;
2232c593315Sopenharmony_ci  DefaultMemchunks buf(&pool);
2242c593315Sopenharmony_ci  http2::build_http1_headers_from_headers(&buf, headers,
2252c593315Sopenharmony_ci                                          http2::HDOP_STRIP_X_FORWARDED_FOR);
2262c593315Sopenharmony_ci  auto hdrs = std::string(buf.head->pos, buf.head->last);
2272c593315Sopenharmony_ci  CU_ASSERT("Alpha: 0\r\n"
2282c593315Sopenharmony_ci            "Bravo: 1\r\n"
2292c593315Sopenharmony_ci            "Delta: 4\r\n"
2302c593315Sopenharmony_ci            "Expect: 5\r\n"
2312c593315Sopenharmony_ci            "Foxtrot: 6\r\n"
2322c593315Sopenharmony_ci            "Tango: 7\r\n"
2332c593315Sopenharmony_ci            "Te: 8\r\n"
2342c593315Sopenharmony_ci            "Te: 9\r\n"
2352c593315Sopenharmony_ci            "Zulu: 12\r\n" == hdrs);
2362c593315Sopenharmony_ci
2372c593315Sopenharmony_ci  buf.reset();
2382c593315Sopenharmony_ci
2392c593315Sopenharmony_ci  http2::build_http1_headers_from_headers(&buf, headers2, http2::HDOP_NONE);
2402c593315Sopenharmony_ci  hdrs = std::string(buf.head->pos, buf.head->last);
2412c593315Sopenharmony_ci  CU_ASSERT("X-Forwarded-For: xff1\r\n"
2422c593315Sopenharmony_ci            "X-Forwarded-Proto: xfp1\r\n"
2432c593315Sopenharmony_ci            "Forwarded: fwd1\r\n"
2442c593315Sopenharmony_ci            "Via: via1\r\n" == hdrs);
2452c593315Sopenharmony_ci
2462c593315Sopenharmony_ci  buf.reset();
2472c593315Sopenharmony_ci
2482c593315Sopenharmony_ci  http2::build_http1_headers_from_headers(&buf, headers2,
2492c593315Sopenharmony_ci                                          http2::HDOP_STRIP_ALL);
2502c593315Sopenharmony_ci  CU_ASSERT(0 == buf.rleft());
2512c593315Sopenharmony_ci}
2522c593315Sopenharmony_ci
2532c593315Sopenharmony_civoid test_http2_lws(void) {
2542c593315Sopenharmony_ci  CU_ASSERT(!http2::lws("alpha"));
2552c593315Sopenharmony_ci  CU_ASSERT(http2::lws(" "));
2562c593315Sopenharmony_ci  CU_ASSERT(http2::lws(""));
2572c593315Sopenharmony_ci}
2582c593315Sopenharmony_ci
2592c593315Sopenharmony_cinamespace {
2602c593315Sopenharmony_civoid check_rewrite_location_uri(const std::string &want, const std::string &uri,
2612c593315Sopenharmony_ci                                const std::string &match_host,
2622c593315Sopenharmony_ci                                const std::string &req_authority,
2632c593315Sopenharmony_ci                                const std::string &upstream_scheme) {
2642c593315Sopenharmony_ci  BlockAllocator balloc(4096, 4096);
2652c593315Sopenharmony_ci  http_parser_url u{};
2662c593315Sopenharmony_ci  CU_ASSERT(0 == http_parser_parse_url(uri.c_str(), uri.size(), 0, &u));
2672c593315Sopenharmony_ci  auto got = http2::rewrite_location_uri(
2682c593315Sopenharmony_ci      balloc, StringRef{uri}, u, StringRef{match_host},
2692c593315Sopenharmony_ci      StringRef{req_authority}, StringRef{upstream_scheme});
2702c593315Sopenharmony_ci  CU_ASSERT(want == got);
2712c593315Sopenharmony_ci}
2722c593315Sopenharmony_ci} // namespace
2732c593315Sopenharmony_ci
2742c593315Sopenharmony_civoid test_http2_rewrite_location_uri(void) {
2752c593315Sopenharmony_ci  check_rewrite_location_uri("https://localhost:3000/alpha?bravo#charlie",
2762c593315Sopenharmony_ci                             "http://localhost:3001/alpha?bravo#charlie",
2772c593315Sopenharmony_ci                             "localhost:3001", "localhost:3000", "https");
2782c593315Sopenharmony_ci  check_rewrite_location_uri("https://localhost/", "http://localhost:3001/",
2792c593315Sopenharmony_ci                             "localhost", "localhost", "https");
2802c593315Sopenharmony_ci  check_rewrite_location_uri("http://localhost/", "http://localhost:3001/",
2812c593315Sopenharmony_ci                             "localhost", "localhost", "http");
2822c593315Sopenharmony_ci  check_rewrite_location_uri("http://localhost:443/", "http://localhost:3001/",
2832c593315Sopenharmony_ci                             "localhost", "localhost:443", "http");
2842c593315Sopenharmony_ci  check_rewrite_location_uri("https://localhost:80/", "http://localhost:3001/",
2852c593315Sopenharmony_ci                             "localhost", "localhost:80", "https");
2862c593315Sopenharmony_ci  check_rewrite_location_uri("", "http://localhost:3001/", "127.0.0.1",
2872c593315Sopenharmony_ci                             "127.0.0.1", "https");
2882c593315Sopenharmony_ci  check_rewrite_location_uri("https://localhost:3000/",
2892c593315Sopenharmony_ci                             "http://localhost:3001/", "localhost",
2902c593315Sopenharmony_ci                             "localhost:3000", "https");
2912c593315Sopenharmony_ci  check_rewrite_location_uri("https://localhost:3000/", "http://localhost/",
2922c593315Sopenharmony_ci                             "localhost", "localhost:3000", "https");
2932c593315Sopenharmony_ci
2942c593315Sopenharmony_ci  // match_host != req_authority
2952c593315Sopenharmony_ci  check_rewrite_location_uri("https://example.org", "http://127.0.0.1:8080",
2962c593315Sopenharmony_ci                             "127.0.0.1", "example.org", "https");
2972c593315Sopenharmony_ci  check_rewrite_location_uri("", "http://example.org", "127.0.0.1",
2982c593315Sopenharmony_ci                             "example.org", "https");
2992c593315Sopenharmony_ci}
3002c593315Sopenharmony_ci
3012c593315Sopenharmony_civoid test_http2_parse_http_status_code(void) {
3022c593315Sopenharmony_ci  CU_ASSERT(200 == http2::parse_http_status_code(StringRef::from_lit("200")));
3032c593315Sopenharmony_ci  CU_ASSERT(102 == http2::parse_http_status_code(StringRef::from_lit("102")));
3042c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("099")));
3052c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("99")));
3062c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("-1")));
3072c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("20a")));
3082c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::parse_http_status_code(StringRef{}));
3092c593315Sopenharmony_ci}
3102c593315Sopenharmony_ci
3112c593315Sopenharmony_civoid test_http2_index_header(void) {
3122c593315Sopenharmony_ci  http2::HeaderIndex hdidx;
3132c593315Sopenharmony_ci  http2::init_hdidx(hdidx);
3142c593315Sopenharmony_ci
3152c593315Sopenharmony_ci  http2::index_header(hdidx, http2::HD__AUTHORITY, 0);
3162c593315Sopenharmony_ci  http2::index_header(hdidx, -1, 1);
3172c593315Sopenharmony_ci
3182c593315Sopenharmony_ci  CU_ASSERT(0 == hdidx[http2::HD__AUTHORITY]);
3192c593315Sopenharmony_ci}
3202c593315Sopenharmony_ci
3212c593315Sopenharmony_civoid test_http2_lookup_token(void) {
3222c593315Sopenharmony_ci  CU_ASSERT(http2::HD__AUTHORITY ==
3232c593315Sopenharmony_ci            http2::lookup_token(StringRef::from_lit(":authority")));
3242c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":authorit")));
3252c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":Authority")));
3262c593315Sopenharmony_ci  CU_ASSERT(http2::HD_EXPECT ==
3272c593315Sopenharmony_ci            http2::lookup_token(StringRef::from_lit("expect")));
3282c593315Sopenharmony_ci}
3292c593315Sopenharmony_ci
3302c593315Sopenharmony_civoid test_http2_parse_link_header(void) {
3312c593315Sopenharmony_ci  {
3322c593315Sopenharmony_ci    // only URI appears; we don't extract URI unless it bears rel=preload
3332c593315Sopenharmony_ci    auto res = http2::parse_link_header(StringRef::from_lit("<url>"));
3342c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
3352c593315Sopenharmony_ci  }
3362c593315Sopenharmony_ci  {
3372c593315Sopenharmony_ci    // URI url should be extracted
3382c593315Sopenharmony_ci    auto res =
3392c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>; rel=preload"));
3402c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3412c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3422c593315Sopenharmony_ci  }
3432c593315Sopenharmony_ci  {
3442c593315Sopenharmony_ci    // With extra link-param.  URI url should be extracted
3452c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3462c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload; as=file"));
3472c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3482c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3492c593315Sopenharmony_ci  }
3502c593315Sopenharmony_ci  {
3512c593315Sopenharmony_ci    // With extra link-param.  URI url should be extracted
3522c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3532c593315Sopenharmony_ci        StringRef::from_lit("<url>; as=file; rel=preload"));
3542c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3552c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3562c593315Sopenharmony_ci  }
3572c593315Sopenharmony_ci  {
3582c593315Sopenharmony_ci    // With extra link-param and quote-string.  URI url should be
3592c593315Sopenharmony_ci    // extracted
3602c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3612c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; title="foo,bar")"));
3622c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3632c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3642c593315Sopenharmony_ci  }
3652c593315Sopenharmony_ci  {
3662c593315Sopenharmony_ci    // With extra link-param and quote-string.  URI url should be
3672c593315Sopenharmony_ci    // extracted
3682c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3692c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; title="foo,bar"; rel=preload)"));
3702c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3712c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3722c593315Sopenharmony_ci  }
3732c593315Sopenharmony_ci  {
3742c593315Sopenharmony_ci    // ',' after quote-string
3752c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3762c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; title="foo,bar", <url2>; rel=preload)"));
3772c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3782c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
3792c593315Sopenharmony_ci  }
3802c593315Sopenharmony_ci  {
3812c593315Sopenharmony_ci    // Only first URI should be extracted.
3822c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3832c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload, <url2>"));
3842c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
3852c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3862c593315Sopenharmony_ci  }
3872c593315Sopenharmony_ci  {
3882c593315Sopenharmony_ci    // Both have rel=preload, so both urls should be extracted
3892c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3902c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload, <url2>; rel=preload"));
3912c593315Sopenharmony_ci    CU_ASSERT(2 == res.size());
3922c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
3932c593315Sopenharmony_ci    CU_ASSERT("url2" == res[1].uri);
3942c593315Sopenharmony_ci  }
3952c593315Sopenharmony_ci  {
3962c593315Sopenharmony_ci    // Second URI uri should be extracted.
3972c593315Sopenharmony_ci    auto res = http2::parse_link_header(
3982c593315Sopenharmony_ci        StringRef::from_lit("<url>, <url2>;rel=preload"));
3992c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
4002c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
4012c593315Sopenharmony_ci  }
4022c593315Sopenharmony_ci  {
4032c593315Sopenharmony_ci    // Error if input ends with ';'
4042c593315Sopenharmony_ci    auto res =
4052c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>;rel=preload;"));
4062c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4072c593315Sopenharmony_ci  }
4082c593315Sopenharmony_ci  {
4092c593315Sopenharmony_ci    // Error if link header ends with ';'
4102c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4112c593315Sopenharmony_ci        StringRef::from_lit("<url>;rel=preload;, <url>"));
4122c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4132c593315Sopenharmony_ci  }
4142c593315Sopenharmony_ci  {
4152c593315Sopenharmony_ci    // OK if input ends with ','
4162c593315Sopenharmony_ci    auto res =
4172c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>;rel=preload,"));
4182c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
4192c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
4202c593315Sopenharmony_ci  }
4212c593315Sopenharmony_ci  {
4222c593315Sopenharmony_ci    // Multiple repeated ','s between fields is OK
4232c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4242c593315Sopenharmony_ci        StringRef::from_lit("<url>,,,<url2>;rel=preload"));
4252c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
4262c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
4272c593315Sopenharmony_ci  }
4282c593315Sopenharmony_ci  {
4292c593315Sopenharmony_ci    // Error if url is not enclosed by <>
4302c593315Sopenharmony_ci    auto res =
4312c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("url>;rel=preload"));
4322c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4332c593315Sopenharmony_ci  }
4342c593315Sopenharmony_ci  {
4352c593315Sopenharmony_ci    // Error if url is not enclosed by <>
4362c593315Sopenharmony_ci    auto res =
4372c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url;rel=preload"));
4382c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4392c593315Sopenharmony_ci  }
4402c593315Sopenharmony_ci  {
4412c593315Sopenharmony_ci    // Empty parameter value is not allowed
4422c593315Sopenharmony_ci    auto res =
4432c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>;rel=preload; as="));
4442c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4452c593315Sopenharmony_ci  }
4462c593315Sopenharmony_ci  {
4472c593315Sopenharmony_ci    // Empty parameter value is not allowed
4482c593315Sopenharmony_ci    auto res =
4492c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>;as=;rel=preload"));
4502c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4512c593315Sopenharmony_ci  }
4522c593315Sopenharmony_ci  {
4532c593315Sopenharmony_ci    // Empty parameter value is not allowed
4542c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4552c593315Sopenharmony_ci        StringRef::from_lit("<url>;as=, <url>;rel=preload"));
4562c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4572c593315Sopenharmony_ci  }
4582c593315Sopenharmony_ci  {
4592c593315Sopenharmony_ci    // Empty parameter name is not allowed
4602c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4612c593315Sopenharmony_ci        StringRef::from_lit("<url>; =file; rel=preload"));
4622c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4632c593315Sopenharmony_ci  }
4642c593315Sopenharmony_ci  {
4652c593315Sopenharmony_ci    // Without whitespaces
4662c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4672c593315Sopenharmony_ci        StringRef::from_lit("<url>;as=file;rel=preload,<url2>;rel=preload"));
4682c593315Sopenharmony_ci    CU_ASSERT(2 == res.size());
4692c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
4702c593315Sopenharmony_ci    CU_ASSERT("url2" == res[1].uri);
4712c593315Sopenharmony_ci  }
4722c593315Sopenharmony_ci  {
4732c593315Sopenharmony_ci    // link-extension may have no value
4742c593315Sopenharmony_ci    auto res =
4752c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>; as; rel=preload"));
4762c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
4772c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
4782c593315Sopenharmony_ci  }
4792c593315Sopenharmony_ci  {
4802c593315Sopenharmony_ci    // ext-name-star
4812c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4822c593315Sopenharmony_ci        StringRef::from_lit("<url>; foo*=bar; rel=preload"));
4832c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
4842c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
4852c593315Sopenharmony_ci  }
4862c593315Sopenharmony_ci  {
4872c593315Sopenharmony_ci    // '*' is not allowed expect for trailing one
4882c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4892c593315Sopenharmony_ci        StringRef::from_lit("<url>; *=bar; rel=preload"));
4902c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4912c593315Sopenharmony_ci  }
4922c593315Sopenharmony_ci  {
4932c593315Sopenharmony_ci    // '*' is not allowed expect for trailing one
4942c593315Sopenharmony_ci    auto res = http2::parse_link_header(
4952c593315Sopenharmony_ci        StringRef::from_lit("<url>; foo*bar=buzz; rel=preload"));
4962c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
4972c593315Sopenharmony_ci  }
4982c593315Sopenharmony_ci  {
4992c593315Sopenharmony_ci    // ext-name-star must be followed by '='
5002c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5012c593315Sopenharmony_ci        StringRef::from_lit("<url>; foo*; rel=preload"));
5022c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5032c593315Sopenharmony_ci  }
5042c593315Sopenharmony_ci  {
5052c593315Sopenharmony_ci    // '>' is not followed by ';'
5062c593315Sopenharmony_ci    auto res =
5072c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url> rel=preload"));
5082c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5092c593315Sopenharmony_ci  }
5102c593315Sopenharmony_ci  {
5112c593315Sopenharmony_ci    // Starting with whitespace is no problem.
5122c593315Sopenharmony_ci    auto res =
5132c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("  <url>; rel=preload"));
5142c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5152c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5162c593315Sopenharmony_ci  }
5172c593315Sopenharmony_ci  {
5182c593315Sopenharmony_ci    // preload is a prefix of bogus rel parameter value
5192c593315Sopenharmony_ci    auto res =
5202c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit("<url>; rel=preloadx"));
5212c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5222c593315Sopenharmony_ci  }
5232c593315Sopenharmony_ci  {
5242c593315Sopenharmony_ci    // preload in relation-types list
5252c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5262c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload")"));
5272c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5282c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5292c593315Sopenharmony_ci  }
5302c593315Sopenharmony_ci  {
5312c593315Sopenharmony_ci    // preload in relation-types list followed by another parameter
5322c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5332c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload foo")"));
5342c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5352c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5362c593315Sopenharmony_ci  }
5372c593315Sopenharmony_ci  {
5382c593315Sopenharmony_ci    // preload in relation-types list following another parameter
5392c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5402c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="foo preload")"));
5412c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5422c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5432c593315Sopenharmony_ci  }
5442c593315Sopenharmony_ci  {
5452c593315Sopenharmony_ci    // preload in relation-types list between other parameters
5462c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5472c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="foo preload bar")"));
5482c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5492c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5502c593315Sopenharmony_ci  }
5512c593315Sopenharmony_ci  {
5522c593315Sopenharmony_ci    // preload in relation-types list between other parameters
5532c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5542c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="foo   preload   bar")"));
5552c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5562c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5572c593315Sopenharmony_ci  }
5582c593315Sopenharmony_ci  {
5592c593315Sopenharmony_ci    // no preload in relation-types list
5602c593315Sopenharmony_ci    auto res =
5612c593315Sopenharmony_ci        http2::parse_link_header(StringRef::from_lit(R"(<url>; rel="foo")"));
5622c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5632c593315Sopenharmony_ci  }
5642c593315Sopenharmony_ci  {
5652c593315Sopenharmony_ci    // no preload in relation-types list, multiple unrelated elements.
5662c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5672c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="foo bar")"));
5682c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5692c593315Sopenharmony_ci  }
5702c593315Sopenharmony_ci  {
5712c593315Sopenharmony_ci    // preload in relation-types list, followed by another link-value.
5722c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5732c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload", <url2>)"));
5742c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5752c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5762c593315Sopenharmony_ci  }
5772c593315Sopenharmony_ci  {
5782c593315Sopenharmony_ci    // preload in relation-types list, following another link-value.
5792c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5802c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>, <url2>; rel="preload")"));
5812c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5822c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
5832c593315Sopenharmony_ci  }
5842c593315Sopenharmony_ci  {
5852c593315Sopenharmony_ci    // preload in relation-types list, followed by another link-param.
5862c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5872c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload"; as="font")"));
5882c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
5892c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
5902c593315Sopenharmony_ci  }
5912c593315Sopenharmony_ci  {
5922c593315Sopenharmony_ci    // preload in relation-types list, followed by character other
5932c593315Sopenharmony_ci    // than ';' or ','
5942c593315Sopenharmony_ci    auto res = http2::parse_link_header(
5952c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload".)"));
5962c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
5972c593315Sopenharmony_ci  }
5982c593315Sopenharmony_ci  {
5992c593315Sopenharmony_ci    // preload in relation-types list, followed by ';' but it
6002c593315Sopenharmony_ci    // terminates input
6012c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6022c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload";)"));
6032c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6042c593315Sopenharmony_ci  }
6052c593315Sopenharmony_ci  {
6062c593315Sopenharmony_ci    // preload in relation-types list, followed by ',' but it
6072c593315Sopenharmony_ci    // terminates input
6082c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6092c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload",)"));
6102c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
6112c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
6122c593315Sopenharmony_ci  }
6132c593315Sopenharmony_ci  {
6142c593315Sopenharmony_ci    // preload in relation-types list but there is preceding white
6152c593315Sopenharmony_ci    // space.
6162c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6172c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=" preload")"));
6182c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6192c593315Sopenharmony_ci  }
6202c593315Sopenharmony_ci  {
6212c593315Sopenharmony_ci    // preload in relation-types list but there is trailing white
6222c593315Sopenharmony_ci    // space.
6232c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6242c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel="preload ")"));
6252c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6262c593315Sopenharmony_ci  }
6272c593315Sopenharmony_ci  {
6282c593315Sopenharmony_ci    // backslash escaped characters in quoted-string
6292c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6302c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; title="foo\"baz\"bar")"));
6312c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
6322c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
6332c593315Sopenharmony_ci  }
6342c593315Sopenharmony_ci  {
6352c593315Sopenharmony_ci    // anchor="" is acceptable
6362c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6372c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; anchor="")"));
6382c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
6392c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
6402c593315Sopenharmony_ci  }
6412c593315Sopenharmony_ci  {
6422c593315Sopenharmony_ci    // With anchor="#foo", url should be ignored
6432c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6442c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; anchor="#foo")"));
6452c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6462c593315Sopenharmony_ci  }
6472c593315Sopenharmony_ci  {
6482c593315Sopenharmony_ci    // With anchor=f, url should be ignored
6492c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6502c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload; anchor=f"));
6512c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6522c593315Sopenharmony_ci  }
6532c593315Sopenharmony_ci  {
6542c593315Sopenharmony_ci    // First url is ignored With anchor="#foo", but url should be
6552c593315Sopenharmony_ci    // accepted.
6562c593315Sopenharmony_ci    auto res = http2::parse_link_header(StringRef::from_lit(
6572c593315Sopenharmony_ci        R"(<url>; rel=preload; anchor="#foo", <url2>; rel=preload)"));
6582c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
6592c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
6602c593315Sopenharmony_ci  }
6612c593315Sopenharmony_ci  {
6622c593315Sopenharmony_ci    // With loadpolicy="next", url should be ignored
6632c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6642c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="next")"));
6652c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6662c593315Sopenharmony_ci  }
6672c593315Sopenharmony_ci  {
6682c593315Sopenharmony_ci    // url should be picked up if empty loadpolicy is specified
6692c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6702c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="")"));
6712c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
6722c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
6732c593315Sopenharmony_ci  }
6742c593315Sopenharmony_ci  {
6752c593315Sopenharmony_ci    // case-insensitive match
6762c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6772c593315Sopenharmony_ci        StringRef::from_lit(R"(<url>; rel=preload; ANCHOR="#foo", <url2>; )"
6782c593315Sopenharmony_ci                            R"(REL=PRELOAD, <url3>; REL="foo PRELOAD bar")"));
6792c593315Sopenharmony_ci    CU_ASSERT(2 == res.size());
6802c593315Sopenharmony_ci    CU_ASSERT("url2" == res[0].uri);
6812c593315Sopenharmony_ci    CU_ASSERT("url3" == res[1].uri);
6822c593315Sopenharmony_ci  }
6832c593315Sopenharmony_ci  {
6842c593315Sopenharmony_ci    // nopush at the end of input
6852c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6862c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload; nopush"));
6872c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6882c593315Sopenharmony_ci  }
6892c593315Sopenharmony_ci  {
6902c593315Sopenharmony_ci    // nopush followed by ';'
6912c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6922c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload; nopush; foo"));
6932c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
6942c593315Sopenharmony_ci  }
6952c593315Sopenharmony_ci  {
6962c593315Sopenharmony_ci    // nopush followed by ','
6972c593315Sopenharmony_ci    auto res = http2::parse_link_header(
6982c593315Sopenharmony_ci        StringRef::from_lit("<url>; nopush; rel=preload"));
6992c593315Sopenharmony_ci    CU_ASSERT(0 == res.size());
7002c593315Sopenharmony_ci  }
7012c593315Sopenharmony_ci  {
7022c593315Sopenharmony_ci    // string whose prefix is nopush
7032c593315Sopenharmony_ci    auto res = http2::parse_link_header(
7042c593315Sopenharmony_ci        StringRef::from_lit("<url>; nopushyes; rel=preload"));
7052c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
7062c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
7072c593315Sopenharmony_ci  }
7082c593315Sopenharmony_ci  {
7092c593315Sopenharmony_ci    // rel=preload twice
7102c593315Sopenharmony_ci    auto res = http2::parse_link_header(
7112c593315Sopenharmony_ci        StringRef::from_lit("<url>; rel=preload; rel=preload"));
7122c593315Sopenharmony_ci    CU_ASSERT(1 == res.size());
7132c593315Sopenharmony_ci    CU_ASSERT("url" == res[0].uri);
7142c593315Sopenharmony_ci  }
7152c593315Sopenharmony_ci}
7162c593315Sopenharmony_ci
7172c593315Sopenharmony_civoid test_http2_path_join(void) {
7182c593315Sopenharmony_ci  {
7192c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7202c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/");
7212c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{}));
7222c593315Sopenharmony_ci  }
7232c593315Sopenharmony_ci  {
7242c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7252c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/alpha");
7262c593315Sopenharmony_ci    CU_ASSERT("/alpha" ==
7272c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7282c593315Sopenharmony_ci  }
7292c593315Sopenharmony_ci  {
7302c593315Sopenharmony_ci    // rel ends with trailing '/'
7312c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7322c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/alpha/");
7332c593315Sopenharmony_ci    CU_ASSERT("/alpha/" ==
7342c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7352c593315Sopenharmony_ci  }
7362c593315Sopenharmony_ci  {
7372c593315Sopenharmony_ci    // rel contains multiple components
7382c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7392c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/alpha/bravo");
7402c593315Sopenharmony_ci    CU_ASSERT("/alpha/bravo" ==
7412c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7422c593315Sopenharmony_ci  }
7432c593315Sopenharmony_ci  {
7442c593315Sopenharmony_ci    // rel is relative
7452c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7462c593315Sopenharmony_ci    auto rel = StringRef::from_lit("alpha/bravo");
7472c593315Sopenharmony_ci    CU_ASSERT("/alpha/bravo" ==
7482c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7492c593315Sopenharmony_ci  }
7502c593315Sopenharmony_ci  {
7512c593315Sopenharmony_ci    // rel is relative and base ends without /, which means it refers
7522c593315Sopenharmony_ci    // to file.
7532c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha");
7542c593315Sopenharmony_ci    auto rel = StringRef::from_lit("bravo/charlie");
7552c593315Sopenharmony_ci    CU_ASSERT("/bravo/charlie" ==
7562c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7572c593315Sopenharmony_ci  }
7582c593315Sopenharmony_ci  {
7592c593315Sopenharmony_ci    // rel contains repeated '/'s
7602c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
7612c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/alpha/////bravo/////");
7622c593315Sopenharmony_ci    CU_ASSERT("/alpha/bravo/" ==
7632c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7642c593315Sopenharmony_ci  }
7652c593315Sopenharmony_ci  {
7662c593315Sopenharmony_ci    // base ends with '/', so '..' eats 'bravo'
7672c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo/");
7682c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../charlie/delta");
7692c593315Sopenharmony_ci    CU_ASSERT("/alpha/charlie/delta" ==
7702c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7712c593315Sopenharmony_ci  }
7722c593315Sopenharmony_ci  {
7732c593315Sopenharmony_ci    // base does not end with '/', so '..' eats 'alpha/bravo'
7742c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo");
7752c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../charlie");
7762c593315Sopenharmony_ci    CU_ASSERT("/charlie" ==
7772c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7782c593315Sopenharmony_ci  }
7792c593315Sopenharmony_ci  {
7802c593315Sopenharmony_ci    // 'charlie' is eaten by following '..'
7812c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo/");
7822c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../charlie/../delta");
7832c593315Sopenharmony_ci    CU_ASSERT("/alpha/delta" ==
7842c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7852c593315Sopenharmony_ci  }
7862c593315Sopenharmony_ci  {
7872c593315Sopenharmony_ci    // excessive '..' results in '/'
7882c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo/");
7892c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../../");
7902c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{}));
7912c593315Sopenharmony_ci  }
7922c593315Sopenharmony_ci  {
7932c593315Sopenharmony_ci    // excessive '..'  and  path component
7942c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo/");
7952c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../../charlie");
7962c593315Sopenharmony_ci    CU_ASSERT("/charlie" ==
7972c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
7982c593315Sopenharmony_ci  }
7992c593315Sopenharmony_ci  {
8002c593315Sopenharmony_ci    // rel ends with '..'
8012c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha/bravo/");
8022c593315Sopenharmony_ci    auto rel = StringRef::from_lit("charlie/..");
8032c593315Sopenharmony_ci    CU_ASSERT("/alpha/bravo/" ==
8042c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
8052c593315Sopenharmony_ci  }
8062c593315Sopenharmony_ci  {
8072c593315Sopenharmony_ci    // base empty and rel contains '..'
8082c593315Sopenharmony_ci    auto base = StringRef{};
8092c593315Sopenharmony_ci    auto rel = StringRef::from_lit("charlie/..");
8102c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{}));
8112c593315Sopenharmony_ci  }
8122c593315Sopenharmony_ci  {
8132c593315Sopenharmony_ci    // '.' is ignored
8142c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
8152c593315Sopenharmony_ci    auto rel = StringRef::from_lit("charlie/././././delta");
8162c593315Sopenharmony_ci    CU_ASSERT("/charlie/delta" ==
8172c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
8182c593315Sopenharmony_ci  }
8192c593315Sopenharmony_ci  {
8202c593315Sopenharmony_ci    // trailing '.' is ignored
8212c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
8222c593315Sopenharmony_ci    auto rel = StringRef::from_lit("charlie/.");
8232c593315Sopenharmony_ci    CU_ASSERT("/charlie/" ==
8242c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
8252c593315Sopenharmony_ci  }
8262c593315Sopenharmony_ci  {
8272c593315Sopenharmony_ci    // query
8282c593315Sopenharmony_ci    auto base = StringRef::from_lit("/");
8292c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/");
8302c593315Sopenharmony_ci    auto relq = StringRef::from_lit("q");
8312c593315Sopenharmony_ci    CU_ASSERT("/?q" == http2::path_join(base, StringRef{}, rel, relq));
8322c593315Sopenharmony_ci  }
8332c593315Sopenharmony_ci  {
8342c593315Sopenharmony_ci    // empty rel and query
8352c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha");
8362c593315Sopenharmony_ci    auto rel = StringRef{};
8372c593315Sopenharmony_ci    auto relq = StringRef::from_lit("q");
8382c593315Sopenharmony_ci    CU_ASSERT("/alpha?q" == http2::path_join(base, StringRef{}, rel, relq));
8392c593315Sopenharmony_ci  }
8402c593315Sopenharmony_ci  {
8412c593315Sopenharmony_ci    // both rel and query are empty
8422c593315Sopenharmony_ci    auto base = StringRef::from_lit("/alpha");
8432c593315Sopenharmony_ci    auto baseq = StringRef::from_lit("r");
8442c593315Sopenharmony_ci    auto rel = StringRef{};
8452c593315Sopenharmony_ci    auto relq = StringRef{};
8462c593315Sopenharmony_ci    CU_ASSERT("/alpha?r" == http2::path_join(base, baseq, rel, relq));
8472c593315Sopenharmony_ci  }
8482c593315Sopenharmony_ci  {
8492c593315Sopenharmony_ci    // empty base
8502c593315Sopenharmony_ci    auto base = StringRef{};
8512c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/alpha");
8522c593315Sopenharmony_ci    CU_ASSERT("/alpha" ==
8532c593315Sopenharmony_ci              http2::path_join(base, StringRef{}, rel, StringRef{}));
8542c593315Sopenharmony_ci  }
8552c593315Sopenharmony_ci  {
8562c593315Sopenharmony_ci    // everything is empty
8572c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(StringRef{}, StringRef{}, StringRef{},
8582c593315Sopenharmony_ci                                      StringRef{}));
8592c593315Sopenharmony_ci  }
8602c593315Sopenharmony_ci  {
8612c593315Sopenharmony_ci    // only baseq is not empty
8622c593315Sopenharmony_ci    auto base = StringRef{};
8632c593315Sopenharmony_ci    auto baseq = StringRef::from_lit("r");
8642c593315Sopenharmony_ci    auto rel = StringRef{};
8652c593315Sopenharmony_ci    CU_ASSERT("/?r" == http2::path_join(base, baseq, rel, StringRef{}));
8662c593315Sopenharmony_ci  }
8672c593315Sopenharmony_ci  {
8682c593315Sopenharmony_ci    // path starts with multiple '/'s.
8692c593315Sopenharmony_ci    auto base = StringRef{};
8702c593315Sopenharmony_ci    auto baseq = StringRef{};
8712c593315Sopenharmony_ci    auto rel = StringRef::from_lit("//alpha//bravo");
8722c593315Sopenharmony_ci    auto relq = StringRef::from_lit("charlie");
8732c593315Sopenharmony_ci    CU_ASSERT("/alpha/bravo?charlie" ==
8742c593315Sopenharmony_ci              http2::path_join(base, baseq, rel, relq));
8752c593315Sopenharmony_ci  }
8762c593315Sopenharmony_ci  // Test cases from RFC 3986, section 5.4.
8772c593315Sopenharmony_ci  constexpr auto base = StringRef::from_lit("/b/c/d;p");
8782c593315Sopenharmony_ci  constexpr auto baseq = StringRef::from_lit("q");
8792c593315Sopenharmony_ci  {
8802c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g");
8812c593315Sopenharmony_ci    auto relq = StringRef{};
8822c593315Sopenharmony_ci    CU_ASSERT("/b/c/g" == http2::path_join(base, baseq, rel, relq));
8832c593315Sopenharmony_ci  }
8842c593315Sopenharmony_ci  {
8852c593315Sopenharmony_ci    auto rel = StringRef::from_lit("./g");
8862c593315Sopenharmony_ci    auto relq = StringRef{};
8872c593315Sopenharmony_ci    CU_ASSERT("/b/c/g" == http2::path_join(base, baseq, rel, relq));
8882c593315Sopenharmony_ci  }
8892c593315Sopenharmony_ci  {
8902c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g/");
8912c593315Sopenharmony_ci    auto relq = StringRef{};
8922c593315Sopenharmony_ci    CU_ASSERT("/b/c/g/" == http2::path_join(base, baseq, rel, relq));
8932c593315Sopenharmony_ci  }
8942c593315Sopenharmony_ci  {
8952c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/g");
8962c593315Sopenharmony_ci    auto relq = StringRef{};
8972c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
8982c593315Sopenharmony_ci  }
8992c593315Sopenharmony_ci  {
9002c593315Sopenharmony_ci    auto rel = StringRef{};
9012c593315Sopenharmony_ci    auto relq = StringRef::from_lit("y");
9022c593315Sopenharmony_ci    CU_ASSERT("/b/c/d;p?y" == http2::path_join(base, baseq, rel, relq));
9032c593315Sopenharmony_ci  }
9042c593315Sopenharmony_ci  {
9052c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g");
9062c593315Sopenharmony_ci    auto relq = StringRef::from_lit("y");
9072c593315Sopenharmony_ci    CU_ASSERT("/b/c/g?y" == http2::path_join(base, baseq, rel, relq));
9082c593315Sopenharmony_ci  }
9092c593315Sopenharmony_ci  {
9102c593315Sopenharmony_ci    auto rel = StringRef::from_lit(";x");
9112c593315Sopenharmony_ci    auto relq = StringRef{};
9122c593315Sopenharmony_ci    CU_ASSERT("/b/c/;x" == http2::path_join(base, baseq, rel, relq));
9132c593315Sopenharmony_ci  }
9142c593315Sopenharmony_ci  {
9152c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g;x");
9162c593315Sopenharmony_ci    auto relq = StringRef{};
9172c593315Sopenharmony_ci    CU_ASSERT("/b/c/g;x" == http2::path_join(base, baseq, rel, relq));
9182c593315Sopenharmony_ci  }
9192c593315Sopenharmony_ci  {
9202c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g;x");
9212c593315Sopenharmony_ci    auto relq = StringRef::from_lit("y");
9222c593315Sopenharmony_ci    CU_ASSERT("/b/c/g;x?y" == http2::path_join(base, baseq, rel, relq));
9232c593315Sopenharmony_ci  }
9242c593315Sopenharmony_ci  {
9252c593315Sopenharmony_ci    auto rel = StringRef{};
9262c593315Sopenharmony_ci    auto relq = StringRef{};
9272c593315Sopenharmony_ci    CU_ASSERT("/b/c/d;p?q" == http2::path_join(base, baseq, rel, relq));
9282c593315Sopenharmony_ci  }
9292c593315Sopenharmony_ci  {
9302c593315Sopenharmony_ci    auto rel = StringRef::from_lit(".");
9312c593315Sopenharmony_ci    auto relq = StringRef{};
9322c593315Sopenharmony_ci    CU_ASSERT("/b/c/" == http2::path_join(base, baseq, rel, relq));
9332c593315Sopenharmony_ci  }
9342c593315Sopenharmony_ci  {
9352c593315Sopenharmony_ci    auto rel = StringRef::from_lit("./");
9362c593315Sopenharmony_ci    auto relq = StringRef{};
9372c593315Sopenharmony_ci    CU_ASSERT("/b/c/" == http2::path_join(base, baseq, rel, relq));
9382c593315Sopenharmony_ci  }
9392c593315Sopenharmony_ci  {
9402c593315Sopenharmony_ci    auto rel = StringRef::from_lit("..");
9412c593315Sopenharmony_ci    auto relq = StringRef{};
9422c593315Sopenharmony_ci    CU_ASSERT("/b/" == http2::path_join(base, baseq, rel, relq));
9432c593315Sopenharmony_ci  }
9442c593315Sopenharmony_ci  {
9452c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../");
9462c593315Sopenharmony_ci    auto relq = StringRef{};
9472c593315Sopenharmony_ci    CU_ASSERT("/b/" == http2::path_join(base, baseq, rel, relq));
9482c593315Sopenharmony_ci  }
9492c593315Sopenharmony_ci  {
9502c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../g");
9512c593315Sopenharmony_ci    auto relq = StringRef{};
9522c593315Sopenharmony_ci    CU_ASSERT("/b/g" == http2::path_join(base, baseq, rel, relq));
9532c593315Sopenharmony_ci  }
9542c593315Sopenharmony_ci  {
9552c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../..");
9562c593315Sopenharmony_ci    auto relq = StringRef{};
9572c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(base, baseq, rel, relq));
9582c593315Sopenharmony_ci  }
9592c593315Sopenharmony_ci  {
9602c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../");
9612c593315Sopenharmony_ci    auto relq = StringRef{};
9622c593315Sopenharmony_ci    CU_ASSERT("/" == http2::path_join(base, baseq, rel, relq));
9632c593315Sopenharmony_ci  }
9642c593315Sopenharmony_ci  {
9652c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../g");
9662c593315Sopenharmony_ci    auto relq = StringRef{};
9672c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
9682c593315Sopenharmony_ci  }
9692c593315Sopenharmony_ci  {
9702c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../../g");
9712c593315Sopenharmony_ci    auto relq = StringRef{};
9722c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
9732c593315Sopenharmony_ci  }
9742c593315Sopenharmony_ci  {
9752c593315Sopenharmony_ci    auto rel = StringRef::from_lit("../../../../g");
9762c593315Sopenharmony_ci    auto relq = StringRef{};
9772c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
9782c593315Sopenharmony_ci  }
9792c593315Sopenharmony_ci  {
9802c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/./g");
9812c593315Sopenharmony_ci    auto relq = StringRef{};
9822c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
9832c593315Sopenharmony_ci  }
9842c593315Sopenharmony_ci  {
9852c593315Sopenharmony_ci    auto rel = StringRef::from_lit("/../g");
9862c593315Sopenharmony_ci    auto relq = StringRef{};
9872c593315Sopenharmony_ci    CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq));
9882c593315Sopenharmony_ci  }
9892c593315Sopenharmony_ci  {
9902c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g.");
9912c593315Sopenharmony_ci    auto relq = StringRef{};
9922c593315Sopenharmony_ci    CU_ASSERT("/b/c/g." == http2::path_join(base, baseq, rel, relq));
9932c593315Sopenharmony_ci  }
9942c593315Sopenharmony_ci  {
9952c593315Sopenharmony_ci    auto rel = StringRef::from_lit(".g");
9962c593315Sopenharmony_ci    auto relq = StringRef{};
9972c593315Sopenharmony_ci    CU_ASSERT("/b/c/.g" == http2::path_join(base, baseq, rel, relq));
9982c593315Sopenharmony_ci  }
9992c593315Sopenharmony_ci  {
10002c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g..");
10012c593315Sopenharmony_ci    auto relq = StringRef{};
10022c593315Sopenharmony_ci    CU_ASSERT("/b/c/g.." == http2::path_join(base, baseq, rel, relq));
10032c593315Sopenharmony_ci  }
10042c593315Sopenharmony_ci  {
10052c593315Sopenharmony_ci    auto rel = StringRef::from_lit("..g");
10062c593315Sopenharmony_ci    auto relq = StringRef{};
10072c593315Sopenharmony_ci    CU_ASSERT("/b/c/..g" == http2::path_join(base, baseq, rel, relq));
10082c593315Sopenharmony_ci  }
10092c593315Sopenharmony_ci  {
10102c593315Sopenharmony_ci    auto rel = StringRef::from_lit("./../g");
10112c593315Sopenharmony_ci    auto relq = StringRef{};
10122c593315Sopenharmony_ci    CU_ASSERT("/b/g" == http2::path_join(base, baseq, rel, relq));
10132c593315Sopenharmony_ci  }
10142c593315Sopenharmony_ci  {
10152c593315Sopenharmony_ci    auto rel = StringRef::from_lit("./g/.");
10162c593315Sopenharmony_ci    auto relq = StringRef{};
10172c593315Sopenharmony_ci    CU_ASSERT("/b/c/g/" == http2::path_join(base, baseq, rel, relq));
10182c593315Sopenharmony_ci  }
10192c593315Sopenharmony_ci  {
10202c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g/./h");
10212c593315Sopenharmony_ci    auto relq = StringRef{};
10222c593315Sopenharmony_ci    CU_ASSERT("/b/c/g/h" == http2::path_join(base, baseq, rel, relq));
10232c593315Sopenharmony_ci  }
10242c593315Sopenharmony_ci  {
10252c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g/../h");
10262c593315Sopenharmony_ci    auto relq = StringRef{};
10272c593315Sopenharmony_ci    CU_ASSERT("/b/c/h" == http2::path_join(base, baseq, rel, relq));
10282c593315Sopenharmony_ci  }
10292c593315Sopenharmony_ci  {
10302c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g;x=1/./y");
10312c593315Sopenharmony_ci    auto relq = StringRef{};
10322c593315Sopenharmony_ci    CU_ASSERT("/b/c/g;x=1/y" == http2::path_join(base, baseq, rel, relq));
10332c593315Sopenharmony_ci  }
10342c593315Sopenharmony_ci  {
10352c593315Sopenharmony_ci    auto rel = StringRef::from_lit("g;x=1/../y");
10362c593315Sopenharmony_ci    auto relq = StringRef{};
10372c593315Sopenharmony_ci    CU_ASSERT("/b/c/y" == http2::path_join(base, baseq, rel, relq));
10382c593315Sopenharmony_ci  }
10392c593315Sopenharmony_ci}
10402c593315Sopenharmony_ci
10412c593315Sopenharmony_civoid test_http2_normalize_path(void) {
10422c593315Sopenharmony_ci  CU_ASSERT("/alpha/charlie" ==
10432c593315Sopenharmony_ci            http2::normalize_path(
10442c593315Sopenharmony_ci                StringRef::from_lit("/alpha/bravo/../charlie"), StringRef{}));
10452c593315Sopenharmony_ci
10462c593315Sopenharmony_ci  CU_ASSERT("/alpha" ==
10472c593315Sopenharmony_ci            http2::normalize_path(StringRef::from_lit("/a%6c%70%68%61"),
10482c593315Sopenharmony_ci                                  StringRef{}));
10492c593315Sopenharmony_ci
10502c593315Sopenharmony_ci  CU_ASSERT(
10512c593315Sopenharmony_ci      "/alpha%2F%3A" ==
10522c593315Sopenharmony_ci      http2::normalize_path(StringRef::from_lit("/alpha%2f%3a"), StringRef{}));
10532c593315Sopenharmony_ci
10542c593315Sopenharmony_ci  CU_ASSERT("/%2F" ==
10552c593315Sopenharmony_ci            http2::normalize_path(StringRef::from_lit("%2f"), StringRef{}));
10562c593315Sopenharmony_ci
10572c593315Sopenharmony_ci  CU_ASSERT("/%f" ==
10582c593315Sopenharmony_ci            http2::normalize_path(StringRef::from_lit("%f"), StringRef{}));
10592c593315Sopenharmony_ci
10602c593315Sopenharmony_ci  CU_ASSERT("/%" ==
10612c593315Sopenharmony_ci            http2::normalize_path(StringRef::from_lit("%"), StringRef{}));
10622c593315Sopenharmony_ci
10632c593315Sopenharmony_ci  CU_ASSERT("/" == http2::normalize_path(StringRef{}, StringRef{}));
10642c593315Sopenharmony_ci
10652c593315Sopenharmony_ci  CU_ASSERT("/alpha?bravo" ==
10662c593315Sopenharmony_ci            http2::normalize_path(StringRef::from_lit("/alpha"),
10672c593315Sopenharmony_ci                                  StringRef::from_lit("bravo")));
10682c593315Sopenharmony_ci}
10692c593315Sopenharmony_ci
10702c593315Sopenharmony_civoid test_http2_rewrite_clean_path(void) {
10712c593315Sopenharmony_ci  BlockAllocator balloc(4096, 4096);
10722c593315Sopenharmony_ci
10732c593315Sopenharmony_ci  // unreserved characters
10742c593315Sopenharmony_ci  CU_ASSERT("/alpha/bravo/" ==
10752c593315Sopenharmony_ci            http2::rewrite_clean_path(balloc,
10762c593315Sopenharmony_ci                                      StringRef::from_lit("/alpha/%62ravo/")));
10772c593315Sopenharmony_ci
10782c593315Sopenharmony_ci  // percent-encoding is converted to upper case.
10792c593315Sopenharmony_ci  CU_ASSERT("/delta%3A" == http2::rewrite_clean_path(
10802c593315Sopenharmony_ci                               balloc, StringRef::from_lit("/delta%3a")));
10812c593315Sopenharmony_ci
10822c593315Sopenharmony_ci  // path component is normalized before matching
10832c593315Sopenharmony_ci  CU_ASSERT(
10842c593315Sopenharmony_ci      "/alpha/bravo/" ==
10852c593315Sopenharmony_ci      http2::rewrite_clean_path(
10862c593315Sopenharmony_ci          balloc, StringRef::from_lit("/alpha/charlie/%2e././bravo/delta/..")));
10872c593315Sopenharmony_ci
10882c593315Sopenharmony_ci  CU_ASSERT("alpha%3a" ==
10892c593315Sopenharmony_ci            http2::rewrite_clean_path(balloc, StringRef::from_lit("alpha%3a")));
10902c593315Sopenharmony_ci
10912c593315Sopenharmony_ci  CU_ASSERT("" == http2::rewrite_clean_path(balloc, StringRef{}));
10922c593315Sopenharmony_ci
10932c593315Sopenharmony_ci  CU_ASSERT(
10942c593315Sopenharmony_ci      "/alpha?bravo" ==
10952c593315Sopenharmony_ci      http2::rewrite_clean_path(balloc, StringRef::from_lit("//alpha?bravo")));
10962c593315Sopenharmony_ci}
10972c593315Sopenharmony_ci
10982c593315Sopenharmony_civoid test_http2_get_pure_path_component(void) {
10992c593315Sopenharmony_ci  CU_ASSERT("/" == http2::get_pure_path_component(StringRef::from_lit("/")));
11002c593315Sopenharmony_ci
11012c593315Sopenharmony_ci  CU_ASSERT("/foo" ==
11022c593315Sopenharmony_ci            http2::get_pure_path_component(StringRef::from_lit("/foo")));
11032c593315Sopenharmony_ci
11042c593315Sopenharmony_ci  CU_ASSERT("/bar" == http2::get_pure_path_component(
11052c593315Sopenharmony_ci                          StringRef::from_lit("https://example.org/bar")));
11062c593315Sopenharmony_ci
11072c593315Sopenharmony_ci  CU_ASSERT("/alpha" == http2::get_pure_path_component(StringRef::from_lit(
11082c593315Sopenharmony_ci                            "https://example.org/alpha?q=a")));
11092c593315Sopenharmony_ci
11102c593315Sopenharmony_ci  CU_ASSERT("/bravo" == http2::get_pure_path_component(StringRef::from_lit(
11112c593315Sopenharmony_ci                            "https://example.org/bravo?q=a#fragment")));
11122c593315Sopenharmony_ci
11132c593315Sopenharmony_ci  CU_ASSERT("" ==
11142c593315Sopenharmony_ci            http2::get_pure_path_component(StringRef::from_lit("\x01\x02")));
11152c593315Sopenharmony_ci}
11162c593315Sopenharmony_ci
11172c593315Sopenharmony_civoid test_http2_construct_push_component(void) {
11182c593315Sopenharmony_ci  BlockAllocator balloc(4096, 4096);
11192c593315Sopenharmony_ci  StringRef base, uri;
11202c593315Sopenharmony_ci  StringRef scheme, authority, path;
11212c593315Sopenharmony_ci
11222c593315Sopenharmony_ci  base = StringRef::from_lit("/b/");
11232c593315Sopenharmony_ci  uri = StringRef::from_lit("https://example.org/foo");
11242c593315Sopenharmony_ci
11252c593315Sopenharmony_ci  CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority,
11262c593315Sopenharmony_ci                                                 path, base, uri));
11272c593315Sopenharmony_ci  CU_ASSERT("https" == scheme);
11282c593315Sopenharmony_ci  CU_ASSERT("example.org" == authority);
11292c593315Sopenharmony_ci  CU_ASSERT("/foo" == path);
11302c593315Sopenharmony_ci
11312c593315Sopenharmony_ci  scheme = StringRef{};
11322c593315Sopenharmony_ci  authority = StringRef{};
11332c593315Sopenharmony_ci  path = StringRef{};
11342c593315Sopenharmony_ci
11352c593315Sopenharmony_ci  uri = StringRef::from_lit("/foo/bar?q=a");
11362c593315Sopenharmony_ci
11372c593315Sopenharmony_ci  CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority,
11382c593315Sopenharmony_ci                                                 path, base, uri));
11392c593315Sopenharmony_ci  CU_ASSERT("" == scheme);
11402c593315Sopenharmony_ci  CU_ASSERT("" == authority);
11412c593315Sopenharmony_ci  CU_ASSERT("/foo/bar?q=a" == path);
11422c593315Sopenharmony_ci
11432c593315Sopenharmony_ci  scheme = StringRef{};
11442c593315Sopenharmony_ci  authority = StringRef{};
11452c593315Sopenharmony_ci  path = StringRef{};
11462c593315Sopenharmony_ci
11472c593315Sopenharmony_ci  uri = StringRef::from_lit("foo/../bar?q=a");
11482c593315Sopenharmony_ci
11492c593315Sopenharmony_ci  CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority,
11502c593315Sopenharmony_ci                                                 path, base, uri));
11512c593315Sopenharmony_ci  CU_ASSERT("" == scheme);
11522c593315Sopenharmony_ci  CU_ASSERT("" == authority);
11532c593315Sopenharmony_ci  CU_ASSERT("/b/bar?q=a" == path);
11542c593315Sopenharmony_ci
11552c593315Sopenharmony_ci  scheme = StringRef{};
11562c593315Sopenharmony_ci  authority = StringRef{};
11572c593315Sopenharmony_ci  path = StringRef{};
11582c593315Sopenharmony_ci
11592c593315Sopenharmony_ci  uri = StringRef{};
11602c593315Sopenharmony_ci
11612c593315Sopenharmony_ci  CU_ASSERT(-1 == http2::construct_push_component(balloc, scheme, authority,
11622c593315Sopenharmony_ci                                                  path, base, uri));
11632c593315Sopenharmony_ci  scheme = StringRef{};
11642c593315Sopenharmony_ci  authority = StringRef{};
11652c593315Sopenharmony_ci  path = StringRef{};
11662c593315Sopenharmony_ci
11672c593315Sopenharmony_ci  uri = StringRef::from_lit("?q=a");
11682c593315Sopenharmony_ci
11692c593315Sopenharmony_ci  CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority,
11702c593315Sopenharmony_ci                                                 path, base, uri));
11712c593315Sopenharmony_ci  CU_ASSERT("" == scheme);
11722c593315Sopenharmony_ci  CU_ASSERT("" == authority);
11732c593315Sopenharmony_ci  CU_ASSERT("/b/?q=a" == path);
11742c593315Sopenharmony_ci}
11752c593315Sopenharmony_ci
11762c593315Sopenharmony_civoid test_http2_contains_trailers(void) {
11772c593315Sopenharmony_ci  CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("")));
11782c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers")));
11792c593315Sopenharmony_ci  // Match must be case-insensitive.
11802c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("TRAILERS")));
11812c593315Sopenharmony_ci  CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailer")));
11822c593315Sopenharmony_ci  CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailers  3")));
11832c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,")));
11842c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,foo")));
11852c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers")));
11862c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers,bar")));
11872c593315Sopenharmony_ci  CU_ASSERT(
11882c593315Sopenharmony_ci      http2::contains_trailers(StringRef::from_lit("foo, trailers ,bar")));
11892c593315Sopenharmony_ci  CU_ASSERT(http2::contains_trailers(StringRef::from_lit(",trailers")));
11902c593315Sopenharmony_ci}
11912c593315Sopenharmony_ci
11922c593315Sopenharmony_civoid test_http2_check_transfer_encoding(void) {
11932c593315Sopenharmony_ci  CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("chunked")));
11942c593315Sopenharmony_ci  CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("foo,chunked")));
11952c593315Sopenharmony_ci  CU_ASSERT(
11962c593315Sopenharmony_ci      http2::check_transfer_encoding(StringRef::from_lit("foo,  chunked")));
11972c593315Sopenharmony_ci  CU_ASSERT(
11982c593315Sopenharmony_ci      http2::check_transfer_encoding(StringRef::from_lit("foo   ,  chunked")));
11992c593315Sopenharmony_ci  CU_ASSERT(
12002c593315Sopenharmony_ci      http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar")));
12012c593315Sopenharmony_ci  CU_ASSERT(
12022c593315Sopenharmony_ci      http2::check_transfer_encoding(StringRef::from_lit("chunked ; foo=bar")));
12032c593315Sopenharmony_ci  CU_ASSERT(http2::check_transfer_encoding(
12042c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="bar")")));
12052c593315Sopenharmony_ci  CU_ASSERT(http2::check_transfer_encoding(
12062c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="\bar\"";FOO=BAR)")));
12072c593315Sopenharmony_ci  CU_ASSERT(
12082c593315Sopenharmony_ci      http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="")")));
12092c593315Sopenharmony_ci  CU_ASSERT(http2::check_transfer_encoding(
12102c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="bar" , gzip)")));
12112c593315Sopenharmony_ci
12122c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef{}));
12132c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(",chunked")));
12142c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked,")));
12152c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked, ")));
12162c593315Sopenharmony_ci  CU_ASSERT(
12172c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit("foo,,chunked")));
12182c593315Sopenharmony_ci  CU_ASSERT(
12192c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo")));
12202c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;")));
12212c593315Sopenharmony_ci  CU_ASSERT(
12222c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar;")));
12232c593315Sopenharmony_ci  CU_ASSERT(
12242c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit("chunked;?=bar")));
12252c593315Sopenharmony_ci  CU_ASSERT(
12262c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit("chunked;=bar")));
12272c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;;")));
12282c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked?")));
12292c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(",")));
12302c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(" ")));
12312c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(";")));
12322c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("\"")));
12332c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(
12342c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="bar)")));
12352c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(
12362c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="bar\)")));
12372c593315Sopenharmony_ci  CU_ASSERT(
12382c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="bar\)"
12392c593315Sopenharmony_ci                                                          "\x0a"
12402c593315Sopenharmony_ci                                                          R"(")")));
12412c593315Sopenharmony_ci  CU_ASSERT(
12422c593315Sopenharmony_ci      !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo=")"
12432c593315Sopenharmony_ci                                                          "\x0a"
12442c593315Sopenharmony_ci                                                          R"(")")));
12452c593315Sopenharmony_ci  CU_ASSERT(!http2::check_transfer_encoding(
12462c593315Sopenharmony_ci      StringRef::from_lit(R"(chunked;foo="bar",,gzip)")));
12472c593315Sopenharmony_ci}
12482c593315Sopenharmony_ci
12492c593315Sopenharmony_ci} // namespace shrpx
1250