xref: /aosp_15_r20/external/cronet/net/spdy/header_coalescer_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/spdy/header_coalescer.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker #include <vector>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/log/test_net_log.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/log/test_net_log_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/spdy/spdy_test_util_common.h"
15*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
16*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker using ::testing::ElementsAre;
19*6777b538SAndroid Build Coastguard Worker using ::testing::Pair;
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker namespace net::test {
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker class HeaderCoalescerTest : public ::testing::Test {
24*6777b538SAndroid Build Coastguard Worker  public:
HeaderCoalescerTest()25*6777b538SAndroid Build Coastguard Worker   HeaderCoalescerTest()
26*6777b538SAndroid Build Coastguard Worker       : header_coalescer_(kMaxHeaderListSizeForTest, net_log_with_source_) {}
27*6777b538SAndroid Build Coastguard Worker 
ExpectEntry(std::string_view expected_header_name,std::string_view expected_header_value,std::string_view expected_error_message)28*6777b538SAndroid Build Coastguard Worker   void ExpectEntry(std::string_view expected_header_name,
29*6777b538SAndroid Build Coastguard Worker                    std::string_view expected_header_value,
30*6777b538SAndroid Build Coastguard Worker                    std::string_view expected_error_message) {
31*6777b538SAndroid Build Coastguard Worker     auto entry_list = net_log_observer_.GetEntries();
32*6777b538SAndroid Build Coastguard Worker     ASSERT_EQ(1u, entry_list.size());
33*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(entry_list[0].type,
34*6777b538SAndroid Build Coastguard Worker               NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER);
35*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(entry_list[0].source.id, net_log_with_source_.source().id);
36*6777b538SAndroid Build Coastguard Worker     std::string value;
37*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_header_name,
38*6777b538SAndroid Build Coastguard Worker               GetStringValueFromParams(entry_list[0], "header_name"));
39*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_header_value,
40*6777b538SAndroid Build Coastguard Worker               GetStringValueFromParams(entry_list[0], "header_value"));
41*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_error_message,
42*6777b538SAndroid Build Coastguard Worker               GetStringValueFromParams(entry_list[0], "error"));
43*6777b538SAndroid Build Coastguard Worker   }
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker  protected:
46*6777b538SAndroid Build Coastguard Worker   NetLogWithSource net_log_with_source_{
47*6777b538SAndroid Build Coastguard Worker       NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
48*6777b538SAndroid Build Coastguard Worker   RecordingNetLogObserver net_log_observer_;
49*6777b538SAndroid Build Coastguard Worker   HeaderCoalescer header_coalescer_;
50*6777b538SAndroid Build Coastguard Worker };
51*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,CorrectHeaders)52*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, CorrectHeaders) {
53*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader(":foo", "bar");
54*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("baz", "qux");
55*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
58*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(header_block,
59*6777b538SAndroid Build Coastguard Worker               ElementsAre(Pair(":foo", "bar"), Pair("baz", "qux")));
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,EmptyHeaderKey)62*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, EmptyHeaderKey) {
63*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("", "foo");
64*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
65*6777b538SAndroid Build Coastguard Worker   ExpectEntry("", "foo", "Header name must not be empty.");
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,HeaderBlockTooLarge)68*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderBlockTooLarge) {
69*6777b538SAndroid Build Coastguard Worker   // key + value + overhead = 3 + kMaxHeaderListSizeForTest - 40 + 32
70*6777b538SAndroid Build Coastguard Worker   // = kMaxHeaderListSizeForTest - 5
71*6777b538SAndroid Build Coastguard Worker   std::string data(kMaxHeaderListSizeForTest - 40, 'a');
72*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", data);
73*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   // Another 3 + 4 + 32 bytes: too large.
76*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("bar", "abcd");
77*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
78*6777b538SAndroid Build Coastguard Worker   ExpectEntry("bar", "abcd", "Header list too large.");
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,PseudoHeadersMustNotFollowRegularHeaders)81*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, PseudoHeadersMustNotFollowRegularHeaders) {
82*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "bar");
83*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
84*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader(":baz", "qux");
85*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
86*6777b538SAndroid Build Coastguard Worker   ExpectEntry(":baz", "qux", "Pseudo header must not follow regular headers.");
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,Append)89*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, Append) {
90*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "bar");
91*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("cookie", "baz");
92*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "quux");
93*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("cookie", "qux");
94*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
97*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(header_block,
98*6777b538SAndroid Build Coastguard Worker               ElementsAre(Pair("foo", std::string_view("bar\0quux", 8)),
99*6777b538SAndroid Build Coastguard Worker                           Pair("cookie", "baz; qux")));
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,HeaderNameNotValid)102*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderNameNotValid) {
103*6777b538SAndroid Build Coastguard Worker   std::string_view header_name("\x1\x7F\x80\xFF");
104*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader(header_name, "foo");
105*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
106*6777b538SAndroid Build Coastguard Worker   ExpectEntry("%ESCAPED:\xE2\x80\x8B \x1\x7F%80%FF", "foo",
107*6777b538SAndroid Build Coastguard Worker               "Invalid character in header name.");
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker // RFC 7540 Section 8.1.2.6. Uppercase in header name is invalid.
TEST_F(HeaderCoalescerTest,HeaderNameHasUppercase)111*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderNameHasUppercase) {
112*6777b538SAndroid Build Coastguard Worker   std::string_view header_name("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
113*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader(header_name, "foo");
114*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
115*6777b538SAndroid Build Coastguard Worker   ExpectEntry("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "foo",
116*6777b538SAndroid Build Coastguard Worker               "Upper case characters in header name.");
117*6777b538SAndroid Build Coastguard Worker }
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker // RFC 7230 Section 3.2. Valid header name is defined as:
120*6777b538SAndroid Build Coastguard Worker // field-name     = token
121*6777b538SAndroid Build Coastguard Worker // token          = 1*tchar
122*6777b538SAndroid Build Coastguard Worker // tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
123*6777b538SAndroid Build Coastguard Worker //                  "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
TEST_F(HeaderCoalescerTest,HeaderNameValid)124*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderNameValid) {
125*6777b538SAndroid Build Coastguard Worker   // Due to RFC 7540 Section 8.1.2.6. Uppercase characters are not included.
126*6777b538SAndroid Build Coastguard Worker   std::string_view header_name(
127*6777b538SAndroid Build Coastguard Worker       "abcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+-."
128*6777b538SAndroid Build Coastguard Worker       "^_`|~");
129*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader(header_name, "foo");
130*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
131*6777b538SAndroid Build Coastguard Worker   spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
132*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(header_block, ElementsAre(Pair(header_name, "foo")));
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker // According to RFC 7540 Section 10.3 and RFC 7230 Section 3.2, allowed
136*6777b538SAndroid Build Coastguard Worker // characters in header values are '\t', '  ', 0x21 to 0x7E, and 0x80 to 0xFF.
TEST_F(HeaderCoalescerTest,HeaderValueValid)137*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderValueValid) {
138*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", " bar \x21 \x7e baz\tqux\x80\xff ");
139*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(header_coalescer_.error_seen());
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,HeaderValueContainsLF)142*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderValueContainsLF) {
143*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "bar\nbaz");
144*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
145*6777b538SAndroid Build Coastguard Worker   ExpectEntry("foo", "bar\nbaz", "Invalid character 0x0A in header value.");
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,HeaderValueContainsCR)148*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderValueContainsCR) {
149*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "bar\rbaz");
150*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
151*6777b538SAndroid Build Coastguard Worker   ExpectEntry("foo", "bar\rbaz", "Invalid character 0x0D in header value.");
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
TEST_F(HeaderCoalescerTest,HeaderValueContains0x7f)154*6777b538SAndroid Build Coastguard Worker TEST_F(HeaderCoalescerTest, HeaderValueContains0x7f) {
155*6777b538SAndroid Build Coastguard Worker   header_coalescer_.OnHeader("foo", "bar\x7f baz");
156*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(header_coalescer_.error_seen());
157*6777b538SAndroid Build Coastguard Worker   ExpectEntry("foo", "bar\x7F baz", "Invalid character 0x7F in header value.");
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker 
160*6777b538SAndroid Build Coastguard Worker }  // namespace net::test
161