OLD | NEW |
| (Empty) |
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 #include "net/quic/spdy_utils.h" | |
5 | |
6 #include "base/macros.h" | |
7 #include "base/strings/string_number_conversions.h" | |
8 #include "base/strings/string_piece.h" | |
9 #include "net/test/gtest_util.h" | |
10 | |
11 using base::StringPiece; | |
12 using std::string; | |
13 using testing::UnorderedElementsAre; | |
14 using testing::Pair; | |
15 | |
16 namespace net { | |
17 namespace test { | |
18 | |
19 TEST(SpdyUtilsTest, SerializeAndParseHeaders) { | |
20 // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then | |
21 // parses the serialized output and verifies that the end result is the same | |
22 // as the headers that the test started with. | |
23 | |
24 SpdyHeaderBlock input_headers; | |
25 input_headers[":pseudo1"] = "pseudo value1"; | |
26 input_headers[":pseudo2"] = "pseudo value2"; | |
27 input_headers["key1"] = "value1"; | |
28 const int64_t kContentLength = 1234; | |
29 input_headers["content-length"] = base::Int64ToString(kContentLength); | |
30 input_headers["key2"] = "value2"; | |
31 | |
32 // Serialize the header block. | |
33 string serialized_headers = | |
34 SpdyUtils::SerializeUncompressedHeaders(input_headers); | |
35 | |
36 // Take the serialized header block, and parse back into SpdyHeaderBlock. | |
37 SpdyHeaderBlock output_headers; | |
38 int64_t content_length = -1; | |
39 ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), | |
40 serialized_headers.size(), | |
41 &content_length, &output_headers)); | |
42 | |
43 // Should be back to the original headers. | |
44 EXPECT_EQ(content_length, kContentLength); | |
45 EXPECT_EQ(output_headers, input_headers); | |
46 } | |
47 | |
48 TEST(SpdyUtilsTest, SerializeAndParseHeadersLargeContentLength) { | |
49 // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then | |
50 // parses the serialized output and verifies that the end result is the same | |
51 // as the headers that the test started with. | |
52 | |
53 SpdyHeaderBlock input_headers; | |
54 input_headers[":pseudo1"] = "pseudo value1"; | |
55 input_headers[":pseudo2"] = "pseudo value2"; | |
56 input_headers["key1"] = "value1"; | |
57 const int64_t kContentLength = 12345678900; | |
58 input_headers["content-length"] = base::Int64ToString(kContentLength); | |
59 input_headers["key2"] = "value2"; | |
60 | |
61 // Serialize the header block. | |
62 string serialized_headers = | |
63 SpdyUtils::SerializeUncompressedHeaders(input_headers); | |
64 | |
65 // Take the serialized header block, and parse back into SpdyHeaderBlock. | |
66 SpdyHeaderBlock output_headers; | |
67 int64_t content_length = -1; | |
68 ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), | |
69 serialized_headers.size(), | |
70 &content_length, &output_headers)); | |
71 | |
72 // Should be back to the original headers. | |
73 EXPECT_EQ(content_length, kContentLength); | |
74 EXPECT_EQ(output_headers, input_headers); | |
75 } | |
76 | |
77 TEST(SpdyUtilsTest, SerializeAndParseValidTrailers) { | |
78 // Creates a SpdyHeaderBlock with some valid Trailers key->value pairs, | |
79 // serializes it, then parses the serialized output and verifies that the end | |
80 // result is the same as the trailers that the test started with. | |
81 SpdyHeaderBlock input_trailers; | |
82 const size_t kFinalOffset = 5678; | |
83 input_trailers[kFinalOffsetHeaderKey] = base::IntToString(kFinalOffset); | |
84 input_trailers["key1"] = "value1"; | |
85 input_trailers["key2"] = "value2"; | |
86 | |
87 // Serialize the trailers. | |
88 string serialized_trailers = | |
89 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
90 | |
91 // Take the serialized trailers, and parse back into a SpdyHeaderBlock. | |
92 SpdyHeaderBlock output_trailers; | |
93 size_t final_byte_offset = 0; | |
94 EXPECT_TRUE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
95 serialized_trailers.size(), | |
96 &final_byte_offset, &output_trailers)); | |
97 | |
98 // Should be back to the original trailers, without the final offset header. | |
99 EXPECT_EQ(final_byte_offset, kFinalOffset); | |
100 input_trailers.erase(kFinalOffsetHeaderKey); | |
101 EXPECT_EQ(output_trailers, input_trailers); | |
102 } | |
103 | |
104 TEST(SpdyUtilsTest, SerializeAndParseTrailersWithoutFinalOffset) { | |
105 // Verifies that parsing fails if Trailers are missing a final offset header. | |
106 | |
107 SpdyHeaderBlock input_trailers; | |
108 input_trailers["key1"] = "value1"; | |
109 input_trailers["key2"] = "value2"; | |
110 | |
111 // Serialize the trailers. | |
112 string serialized_trailers = | |
113 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
114 | |
115 // Parsing the serialized trailers fails because of the missing final offset. | |
116 SpdyHeaderBlock output_trailers; | |
117 size_t final_byte_offset = 0; | |
118 EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
119 serialized_trailers.size(), | |
120 &final_byte_offset, &output_trailers)); | |
121 EXPECT_EQ(final_byte_offset, 0u); | |
122 } | |
123 | |
124 TEST(SpdyUtilsTest, SerializeAndParseTrailersWithPseudoHeaders) { | |
125 // Verifies that parsing fails if Trailers include pseudo-headers. | |
126 | |
127 SpdyHeaderBlock input_trailers; | |
128 input_trailers[kFinalOffsetHeaderKey] = "12345"; | |
129 input_trailers[":disallowed-pseudo-header"] = "pseudo value"; | |
130 input_trailers["key1"] = "value1"; | |
131 input_trailers["key2"] = "value2"; | |
132 | |
133 // Serialize the trailers. | |
134 string serialized_trailers = | |
135 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
136 | |
137 // Parsing the serialized trailers fails because of the extra pseudo header. | |
138 SpdyHeaderBlock output_trailers; | |
139 size_t final_byte_offset = 0; | |
140 EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
141 serialized_trailers.size(), | |
142 &final_byte_offset, &output_trailers)); | |
143 } | |
144 static std::unique_ptr<QuicHeaderList> FromList( | |
145 const QuicHeaderList::ListType& src) { | |
146 std::unique_ptr<QuicHeaderList> headers(new QuicHeaderList); | |
147 headers->OnHeaderBlockStart(); | |
148 for (const auto& p : src) { | |
149 headers->OnHeader(p.first, p.second); | |
150 } | |
151 headers->OnHeaderBlockEnd(0); | |
152 return headers; | |
153 } | |
154 | |
155 TEST(SpdyUtilsTest, CopyAndValidateHeaders) { | |
156 auto headers = FromList({// All cookie crumbs are joined. | |
157 {"cookie", " part 1"}, | |
158 {"cookie", "part 2 "}, | |
159 {"cookie", "part3"}, | |
160 | |
161 // Already-delimited headers are passed through. | |
162 {"passed-through", string("foo\0baz", 7)}, | |
163 | |
164 // Other headers are joined on \0. | |
165 {"joined", "value 1"}, | |
166 {"joined", "value 2"}, | |
167 | |
168 // Empty headers remain empty. | |
169 {"empty", ""}, | |
170 | |
171 // Joined empty headers work as expected. | |
172 {"empty-joined", ""}, | |
173 {"empty-joined", "foo"}, | |
174 {"empty-joined", ""}, | |
175 {"empty-joined", ""}, | |
176 | |
177 // Non-continguous cookie crumb. | |
178 {"cookie", " fin!"}}); | |
179 | |
180 int64_t content_length = -1; | |
181 SpdyHeaderBlock block; | |
182 ASSERT_TRUE( | |
183 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
184 EXPECT_THAT(block, UnorderedElementsAre( | |
185 Pair("cookie", " part 1; part 2 ; part3; fin!"), | |
186 Pair("passed-through", StringPiece("foo\0baz", 7)), | |
187 Pair("joined", StringPiece("value 1\0value 2", 15)), | |
188 Pair("empty", ""), | |
189 Pair("empty-joined", StringPiece("\0foo\0\0", 6)))); | |
190 EXPECT_EQ(-1, content_length); | |
191 } | |
192 | |
193 TEST(SpdyUtilsTest, CopyAndValidateHeadersEmptyName) { | |
194 auto headers = FromList({{"foo", "foovalue"}, {"", "barvalue"}, {"baz", ""}}); | |
195 int64_t content_length = -1; | |
196 SpdyHeaderBlock block; | |
197 ASSERT_FALSE( | |
198 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
199 } | |
200 | |
201 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleContentLengths) { | |
202 auto headers = FromList({{"content-length", "9"}, | |
203 {"foo", "foovalue"}, | |
204 {"content-length", "9"}, | |
205 {"bar", "barvalue"}, | |
206 {"baz", ""}}); | |
207 int64_t content_length = -1; | |
208 SpdyHeaderBlock block; | |
209 ASSERT_TRUE( | |
210 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
211 EXPECT_THAT(block, UnorderedElementsAre( | |
212 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
213 Pair("content-length", StringPiece("9" | |
214 "\0" | |
215 "9", | |
216 3)), | |
217 Pair("baz", ""))); | |
218 EXPECT_EQ(9, content_length); | |
219 } | |
220 | |
221 TEST(SpdyUtilsTest, CopyAndValidateHeadersInconsistentContentLengths) { | |
222 auto headers = FromList({{"content-length", "9"}, | |
223 {"foo", "foovalue"}, | |
224 {"content-length", "8"}, | |
225 {"bar", "barvalue"}, | |
226 {"baz", ""}}); | |
227 int64_t content_length = -1; | |
228 SpdyHeaderBlock block; | |
229 ASSERT_FALSE( | |
230 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
231 } | |
232 | |
233 TEST(SpdyUtilsTest, CopyAndValidateHeadersLargeContentLength) { | |
234 auto headers = FromList({{"content-length", "9000000000"}, | |
235 {"foo", "foovalue"}, | |
236 {"bar", "barvalue"}, | |
237 {"baz", ""}}); | |
238 int64_t content_length = -1; | |
239 SpdyHeaderBlock block; | |
240 ASSERT_TRUE( | |
241 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
242 EXPECT_THAT(block, UnorderedElementsAre( | |
243 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
244 Pair("content-length", StringPiece("9000000000")), | |
245 Pair("baz", ""))); | |
246 EXPECT_EQ(9000000000, content_length); | |
247 } | |
248 | |
249 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleValues) { | |
250 auto headers = FromList({{"foo", "foovalue"}, | |
251 {"bar", "barvalue"}, | |
252 {"baz", ""}, | |
253 {"foo", "boo"}, | |
254 {"baz", "buzz"}}); | |
255 int64_t content_length = -1; | |
256 SpdyHeaderBlock block; | |
257 ASSERT_TRUE( | |
258 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
259 EXPECT_THAT( | |
260 block, UnorderedElementsAre(Pair("foo", StringPiece("foovalue\0boo", 12)), | |
261 Pair("bar", "barvalue"), | |
262 Pair("baz", StringPiece("\0buzz", 5)))); | |
263 EXPECT_EQ(-1, content_length); | |
264 } | |
265 | |
266 TEST(SpdyUtilsTest, CopyAndValidateHeadersMoreThanTwoValues) { | |
267 auto headers = FromList({{"set-cookie", "value1"}, | |
268 {"set-cookie", "value2"}, | |
269 {"set-cookie", "value3"}}); | |
270 int64_t content_length = -1; | |
271 SpdyHeaderBlock block; | |
272 ASSERT_TRUE( | |
273 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
274 EXPECT_THAT(block, | |
275 UnorderedElementsAre(Pair( | |
276 "set-cookie", StringPiece("value1\0value2\0value3", 20)))); | |
277 EXPECT_EQ(-1, content_length); | |
278 } | |
279 | |
280 TEST(SpdyUtilsTest, CopyAndValidateHeadersCookie) { | |
281 auto headers = FromList({{"foo", "foovalue"}, | |
282 {"bar", "barvalue"}, | |
283 {"cookie", "value1"}, | |
284 {"baz", ""}}); | |
285 int64_t content_length = -1; | |
286 SpdyHeaderBlock block; | |
287 ASSERT_TRUE( | |
288 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
289 EXPECT_THAT(block, UnorderedElementsAre( | |
290 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
291 Pair("cookie", "value1"), Pair("baz", ""))); | |
292 EXPECT_EQ(-1, content_length); | |
293 } | |
294 | |
295 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleCookies) { | |
296 auto headers = FromList({{"foo", "foovalue"}, | |
297 {"bar", "barvalue"}, | |
298 {"cookie", "value1"}, | |
299 {"baz", ""}, | |
300 {"cookie", "value2"}}); | |
301 int64_t content_length = -1; | |
302 SpdyHeaderBlock block; | |
303 ASSERT_TRUE( | |
304 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
305 EXPECT_THAT(block, UnorderedElementsAre( | |
306 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
307 Pair("cookie", "value1; value2"), Pair("baz", ""))); | |
308 EXPECT_EQ(-1, content_length); | |
309 } | |
310 | |
311 TEST(SpdyUtilsTest, GetUrlFromHeaderBlock) { | |
312 SpdyHeaderBlock headers; | |
313 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
314 headers[":scheme"] = "https"; | |
315 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
316 headers[":authority"] = "www.google.com"; | |
317 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
318 headers[":path"] = "/index.html"; | |
319 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), | |
320 "https://www.google.com/index.html"); | |
321 headers["key1"] = "value1"; | |
322 headers["key2"] = "value2"; | |
323 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), | |
324 "https://www.google.com/index.html"); | |
325 } | |
326 | |
327 TEST(SpdyUtilsTest, GetHostNameFromHeaderBlock) { | |
328 SpdyHeaderBlock headers; | |
329 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
330 headers[":scheme"] = "https"; | |
331 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
332 headers[":authority"] = "www.google.com"; | |
333 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
334 headers[":path"] = "/index.html"; | |
335 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
336 headers["key1"] = "value1"; | |
337 headers["key2"] = "value2"; | |
338 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
339 headers[":authority"] = "www.google.com:6666"; | |
340 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
341 headers[":authority"] = "192.168.1.1"; | |
342 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1"); | |
343 headers[":authority"] = "192.168.1.1:6666"; | |
344 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1"); | |
345 } | |
346 | |
347 TEST(SpdyUtilsTest, UrlIsValid) { | |
348 SpdyHeaderBlock headers; | |
349 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
350 headers[":scheme"] = "https"; | |
351 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
352 headers[":authority"] = "www.google.com"; | |
353 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
354 headers[":path"] = "/index.html"; | |
355 EXPECT_TRUE(SpdyUtils::UrlIsValid(headers)); | |
356 } | |
357 | |
358 } // namespace test | |
359 } // namespace net | |
OLD | NEW |