| 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(kuint32max); |
| 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.AppendUint32ForTest(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(kuint32max); |
| 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.AppendUint32ForTest(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 313 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 |