OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/hpack_decoder.h" | 5 #include "net/spdy/hpack_decoder.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
13 #include "net/spdy/hpack_encoder.h" | 13 #include "net/spdy/hpack_encoder.h" |
14 #include "net/spdy/hpack_input_stream.h" | 14 #include "net/spdy/hpack_input_stream.h" |
15 #include "net/spdy/hpack_output_stream.h" | 15 #include "net/spdy/hpack_output_stream.h" |
16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
21 namespace test { | 21 namespace test { |
22 | 22 |
23 using base::StringPiece; | 23 using base::StringPiece; |
24 using std::string; | 24 using std::string; |
25 | 25 |
26 class HpackEncodingContextPeer { | |
27 public: | |
28 explicit HpackEncodingContextPeer(const HpackEncodingContext& context) | |
29 : context_(context) {} | |
30 const HpackHeaderTable& header_table() { | |
31 return context_.header_table_; | |
32 } | |
33 | |
34 private: | |
35 const HpackEncodingContext& context_; | |
36 }; | |
37 | |
38 class HpackDecoderPeer { | 26 class HpackDecoderPeer { |
39 public: | 27 public: |
40 explicit HpackDecoderPeer(HpackDecoder* decoder) | 28 explicit HpackDecoderPeer(HpackDecoder* decoder) |
41 : decoder_(decoder) {} | 29 : decoder_(decoder) {} |
42 | 30 |
43 void HandleHeaderRepresentation(StringPiece name, StringPiece value) { | 31 void HandleHeaderRepresentation(StringPiece name, StringPiece value) { |
44 decoder_->HandleHeaderRepresentation(name, value); | 32 decoder_->HandleHeaderRepresentation(name, value); |
45 } | 33 } |
46 bool DecodeNextName(HpackInputStream* in, StringPiece* out) { | 34 bool DecodeNextName(HpackInputStream* in, StringPiece* out) { |
47 return decoder_->DecodeNextName(in, out); | 35 return decoder_->DecodeNextName(in, out); |
48 } | 36 } |
49 HpackEncodingContextPeer context_peer() { | 37 const HpackHeaderTable& header_table() { |
50 return HpackEncodingContextPeer(decoder_->context_); | 38 return decoder_->header_table_; |
51 } | 39 } |
52 void set_cookie_name(string name) { | 40 void set_cookie_name(string name) { |
53 decoder_->cookie_name_ = name; | 41 decoder_->cookie_name_ = name; |
54 } | 42 } |
55 string cookie_name() { | 43 string cookie_name() { |
56 return decoder_->cookie_name_; | 44 return decoder_->cookie_name_; |
57 } | 45 } |
58 void set_cookie_value(string value) { | 46 void set_cookie_value(string value) { |
59 decoder_->cookie_value_ = value; | 47 decoder_->cookie_value_ = value; |
60 } | 48 } |
(...skipping 20 matching lines...) Expand all Loading... |
81 | 69 |
82 using testing::ElementsAre; | 70 using testing::ElementsAre; |
83 using testing::Pair; | 71 using testing::Pair; |
84 | 72 |
85 const size_t kLiteralBound = 1024; | 73 const size_t kLiteralBound = 1024; |
86 | 74 |
87 class HpackDecoderTest : public ::testing::Test { | 75 class HpackDecoderTest : public ::testing::Test { |
88 protected: | 76 protected: |
89 HpackDecoderTest() | 77 HpackDecoderTest() |
90 : decoder_(ObtainHpackHuffmanTable()), | 78 : decoder_(ObtainHpackHuffmanTable()), |
91 decoder_peer_(&decoder_), | 79 decoder_peer_(&decoder_) {} |
92 context_peer_(decoder_peer_.context_peer()) {} | |
93 | 80 |
94 bool DecodeHeaderBlock(StringPiece str) { | 81 bool DecodeHeaderBlock(StringPiece str) { |
95 return decoder_.HandleControlFrameHeadersData(0, str.data(), str.size()) && | 82 return decoder_.HandleControlFrameHeadersData(0, str.data(), str.size()) && |
96 decoder_.HandleControlFrameHeadersComplete(0); | 83 decoder_.HandleControlFrameHeadersComplete(0); |
97 } | 84 } |
98 const std::map<string, string>& decoded_block() const { | 85 const std::map<string, string>& decoded_block() const { |
99 // TODO(jgraettinger): HpackDecoderTest should implement | 86 // TODO(jgraettinger): HpackDecoderTest should implement |
100 // SpdyHeadersHandlerInterface, and collect headers for examination. | 87 // SpdyHeadersHandlerInterface, and collect headers for examination. |
101 return decoder_peer_.decoded_block(); | 88 return decoder_peer_.decoded_block(); |
102 } | 89 } |
103 // TODO(jgraettinger): Eliminate uses of this in tests below. Prefer | 90 // TODO(jgraettinger): Eliminate uses of this in tests below. Prefer |
104 // DecodeHeaderBlock(). | 91 // DecodeHeaderBlock(). |
105 const std::map<string, string>& DecodeUniqueHeaderSet(StringPiece str) { | 92 const std::map<string, string>& DecodeUniqueHeaderSet(StringPiece str) { |
106 EXPECT_TRUE(DecodeHeaderBlock(str)); | 93 EXPECT_TRUE(DecodeHeaderBlock(str)); |
107 return decoded_block(); | 94 return decoded_block(); |
108 } | 95 } |
109 | 96 |
110 HpackDecoder decoder_; | 97 HpackDecoder decoder_; |
111 test::HpackDecoderPeer decoder_peer_; | 98 test::HpackDecoderPeer decoder_peer_; |
112 test::HpackEncodingContextPeer context_peer_; | |
113 }; | 99 }; |
114 | 100 |
115 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) { | 101 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) { |
116 // Strings under threshold are concatenated in the buffer. | 102 // Strings under threshold are concatenated in the buffer. |
117 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( | 103 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( |
118 0, "small string one", 16)); | 104 0, "small string one", 16)); |
119 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( | 105 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( |
120 0, "small string two", 16)); | 106 0, "small string two", 16)); |
121 // A string which would push the buffer over the threshold is refused. | 107 // A string which would push the buffer over the threshold is refused. |
122 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData( | 108 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData( |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 } | 236 } |
251 | 237 |
252 // Test a too-large indexed header. | 238 // Test a too-large indexed header. |
253 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { | 239 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { |
254 // High-bit set, and a prefix of one more than the number of static entries. | 240 // High-bit set, and a prefix of one more than the number of static entries. |
255 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbd", 1))); | 241 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbd", 1))); |
256 } | 242 } |
257 | 243 |
258 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) { | 244 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) { |
259 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 245 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
260 context_peer_.header_table().max_size()); | 246 decoder_peer_.header_table().max_size()); |
261 { | 247 { |
262 // Maximum-size update with size 126. Succeeds. | 248 // Maximum-size update with size 126. Succeeds. |
263 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x80\x7e", 2))); | 249 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x80\x7e", 2))); |
264 EXPECT_EQ(126u, context_peer_.header_table().max_size()); | 250 EXPECT_EQ(126u, decoder_peer_.header_table().max_size()); |
265 } | 251 } |
266 string input; | 252 string input; |
267 { | 253 { |
268 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds. | 254 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds. |
269 HpackOutputStream output_stream(kuint32max); | 255 HpackOutputStream output_stream; |
270 output_stream.AppendBits(0x80, 8); // Context update. | 256 output_stream.AppendBits(0x80, 8); // Context update. |
271 output_stream.AppendBits(0x00, 1); // Size update. | 257 output_stream.AppendBits(0x00, 1); // Size update. |
272 output_stream.AppendUint32ForTest(kDefaultHeaderTableSizeSetting); | 258 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting); |
273 | 259 |
274 output_stream.TakeString(&input); | 260 output_stream.TakeString(&input); |
275 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); | 261 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); |
276 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 262 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
277 context_peer_.header_table().max_size()); | 263 decoder_peer_.header_table().max_size()); |
278 } | 264 } |
279 { | 265 { |
280 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails. | 266 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails. |
281 HpackOutputStream output_stream(kuint32max); | 267 HpackOutputStream output_stream; |
282 output_stream.AppendBits(0x80, 8); // Context update. | 268 output_stream.AppendBits(0x80, 8); // Context update. |
283 output_stream.AppendBits(0x00, 1); // Size update. | 269 output_stream.AppendBits(0x00, 1); // Size update. |
284 output_stream.AppendUint32ForTest(kDefaultHeaderTableSizeSetting + 1); | 270 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1); |
285 | 271 |
286 output_stream.TakeString(&input); | 272 output_stream.TakeString(&input); |
287 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input))); | 273 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input))); |
288 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 274 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
289 context_peer_.header_table().max_size()); | 275 decoder_peer_.header_table().max_size()); |
290 } | 276 } |
291 } | 277 } |
292 | 278 |
293 TEST_F(HpackDecoderTest, ContextUpdateClearReferenceSet) { | 279 TEST_F(HpackDecoderTest, ContextUpdateClearReferenceSet) { |
294 // Toggle on a couple of headers. | 280 // Toggle on a couple of headers. |
295 std::map<string, string> header_set1 = | 281 std::map<string, string> header_set1 = |
296 DecodeUniqueHeaderSet("\x82\x86"); | 282 DecodeUniqueHeaderSet("\x82\x86"); |
297 std::map<string, string> expected_header_set1; | 283 std::map<string, string> expected_header_set1; |
298 expected_header_set1[":method"] = "GET"; | 284 expected_header_set1[":method"] = "GET"; |
299 expected_header_set1[":path"] = "/index.html"; | 285 expected_header_set1[":path"] = "/index.html"; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 335 |
350 // Incremental indexing. | 336 // Incremental indexing. |
351 | 337 |
352 // One more than the number of static table entries. | 338 // One more than the number of static table entries. |
353 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x3d", 1))); | 339 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x3d", 1))); |
354 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x00", 1))); | 340 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x00", 1))); |
355 } | 341 } |
356 | 342 |
357 // Round-tripping the header set from E.2.1 should work. | 343 // Round-tripping the header set from E.2.1 should work. |
358 TEST_F(HpackDecoderTest, BasicE21) { | 344 TEST_F(HpackDecoderTest, BasicE21) { |
359 HpackEncoder encoder; | 345 HpackEncoder encoder(ObtainHpackHuffmanTable()); |
360 | 346 |
361 std::map<string, string> expected_header_set; | 347 std::map<string, string> expected_header_set; |
362 expected_header_set[":method"] = "GET"; | 348 expected_header_set[":method"] = "GET"; |
363 expected_header_set[":scheme"] = "http"; | 349 expected_header_set[":scheme"] = "http"; |
364 expected_header_set[":path"] = "/"; | 350 expected_header_set[":path"] = "/"; |
365 expected_header_set[":authority"] = "www.example.com"; | 351 expected_header_set[":authority"] = "www.example.com"; |
366 | 352 |
367 string encoded_header_set; | 353 string encoded_header_set; |
368 EXPECT_TRUE(encoder.EncodeHeaderSet( | 354 EXPECT_TRUE(encoder.EncodeHeaderSet( |
369 expected_header_set, &encoded_header_set)); | 355 expected_header_set, &encoded_header_set)); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 Pair("content-encoding", "gzip"), | 599 Pair("content-encoding", "gzip"), |
614 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), | 600 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), |
615 Pair("location", "https://www.example.com"), | 601 Pair("location", "https://www.example.com"), |
616 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 602 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
617 " max-age=3600; version=1"))); | 603 " max-age=3600; version=1"))); |
618 } | 604 } |
619 | 605 |
620 } // namespace | 606 } // namespace |
621 | 607 |
622 } // namespace net | 608 } // namespace net |
OLD | NEW |