xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/test_tools/http2_frame_builder_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/http2/test_tools/http2_frame_builder.h"
6 
7 #include <string>
8 
9 #include "absl/strings/escaping.h"
10 #include "quiche/common/platform/api/quiche_test.h"
11 
12 namespace http2 {
13 namespace test {
14 namespace {
15 
16 const char kHighBitSetMsg[] = "High-bit of uint32_t should be clear";
17 
TEST(Http2FrameBuilderTest,Constructors)18 TEST(Http2FrameBuilderTest, Constructors) {
19   {
20     Http2FrameBuilder fb;
21     EXPECT_EQ(0u, fb.size());
22   }
23   {
24     Http2FrameBuilder fb(Http2FrameType::DATA, 0, 123);
25     EXPECT_EQ(9u, fb.size());
26 
27     std::string expected_data;
28     ASSERT_TRUE(
29         absl::HexStringToBytes("000000"     // Payload length: 0 (unset)
30                                "00"         // Frame type: DATA
31                                "00"         // Flags: none
32                                "0000007b",  // Stream ID: 123
33                                &expected_data));
34     EXPECT_EQ(expected_data, fb.buffer());
35   }
36   {
37     Http2FrameHeader header;
38     header.payload_length = (1 << 24) - 1;
39     header.type = Http2FrameType::HEADERS;
40     header.flags = Http2FrameFlag::END_HEADERS;
41     header.stream_id = StreamIdMask();
42     Http2FrameBuilder fb(header);
43     EXPECT_EQ(9u, fb.size());
44 
45     std::string expected_data;
46     ASSERT_TRUE(absl::HexStringToBytes(
47         "ffffff"     // Payload length: 2^24 - 1 (max uint24)
48         "01"         // Frame type: HEADER
49         "04"         // Flags: END_HEADERS
50         "7fffffff",  // Stream ID: stream id mask
51         &expected_data));
52     EXPECT_EQ(expected_data, fb.buffer());
53   }
54 }
55 
TEST(Http2FrameBuilderTest,SetPayloadLength)56 TEST(Http2FrameBuilderTest, SetPayloadLength) {
57   Http2FrameBuilder fb(Http2FrameType::DATA, PADDED, 20000);
58   EXPECT_EQ(9u, fb.size());
59 
60   fb.AppendUInt8(50);  // Trailing payload length
61   EXPECT_EQ(10u, fb.size());
62 
63   fb.Append("ten bytes.");
64   EXPECT_EQ(20u, fb.size());
65 
66   fb.AppendZeroes(50);
67   EXPECT_EQ(70u, fb.size());
68 
69   fb.SetPayloadLength();
70   EXPECT_EQ(70u, fb.size());
71 
72   std::string expected_data;
73   ASSERT_TRUE(
74       absl::HexStringToBytes("00003d"                 // Payload length: 61
75                              "00"                     // Frame type: DATA
76                              "08"                     // Flags: PADDED
77                              "00004e20"               // Stream ID: 20000
78                              "32"                     // Padding Length: 50
79                              "74656e2062797465732e"   // "ten bytes."
80                              "00000000000000000000"   // Padding bytes
81                              "00000000000000000000"   // Padding bytes
82                              "00000000000000000000"   // Padding bytes
83                              "00000000000000000000"   // Padding bytes
84                              "00000000000000000000",  // Padding bytes
85                              &expected_data));
86   EXPECT_EQ(expected_data, fb.buffer());
87 }
88 
TEST(Http2FrameBuilderTest,Settings)89 TEST(Http2FrameBuilderTest, Settings) {
90   Http2FrameBuilder fb(Http2FrameType::SETTINGS, 0, 0);
91   Http2SettingFields sf;
92 
93   sf.parameter = Http2SettingsParameter::HEADER_TABLE_SIZE;
94   sf.value = 1 << 12;
95   fb.Append(sf);
96 
97   sf.parameter = Http2SettingsParameter::ENABLE_PUSH;
98   sf.value = 0;
99   fb.Append(sf);
100 
101   sf.parameter = Http2SettingsParameter::MAX_CONCURRENT_STREAMS;
102   sf.value = ~0;
103   fb.Append(sf);
104 
105   sf.parameter = Http2SettingsParameter::INITIAL_WINDOW_SIZE;
106   sf.value = 1 << 16;
107   fb.Append(sf);
108 
109   sf.parameter = Http2SettingsParameter::MAX_FRAME_SIZE;
110   sf.value = 1 << 14;
111   fb.Append(sf);
112 
113   sf.parameter = Http2SettingsParameter::MAX_HEADER_LIST_SIZE;
114   sf.value = 1 << 10;
115   fb.Append(sf);
116 
117   size_t payload_size = 6 * Http2SettingFields::EncodedSize();
118   EXPECT_EQ(Http2FrameHeader::EncodedSize() + payload_size, fb.size());
119 
120   fb.SetPayloadLength(payload_size);
121 
122   std::string expected_data;
123   ASSERT_TRUE(
124       absl::HexStringToBytes("000024"     // Payload length: 36
125                              "04"         // Frame type: SETTINGS
126                              "00"         // Flags: none
127                              "00000000"   // Stream ID: 0
128                              "0001"       // HEADER_TABLE_SIZE
129                              "00001000"   // 4096
130                              "0002"       // ENABLE_PUSH
131                              "00000000"   // 0
132                              "0003"       // MAX_CONCURRENT_STREAMS
133                              "ffffffff"   // 0xffffffff (max uint32)
134                              "0004"       // INITIAL_WINDOW_SIZE
135                              "00010000"   // 4096
136                              "0005"       // MAX_FRAME_SIZE
137                              "00004000"   // 4096
138                              "0006"       // MAX_HEADER_LIST_SIZE
139                              "00000400",  // 1024
140                              &expected_data));
141   EXPECT_EQ(expected_data, fb.buffer());
142 }
143 
TEST(Http2FrameBuilderTest,EnhanceYourCalm)144 TEST(Http2FrameBuilderTest, EnhanceYourCalm) {
145   std::string expected_data;
146   ASSERT_TRUE(absl::HexStringToBytes("0000000b", &expected_data));
147   {
148     Http2FrameBuilder fb;
149     fb.Append(Http2ErrorCode::ENHANCE_YOUR_CALM);
150     EXPECT_EQ(expected_data, fb.buffer());
151   }
152   {
153     Http2FrameBuilder fb;
154     Http2RstStreamFields rsp;
155     rsp.error_code = Http2ErrorCode::ENHANCE_YOUR_CALM;
156     fb.Append(rsp);
157     EXPECT_EQ(expected_data, fb.buffer());
158   }
159 }
160 
TEST(Http2FrameBuilderTest,PushPromise)161 TEST(Http2FrameBuilderTest, PushPromise) {
162   std::string expected_data;
163   ASSERT_TRUE(absl::HexStringToBytes("7fffffff", &expected_data));
164   {
165     Http2FrameBuilder fb;
166     fb.Append(Http2PushPromiseFields{0x7fffffff});
167     EXPECT_EQ(expected_data, fb.buffer());
168   }
169   {
170     Http2FrameBuilder fb;
171     // Will generate an error if the high-bit of the stream id is set.
172     EXPECT_NONFATAL_FAILURE(fb.Append(Http2PushPromiseFields{0xffffffff}),
173                             kHighBitSetMsg);
174     EXPECT_EQ(expected_data, fb.buffer());
175   }
176 }
177 
TEST(Http2FrameBuilderTest,Ping)178 TEST(Http2FrameBuilderTest, Ping) {
179   Http2FrameBuilder fb;
180   Http2PingFields ping{"8 bytes"};
181   fb.Append(ping);
182 
183   const absl::string_view kData{"8 bytes\0", 8};
184   EXPECT_EQ(kData.size(), Http2PingFields::EncodedSize());
185   EXPECT_EQ(kData, fb.buffer());
186 }
187 
TEST(Http2FrameBuilderTest,GoAway)188 TEST(Http2FrameBuilderTest, GoAway) {
189   std::string expected_data;
190   ASSERT_TRUE(
191       absl::HexStringToBytes("12345678"   // Last Stream Id
192                              "00000001",  // Error code
193                              &expected_data));
194   EXPECT_EQ(expected_data.size(), Http2GoAwayFields::EncodedSize());
195   {
196     Http2FrameBuilder fb;
197     Http2GoAwayFields ga(0x12345678, Http2ErrorCode::PROTOCOL_ERROR);
198     fb.Append(ga);
199     EXPECT_EQ(expected_data, fb.buffer());
200   }
201   {
202     Http2FrameBuilder fb;
203     // Will generate a test failure if the high-bit of the stream id is set.
204     Http2GoAwayFields ga(0x92345678, Http2ErrorCode::PROTOCOL_ERROR);
205     EXPECT_NONFATAL_FAILURE(fb.Append(ga), kHighBitSetMsg);
206     EXPECT_EQ(expected_data, fb.buffer());
207   }
208 }
209 
TEST(Http2FrameBuilderTest,WindowUpdate)210 TEST(Http2FrameBuilderTest, WindowUpdate) {
211   Http2FrameBuilder fb;
212   fb.Append(Http2WindowUpdateFields{123456});
213 
214   // Will generate a test failure if the high-bit of the increment is set.
215   EXPECT_NONFATAL_FAILURE(fb.Append(Http2WindowUpdateFields{0x80000001}),
216                           kHighBitSetMsg);
217 
218   // Will generate a test failure if the increment is zero.
219   EXPECT_NONFATAL_FAILURE(fb.Append(Http2WindowUpdateFields{0}), "non-zero");
220 
221   std::string expected_data;
222   ASSERT_TRUE(
223       absl::HexStringToBytes("0001e240"   // Valid Window Size Increment
224                              "00000001"   // High-bit cleared
225                              "00000000",  // Invalid Window Size Increment
226                              &expected_data));
227   EXPECT_EQ(expected_data.size(), 3 * Http2WindowUpdateFields::EncodedSize());
228   EXPECT_EQ(expected_data, fb.buffer());
229 }
230 
TEST(Http2FrameBuilderTest,AltSvc)231 TEST(Http2FrameBuilderTest, AltSvc) {
232   Http2FrameBuilder fb;
233   fb.Append(Http2AltSvcFields{99});
234   fb.Append(Http2AltSvcFields{0});  // No optional origin
235   std::string expected_data;
236   ASSERT_TRUE(
237       absl::HexStringToBytes("0063"   // Has origin.
238                              "0000",  // Doesn't have origin.
239                              &expected_data));
240   EXPECT_EQ(expected_data.size(), 2 * Http2AltSvcFields::EncodedSize());
241   EXPECT_EQ(expected_data, fb.buffer());
242 }
243 
244 }  // namespace
245 }  // namespace test
246 }  // namespace http2
247