| 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/hpack_decoder.h" | 5 #include "net/spdy/hpack/hpack_decoder.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | |
| 9 | 8 |
| 10 #include "base/logging.h" | 9 #include "base/logging.h" |
| 11 #include "net/spdy/hpack/hpack_encoder.h" | 10 #include "net/spdy/hpack/hpack_encoder.h" |
| 12 #include "net/spdy/hpack/hpack_input_stream.h" | 11 #include "net/spdy/hpack/hpack_input_stream.h" |
| 13 #include "net/spdy/hpack/hpack_output_stream.h" | 12 #include "net/spdy/hpack/hpack_output_stream.h" |
| 14 #include "net/spdy/spdy_flags.h" | 13 #include "net/spdy/spdy_flags.h" |
| 15 #include "net/spdy/spdy_protocol.h" | 14 #include "net/spdy/spdy_protocol.h" |
| 16 #include "net/spdy/spdy_test_utils.h" | 15 #include "net/spdy/spdy_test_utils.h" |
| 17 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 18 |
| 20 namespace net { | 19 namespace net { |
| 21 namespace test { | 20 namespace test { |
| 22 | 21 |
| 23 using std::string; | |
| 24 | |
| 25 class HpackDecoderPeer { | 22 class HpackDecoderPeer { |
| 26 public: | 23 public: |
| 27 explicit HpackDecoderPeer(HpackDecoder* decoder) : decoder_(decoder) {} | 24 explicit HpackDecoderPeer(HpackDecoder* decoder) : decoder_(decoder) {} |
| 28 | 25 |
| 29 void HandleHeaderRepresentation(SpdyStringPiece name, SpdyStringPiece value) { | 26 void HandleHeaderRepresentation(SpdyStringPiece name, SpdyStringPiece value) { |
| 30 decoder_->HandleHeaderRepresentation(name, value); | 27 decoder_->HandleHeaderRepresentation(name, value); |
| 31 } | 28 } |
| 32 bool DecodeNextName(HpackInputStream* in, SpdyStringPiece* out) { | 29 bool DecodeNextName(HpackInputStream* in, SpdyStringPiece* out) { |
| 33 return decoder_->DecodeNextName(in, out); | 30 return decoder_->DecodeNextName(in, out); |
| 34 } | 31 } |
| 35 HpackHeaderTable* header_table() { return &decoder_->header_table_; } | 32 HpackHeaderTable* header_table() { return &decoder_->header_table_; } |
| 36 | 33 |
| 37 bool DecodeNextStringLiteral(HpackInputStream* in, | 34 bool DecodeNextStringLiteral(HpackInputStream* in, |
| 38 bool is_header_key, | 35 bool is_header_key, |
| 39 SpdyStringPiece* str) { | 36 SpdyStringPiece* str) { |
| 40 return decoder_->DecodeNextStringLiteral(in, is_header_key, str); | 37 return decoder_->DecodeNextStringLiteral(in, is_header_key, str); |
| 41 } | 38 } |
| 42 | 39 |
| 43 const string& headers_block_buffer() const { | 40 const SpdyString& headers_block_buffer() const { |
| 44 return decoder_->headers_block_buffer_; | 41 return decoder_->headers_block_buffer_; |
| 45 } | 42 } |
| 46 | 43 |
| 47 private: | 44 private: |
| 48 HpackDecoder* decoder_; | 45 HpackDecoder* decoder_; |
| 49 }; | 46 }; |
| 50 | 47 |
| 51 namespace { | 48 namespace { |
| 52 | 49 |
| 53 using std::string; | |
| 54 using test::a2b_hex; | 50 using test::a2b_hex; |
| 55 | 51 |
| 56 using testing::ElementsAre; | 52 using testing::ElementsAre; |
| 57 using testing::Pair; | 53 using testing::Pair; |
| 58 | 54 |
| 59 class HpackDecoderTest : public ::testing::TestWithParam<bool> { | 55 class HpackDecoderTest : public ::testing::TestWithParam<bool> { |
| 60 protected: | 56 protected: |
| 61 HpackDecoderTest() : decoder_(), decoder_peer_(&decoder_) {} | 57 HpackDecoderTest() : decoder_(), decoder_peer_(&decoder_) {} |
| 62 | 58 |
| 63 void SetUp() override { handler_exists_ = GetParam(); } | 59 void SetUp() override { handler_exists_ = GetParam(); } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 86 } | 82 } |
| 87 } | 83 } |
| 88 | 84 |
| 89 const SpdyHeaderBlock& DecodeBlockExpectingSuccess(SpdyStringPiece str) { | 85 const SpdyHeaderBlock& DecodeBlockExpectingSuccess(SpdyStringPiece str) { |
| 90 EXPECT_TRUE(DecodeHeaderBlock(str)); | 86 EXPECT_TRUE(DecodeHeaderBlock(str)); |
| 91 return decoded_block(); | 87 return decoded_block(); |
| 92 } | 88 } |
| 93 | 89 |
| 94 void expectEntry(size_t index, | 90 void expectEntry(size_t index, |
| 95 size_t size, | 91 size_t size, |
| 96 const string& name, | 92 const SpdyString& name, |
| 97 const string& value) { | 93 const SpdyString& value) { |
| 98 const HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index); | 94 const HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index); |
| 99 EXPECT_EQ(name, entry->name()) << "index " << index; | 95 EXPECT_EQ(name, entry->name()) << "index " << index; |
| 100 EXPECT_EQ(value, entry->value()); | 96 EXPECT_EQ(value, entry->value()); |
| 101 EXPECT_EQ(size, entry->Size()); | 97 EXPECT_EQ(size, entry->Size()); |
| 102 EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry)); | 98 EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry)); |
| 103 } | 99 } |
| 104 | 100 |
| 105 HpackDecoder decoder_; | 101 HpackDecoder decoder_; |
| 106 test::HpackDecoderPeer decoder_peer_; | 102 test::HpackDecoderPeer decoder_peer_; |
| 107 TestHeadersHandler handler_; | 103 TestHeadersHandler handler_; |
| 108 bool handler_exists_; | 104 bool handler_exists_; |
| 109 }; | 105 }; |
| 110 | 106 |
| 111 INSTANTIATE_TEST_CASE_P(WithAndWithoutHeadersHandler, | 107 INSTANTIATE_TEST_CASE_P(WithAndWithoutHeadersHandler, |
| 112 HpackDecoderTest, | 108 HpackDecoderTest, |
| 113 ::testing::Bool()); | 109 ::testing::Bool()); |
| 114 | 110 |
| 115 TEST_P(HpackDecoderTest, AddHeaderDataWithHandleControlFrameHeadersData) { | 111 TEST_P(HpackDecoderTest, AddHeaderDataWithHandleControlFrameHeadersData) { |
| 116 // The hpack decode buffer size is limited in size. This test verifies that | 112 // The hpack decode buffer size is limited in size. This test verifies that |
| 117 // adding encoded data under that limit is accepted, and data that exceeds the | 113 // adding encoded data under that limit is accepted, and data that exceeds the |
| 118 // limit is rejected. | 114 // limit is rejected. |
| 119 const size_t kMaxBufferSizeBytes = 50; | 115 const size_t kMaxBufferSizeBytes = 50; |
| 120 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); | 116 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); |
| 121 | 117 |
| 122 // Strings under threshold are concatenated in the buffer. | 118 // Strings under threshold are concatenated in the buffer. |
| 123 string first_input; | 119 SpdyString first_input; |
| 124 first_input.push_back(0x00); // Literal name and value, unindexed | 120 first_input.push_back(0x00); // Literal name and value, unindexed |
| 125 first_input.push_back(0x7f); // Name length = 127 | 121 first_input.push_back(0x7f); // Name length = 127 |
| 126 ASSERT_EQ(2u, first_input.size()); | 122 ASSERT_EQ(2u, first_input.size()); |
| 127 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(first_input.data(), | 123 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(first_input.data(), |
| 128 first_input.size())); | 124 first_input.size())); |
| 129 // Further 38 bytes to make 40 total buffered bytes. | 125 // Further 38 bytes to make 40 total buffered bytes. |
| 130 string second_input = string(38, 'x'); | 126 SpdyString second_input = SpdyString(38, 'x'); |
| 131 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(second_input.data(), | 127 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(second_input.data(), |
| 132 second_input.size())); | 128 second_input.size())); |
| 133 // A string which would push the buffer over the threshold is refused. | 129 // A string which would push the buffer over the threshold is refused. |
| 134 const int kThirdInputSize = | 130 const int kThirdInputSize = |
| 135 kMaxBufferSizeBytes - (first_input.size() + second_input.size()) + 1; | 131 kMaxBufferSizeBytes - (first_input.size() + second_input.size()) + 1; |
| 136 string third_input = string(kThirdInputSize, 'y'); | 132 SpdyString third_input = SpdyString(kThirdInputSize, 'y'); |
| 137 ASSERT_GT(first_input.size() + second_input.size() + third_input.size(), | 133 ASSERT_GT(first_input.size() + second_input.size() + third_input.size(), |
| 138 kMaxBufferSizeBytes); | 134 kMaxBufferSizeBytes); |
| 139 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(third_input.data(), | 135 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(third_input.data(), |
| 140 third_input.size())); | 136 third_input.size())); |
| 141 | 137 |
| 142 string expected(first_input); | 138 SpdyString expected(first_input); |
| 143 expected.append(second_input); | 139 expected.append(second_input); |
| 144 EXPECT_EQ(expected, decoder_peer_.headers_block_buffer()); | 140 EXPECT_EQ(expected, decoder_peer_.headers_block_buffer()); |
| 145 } | 141 } |
| 146 | 142 |
| 147 // Decode with incomplete data in buffer. | 143 // Decode with incomplete data in buffer. |
| 148 TEST_P(HpackDecoderTest, DecodeWithIncompleteData) { | 144 TEST_P(HpackDecoderTest, DecodeWithIncompleteData) { |
| 149 // No need to wait for more data. | 145 // No need to wait for more data. |
| 150 EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82")); | 146 EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82")); |
| 151 EXPECT_EQ("", decoder_peer_.headers_block_buffer()); | 147 EXPECT_EQ("", decoder_peer_.headers_block_buffer()); |
| 152 | 148 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 170 decoder_.HandleControlFrameHeadersStart(&handler_); | 166 decoder_.HandleControlFrameHeadersStart(&handler_); |
| 171 } | 167 } |
| 172 | 168 |
| 173 // All cookie crumbs are joined. | 169 // All cookie crumbs are joined. |
| 174 decoder_peer_.HandleHeaderRepresentation("cookie", " part 1"); | 170 decoder_peer_.HandleHeaderRepresentation("cookie", " part 1"); |
| 175 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 "); | 171 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 "); |
| 176 decoder_peer_.HandleHeaderRepresentation("cookie", "part3"); | 172 decoder_peer_.HandleHeaderRepresentation("cookie", "part3"); |
| 177 | 173 |
| 178 // Already-delimited headers are passed through. | 174 // Already-delimited headers are passed through. |
| 179 decoder_peer_.HandleHeaderRepresentation("passed-through", | 175 decoder_peer_.HandleHeaderRepresentation("passed-through", |
| 180 string("foo\0baz", 7)); | 176 SpdyString("foo\0baz", 7)); |
| 181 | 177 |
| 182 // Other headers are joined on \0. Case matters. | 178 // Other headers are joined on \0. Case matters. |
| 183 decoder_peer_.HandleHeaderRepresentation("joined", "not joined"); | 179 decoder_peer_.HandleHeaderRepresentation("joined", "not joined"); |
| 184 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1"); | 180 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1"); |
| 185 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2"); | 181 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2"); |
| 186 | 182 |
| 187 // Empty headers remain empty. | 183 // Empty headers remain empty. |
| 188 decoder_peer_.HandleHeaderRepresentation("empty", ""); | 184 decoder_peer_.HandleHeaderRepresentation("empty", ""); |
| 189 | 185 |
| 190 // Joined empty headers work as expected. | 186 // Joined empty headers work as expected. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 input_stream.MarkCurrentPosition(); | 229 input_stream.MarkCurrentPosition(); |
| 234 EXPECT_EQ(6u, input_stream.ParsedBytes()); | 230 EXPECT_EQ(6u, input_stream.ParsedBytes()); |
| 235 | 231 |
| 236 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 232 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| 237 EXPECT_TRUE(input_stream.NeedMoreData()); | 233 EXPECT_TRUE(input_stream.NeedMoreData()); |
| 238 input_stream.MarkCurrentPosition(); | 234 input_stream.MarkCurrentPosition(); |
| 239 EXPECT_EQ(8u, input_stream.ParsedBytes()); | 235 EXPECT_EQ(8u, input_stream.ParsedBytes()); |
| 240 } | 236 } |
| 241 | 237 |
| 242 TEST_P(HpackDecoderTest, DecodeNextNameLiteralWithHuffmanEncoding) { | 238 TEST_P(HpackDecoderTest, DecodeNextNameLiteralWithHuffmanEncoding) { |
| 243 string input = a2b_hex("008825a849e95ba97d7f"); | 239 SpdyString input = a2b_hex("008825a849e95ba97d7f"); |
| 244 HpackInputStream input_stream(input); | 240 HpackInputStream input_stream(input); |
| 245 | 241 |
| 246 SpdyStringPiece string_piece; | 242 SpdyStringPiece string_piece; |
| 247 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 243 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| 248 EXPECT_EQ("custom-key", string_piece); | 244 EXPECT_EQ("custom-key", string_piece); |
| 249 EXPECT_FALSE(input_stream.HasMoreData()); | 245 EXPECT_FALSE(input_stream.HasMoreData()); |
| 250 EXPECT_FALSE(input_stream.NeedMoreData()); | 246 EXPECT_FALSE(input_stream.NeedMoreData()); |
| 251 input_stream.MarkCurrentPosition(); | 247 input_stream.MarkCurrentPosition(); |
| 252 EXPECT_EQ(input.size(), input_stream.ParsedBytes()); | 248 EXPECT_EQ(input.size(), input_stream.ParsedBytes()); |
| 253 } | 249 } |
| 254 | 250 |
| 255 // Decode with incomplete huffman encoding. | 251 // Decode with incomplete huffman encoding. |
| 256 TEST_P(HpackDecoderTest, DecodeNextNameLiteralWithIncompleteHuffmanEncoding) { | 252 TEST_P(HpackDecoderTest, DecodeNextNameLiteralWithIncompleteHuffmanEncoding) { |
| 257 // CHECK(huffman_table_.Initialize(kHpackHuffmanCode, | 253 // CHECK(huffman_table_.Initialize(kHpackHuffmanCode, |
| 258 // arraysize(kHpackHuffmanCode))); | 254 // arraysize(kHpackHuffmanCode))); |
| 259 // Put two copies of the same huffman encoding into input. | 255 // Put two copies of the same huffman encoding into input. |
| 260 string input = a2b_hex("008825a849e95ba97d7f008825a849e95ba97d7f"); | 256 SpdyString input = a2b_hex("008825a849e95ba97d7f008825a849e95ba97d7f"); |
| 261 input.resize(input.size() - 1); // Remove the last byte. | 257 input.resize(input.size() - 1); // Remove the last byte. |
| 262 HpackInputStream input_stream(input); | 258 HpackInputStream input_stream(input); |
| 263 | 259 |
| 264 SpdyStringPiece string_piece; | 260 SpdyStringPiece string_piece; |
| 265 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 261 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| 266 EXPECT_FALSE(input_stream.NeedMoreData()); | 262 EXPECT_FALSE(input_stream.NeedMoreData()); |
| 267 input_stream.MarkCurrentPosition(); | 263 input_stream.MarkCurrentPosition(); |
| 268 EXPECT_EQ(10u, input_stream.ParsedBytes()); | 264 EXPECT_EQ(10u, input_stream.ParsedBytes()); |
| 269 | 265 |
| 270 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 266 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 341 |
| 346 // Test a too-large indexed header. | 342 // Test a too-large indexed header. |
| 347 TEST_P(HpackDecoderTest, InvalidIndexedHeader) { | 343 TEST_P(HpackDecoderTest, InvalidIndexedHeader) { |
| 348 // High-bit set, and a prefix of one more than the number of static entries. | 344 // High-bit set, and a prefix of one more than the number of static entries. |
| 349 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece("\xbe", 1))); | 345 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece("\xbe", 1))); |
| 350 } | 346 } |
| 351 | 347 |
| 352 TEST_P(HpackDecoderTest, ContextUpdateMaximumSize) { | 348 TEST_P(HpackDecoderTest, ContextUpdateMaximumSize) { |
| 353 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 349 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 354 decoder_peer_.header_table()->max_size()); | 350 decoder_peer_.header_table()->max_size()); |
| 355 string input; | 351 SpdyString input; |
| 356 { | 352 { |
| 357 // Maximum-size update with size 126. Succeeds. | 353 // Maximum-size update with size 126. Succeeds. |
| 358 HpackOutputStream output_stream; | 354 HpackOutputStream output_stream; |
| 359 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 355 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 360 output_stream.AppendUint32(126); | 356 output_stream.AppendUint32(126); |
| 361 | 357 |
| 362 output_stream.TakeString(&input); | 358 output_stream.TakeString(&input); |
| 363 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); | 359 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 364 EXPECT_EQ(126u, decoder_peer_.header_table()->max_size()); | 360 EXPECT_EQ(126u, decoder_peer_.header_table()->max_size()); |
| 365 } | 361 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 382 | 378 |
| 383 output_stream.TakeString(&input); | 379 output_stream.TakeString(&input); |
| 384 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 380 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 385 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 381 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 386 decoder_peer_.header_table()->max_size()); | 382 decoder_peer_.header_table()->max_size()); |
| 387 } | 383 } |
| 388 } | 384 } |
| 389 | 385 |
| 390 // Two HeaderTableSizeUpdates may appear at the beginning of the block | 386 // Two HeaderTableSizeUpdates may appear at the beginning of the block |
| 391 TEST_P(HpackDecoderTest, TwoTableSizeUpdates) { | 387 TEST_P(HpackDecoderTest, TwoTableSizeUpdates) { |
| 392 string input; | 388 SpdyString input; |
| 393 { | 389 { |
| 394 // Should accept two table size updates, update to second one | 390 // Should accept two table size updates, update to second one |
| 395 HpackOutputStream output_stream; | 391 HpackOutputStream output_stream; |
| 396 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 392 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 397 output_stream.AppendUint32(0); | 393 output_stream.AppendUint32(0); |
| 398 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 394 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 399 output_stream.AppendUint32(122); | 395 output_stream.AppendUint32(122); |
| 400 | 396 |
| 401 output_stream.TakeString(&input); | 397 output_stream.TakeString(&input); |
| 402 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); | 398 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 403 EXPECT_EQ(122u, decoder_peer_.header_table()->max_size()); | 399 EXPECT_EQ(122u, decoder_peer_.header_table()->max_size()); |
| 404 } | 400 } |
| 405 } | 401 } |
| 406 | 402 |
| 407 // Three HeaderTableSizeUpdates should result in an error | 403 // Three HeaderTableSizeUpdates should result in an error |
| 408 TEST_P(HpackDecoderTest, ThreeTableSizeUpdatesError) { | 404 TEST_P(HpackDecoderTest, ThreeTableSizeUpdatesError) { |
| 409 string input; | 405 SpdyString input; |
| 410 { | 406 { |
| 411 // Should reject three table size updates, update to second one | 407 // Should reject three table size updates, update to second one |
| 412 HpackOutputStream output_stream; | 408 HpackOutputStream output_stream; |
| 413 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 409 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 414 output_stream.AppendUint32(5); | 410 output_stream.AppendUint32(5); |
| 415 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 411 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 416 output_stream.AppendUint32(10); | 412 output_stream.AppendUint32(10); |
| 417 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 413 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 418 output_stream.AppendUint32(15); | 414 output_stream.AppendUint32(15); |
| 419 | 415 |
| 420 output_stream.TakeString(&input); | 416 output_stream.TakeString(&input); |
| 421 | 417 |
| 422 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 418 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 423 EXPECT_EQ(10u, decoder_peer_.header_table()->max_size()); | 419 EXPECT_EQ(10u, decoder_peer_.header_table()->max_size()); |
| 424 } | 420 } |
| 425 } | 421 } |
| 426 | 422 |
| 427 // HeaderTableSizeUpdates may only appear at the beginning of the block | 423 // HeaderTableSizeUpdates may only appear at the beginning of the block |
| 428 // Any other updates should result in an error | 424 // Any other updates should result in an error |
| 429 TEST_P(HpackDecoderTest, TableSizeUpdateSecondError) { | 425 TEST_P(HpackDecoderTest, TableSizeUpdateSecondError) { |
| 430 string input; | 426 SpdyString input; |
| 431 { | 427 { |
| 432 // Should reject a table size update appearing after a different entry | 428 // Should reject a table size update appearing after a different entry |
| 433 // The table size should remain as the default | 429 // The table size should remain as the default |
| 434 HpackOutputStream output_stream; | 430 HpackOutputStream output_stream; |
| 435 output_stream.AppendBytes("\x82\x85"); | 431 output_stream.AppendBytes("\x82\x85"); |
| 436 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 432 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 437 output_stream.AppendUint32(123); | 433 output_stream.AppendUint32(123); |
| 438 | 434 |
| 439 output_stream.TakeString(&input); | 435 output_stream.TakeString(&input); |
| 440 | 436 |
| 441 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 437 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 442 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 438 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 443 decoder_peer_.header_table()->max_size()); | 439 decoder_peer_.header_table()->max_size()); |
| 444 } | 440 } |
| 445 } | 441 } |
| 446 | 442 |
| 447 // HeaderTableSizeUpdates may only appear at the beginning of the block | 443 // HeaderTableSizeUpdates may only appear at the beginning of the block |
| 448 // Any other updates should result in an error | 444 // Any other updates should result in an error |
| 449 TEST_P(HpackDecoderTest, TableSizeUpdateFirstThirdError) { | 445 TEST_P(HpackDecoderTest, TableSizeUpdateFirstThirdError) { |
| 450 string input; | 446 SpdyString input; |
| 451 { | 447 { |
| 452 // Should reject the second table size update | 448 // Should reject the second table size update |
| 453 // if a different entry appears after the first update | 449 // if a different entry appears after the first update |
| 454 // The table size should update to the first but not the second | 450 // The table size should update to the first but not the second |
| 455 HpackOutputStream output_stream; | 451 HpackOutputStream output_stream; |
| 456 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 452 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 457 output_stream.AppendUint32(60); | 453 output_stream.AppendUint32(60); |
| 458 output_stream.AppendBytes("\x82\x85"); | 454 output_stream.AppendBytes("\x82\x85"); |
| 459 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 455 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 460 output_stream.AppendUint32(125); | 456 output_stream.AppendUint32(125); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 | 541 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 |
| 546 TEST_P(HpackDecoderTest, BasicC31) { | 542 TEST_P(HpackDecoderTest, BasicC31) { |
| 547 HpackEncoder encoder(ObtainHpackHuffmanTable()); | 543 HpackEncoder encoder(ObtainHpackHuffmanTable()); |
| 548 | 544 |
| 549 SpdyHeaderBlock expected_header_set; | 545 SpdyHeaderBlock expected_header_set; |
| 550 expected_header_set[":method"] = "GET"; | 546 expected_header_set[":method"] = "GET"; |
| 551 expected_header_set[":scheme"] = "http"; | 547 expected_header_set[":scheme"] = "http"; |
| 552 expected_header_set[":path"] = "/"; | 548 expected_header_set[":path"] = "/"; |
| 553 expected_header_set[":authority"] = "www.example.com"; | 549 expected_header_set[":authority"] = "www.example.com"; |
| 554 | 550 |
| 555 string encoded_header_set; | 551 SpdyString encoded_header_set; |
| 556 EXPECT_TRUE( | 552 EXPECT_TRUE( |
| 557 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); | 553 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); |
| 558 | 554 |
| 559 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); | 555 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); |
| 560 EXPECT_EQ(expected_header_set, decoded_block()); | 556 EXPECT_EQ(expected_header_set, decoded_block()); |
| 561 } | 557 } |
| 562 | 558 |
| 563 // RFC 7541, Section C.4: Request Examples with Huffman Coding | 559 // RFC 7541, Section C.4: Request Examples with Huffman Coding |
| 564 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 | 560 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 |
| 565 TEST_P(HpackDecoderTest, SectionC4RequestHuffmanExamples) { | 561 TEST_P(HpackDecoderTest, SectionC4RequestHuffmanExamples) { |
| 566 // 82 | == Indexed - Add == | 562 // 82 | == Indexed - Add == |
| 567 // | idx = 2 | 563 // | idx = 2 |
| 568 // | -> :method: GET | 564 // | -> :method: GET |
| 569 // 86 | == Indexed - Add == | 565 // 86 | == Indexed - Add == |
| 570 // | idx = 6 | 566 // | idx = 6 |
| 571 // | -> :scheme: http | 567 // | -> :scheme: http |
| 572 // 84 | == Indexed - Add == | 568 // 84 | == Indexed - Add == |
| 573 // | idx = 4 | 569 // | idx = 4 |
| 574 // | -> :path: / | 570 // | -> :path: / |
| 575 // 41 | == Literal indexed == | 571 // 41 | == Literal indexed == |
| 576 // | Indexed name (idx = 1) | 572 // | Indexed name (idx = 1) |
| 577 // | :authority | 573 // | :authority |
| 578 // 8c | Literal value (len = 15) | 574 // 8c | Literal value (len = 15) |
| 579 // | Huffman encoded: | 575 // | Huffman encoded: |
| 580 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... | 576 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... |
| 581 // | Decoded: | 577 // | Decoded: |
| 582 // | www.example.com | 578 // | www.example.com |
| 583 // | -> :authority: www.example.com | 579 // | -> :authority: www.example.com |
| 584 string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff"); | 580 SpdyString first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff"); |
| 585 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); | 581 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); |
| 586 | 582 |
| 587 EXPECT_THAT( | 583 EXPECT_THAT( |
| 588 first_header_set, | 584 first_header_set, |
| 589 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "http"), | 585 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "http"), |
| 590 Pair(":path", "/"), Pair(":authority", "www.example.com"))); | 586 Pair(":path", "/"), Pair(":authority", "www.example.com"))); |
| 591 | 587 |
| 592 expectEntry(62, 57, ":authority", "www.example.com"); | 588 expectEntry(62, 57, ":authority", "www.example.com"); |
| 593 EXPECT_EQ(57u, decoder_peer_.header_table()->size()); | 589 EXPECT_EQ(57u, decoder_peer_.header_table()->size()); |
| 594 | 590 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 607 // 58 | == Literal indexed == | 603 // 58 | == Literal indexed == |
| 608 // | Indexed name (idx = 24) | 604 // | Indexed name (idx = 24) |
| 609 // | cache-control | 605 // | cache-control |
| 610 // 86 | Literal value (len = 8) | 606 // 86 | Literal value (len = 8) |
| 611 // | Huffman encoded: | 607 // | Huffman encoded: |
| 612 // a8eb 1064 9cbf | ...d.. | 608 // a8eb 1064 9cbf | ...d.. |
| 613 // | Decoded: | 609 // | Decoded: |
| 614 // | no-cache | 610 // | no-cache |
| 615 // | -> cache-control: no-cache | 611 // | -> cache-control: no-cache |
| 616 | 612 |
| 617 string second = a2b_hex("828684be5886a8eb10649cbf"); | 613 SpdyString second = a2b_hex("828684be5886a8eb10649cbf"); |
| 618 const SpdyHeaderBlock& second_header_set = | 614 const SpdyHeaderBlock& second_header_set = |
| 619 DecodeBlockExpectingSuccess(second); | 615 DecodeBlockExpectingSuccess(second); |
| 620 | 616 |
| 621 EXPECT_THAT( | 617 EXPECT_THAT( |
| 622 second_header_set, | 618 second_header_set, |
| 623 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "http"), | 619 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "http"), |
| 624 Pair(":path", "/"), Pair(":authority", "www.example.com"), | 620 Pair(":path", "/"), Pair(":authority", "www.example.com"), |
| 625 Pair("cache-control", "no-cache"))); | 621 Pair("cache-control", "no-cache"))); |
| 626 | 622 |
| 627 expectEntry(62, 53, "cache-control", "no-cache"); | 623 expectEntry(62, 53, "cache-control", "no-cache"); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 645 // | Huffman encoded: | 641 // | Huffman encoded: |
| 646 // 25a8 49e9 5ba9 7d7f | %.I.[.}. | 642 // 25a8 49e9 5ba9 7d7f | %.I.[.}. |
| 647 // | Decoded: | 643 // | Decoded: |
| 648 // | custom-key | 644 // | custom-key |
| 649 // 89 | Literal value (len = 12) | 645 // 89 | Literal value (len = 12) |
| 650 // | Huffman encoded: | 646 // | Huffman encoded: |
| 651 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... | 647 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... |
| 652 // | Decoded: | 648 // | Decoded: |
| 653 // | custom-value | 649 // | custom-value |
| 654 // | -> custom-key: custom-value | 650 // | -> custom-key: custom-value |
| 655 string third = a2b_hex( | 651 SpdyString third = a2b_hex( |
| 656 "828785bf408825a849e95ba97d7f89" | 652 "828785bf408825a849e95ba97d7f89" |
| 657 "25a849e95bb8e8b4bf"); | 653 "25a849e95bb8e8b4bf"); |
| 658 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); | 654 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); |
| 659 | 655 |
| 660 EXPECT_THAT(third_header_set, | 656 EXPECT_THAT(third_header_set, |
| 661 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "https"), | 657 ElementsAre(Pair(":method", "GET"), Pair(":scheme", "https"), |
| 662 Pair(":path", "/index.html"), | 658 Pair(":path", "/index.html"), |
| 663 Pair(":authority", "www.example.com"), | 659 Pair(":authority", "www.example.com"), |
| 664 Pair("custom-key", "custom-value"))); | 660 Pair("custom-key", "custom-value"))); |
| 665 | 661 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 // | location | 705 // | location |
| 710 // 91 | Literal value (len = 23) | 706 // 91 | Literal value (len = 23) |
| 711 // | Huffman encoded: | 707 // | Huffman encoded: |
| 712 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C | 708 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C |
| 713 // d3 | . | 709 // d3 | . |
| 714 // | Decoded: | 710 // | Decoded: |
| 715 // | https://www.example.com | 711 // | https://www.example.com |
| 716 // | -> location: https://www.e | 712 // | -> location: https://www.e |
| 717 // | xample.com | 713 // | xample.com |
| 718 | 714 |
| 719 string first = a2b_hex( | 715 SpdyString first = a2b_hex( |
| 720 "488264025885aec3771a4b6196d07abe" | 716 "488264025885aec3771a4b6196d07abe" |
| 721 "941054d444a8200595040b8166e082a6" | 717 "941054d444a8200595040b8166e082a6" |
| 722 "2d1bff6e919d29ad171863c78f0b97c8" | 718 "2d1bff6e919d29ad171863c78f0b97c8" |
| 723 "e9ae82ae43d3"); | 719 "e9ae82ae43d3"); |
| 724 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); | 720 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); |
| 725 | 721 |
| 726 EXPECT_THAT( | 722 EXPECT_THAT( |
| 727 first_header_set, | 723 first_header_set, |
| 728 ElementsAre(Pair(":status", "302"), Pair("cache-control", "private"), | 724 ElementsAre(Pair(":status", "302"), Pair("cache-control", "private"), |
| 729 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), | 725 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 749 // | idx = 65 | 745 // | idx = 65 |
| 750 // | -> cache-control: private | 746 // | -> cache-control: private |
| 751 // c0 | == Indexed - Add == | 747 // c0 | == Indexed - Add == |
| 752 // | idx = 64 | 748 // | idx = 64 |
| 753 // | -> date: Mon, 21 Oct 2013 | 749 // | -> date: Mon, 21 Oct 2013 |
| 754 // | 20:13:21 GMT | 750 // | 20:13:21 GMT |
| 755 // bf | == Indexed - Add == | 751 // bf | == Indexed - Add == |
| 756 // | idx = 63 | 752 // | idx = 63 |
| 757 // | -> location: | 753 // | -> location: |
| 758 // | https://www.example.com | 754 // | https://www.example.com |
| 759 string second = a2b_hex("4883640effc1c0bf"); | 755 SpdyString second = a2b_hex("4883640effc1c0bf"); |
| 760 const SpdyHeaderBlock& second_header_set = | 756 const SpdyHeaderBlock& second_header_set = |
| 761 DecodeBlockExpectingSuccess(second); | 757 DecodeBlockExpectingSuccess(second); |
| 762 | 758 |
| 763 EXPECT_THAT( | 759 EXPECT_THAT( |
| 764 second_header_set, | 760 second_header_set, |
| 765 ElementsAre(Pair(":status", "307"), Pair("cache-control", "private"), | 761 ElementsAre(Pair(":status", "307"), Pair("cache-control", "private"), |
| 766 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), | 762 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), |
| 767 Pair("location", "https://www.example.com"))); | 763 Pair("location", "https://www.example.com"))); |
| 768 | 764 |
| 769 expectEntry(62, 42, ":status", "307"); | 765 expectEntry(62, 42, ":status", "307"); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 // | Decoded: | 814 // | Decoded: |
| 819 // | foo=ASDJKHQKBZXOQWEOPIUAXQ | 815 // | foo=ASDJKHQKBZXOQWEOPIUAXQ |
| 820 // | WEOIU; max-age=3600; versi | 816 // | WEOIU; max-age=3600; versi |
| 821 // | on=1 | 817 // | on=1 |
| 822 // | - evict: location: | 818 // | - evict: location: |
| 823 // | https://www.example.com | 819 // | https://www.example.com |
| 824 // | - evict: :status: 307 | 820 // | - evict: :status: 307 |
| 825 // | -> set-cookie: foo=ASDJKHQ | 821 // | -> set-cookie: foo=ASDJKHQ |
| 826 // | KBZXOQWEOPIUAXQWEOIU; | 822 // | KBZXOQWEOPIUAXQWEOIU; |
| 827 // | max-age=3600; version=1 | 823 // | max-age=3600; version=1 |
| 828 string third = a2b_hex( | 824 SpdyString third = a2b_hex( |
| 829 "88c16196d07abe941054d444a8200595" | 825 "88c16196d07abe941054d444a8200595" |
| 830 "040b8166e084a62d1bffc05a839bd9ab" | 826 "040b8166e084a62d1bffc05a839bd9ab" |
| 831 "77ad94e7821dd7f2e6c7b335dfdfcd5b" | 827 "77ad94e7821dd7f2e6c7b335dfdfcd5b" |
| 832 "3960d5af27087f3672c1ab270fb5291f" | 828 "3960d5af27087f3672c1ab270fb5291f" |
| 833 "9587316065c003ed4ee5b1063d5007"); | 829 "9587316065c003ed4ee5b1063d5007"); |
| 834 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); | 830 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); |
| 835 | 831 |
| 836 EXPECT_THAT( | 832 EXPECT_THAT( |
| 837 third_header_set, | 833 third_header_set, |
| 838 ElementsAre(Pair(":status", "200"), Pair("cache-control", "private"), | 834 ElementsAre(Pair(":status", "200"), Pair("cache-control", "private"), |
| 839 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), | 835 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), |
| 840 Pair("location", "https://www.example.com"), | 836 Pair("location", "https://www.example.com"), |
| 841 Pair("content-encoding", "gzip"), | 837 Pair("content-encoding", "gzip"), |
| 842 Pair("set-cookie", | 838 Pair("set-cookie", |
| 843 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 839 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
| 844 " max-age=3600; version=1"))); | 840 " max-age=3600; version=1"))); |
| 845 | 841 |
| 846 expectEntry(62, 98, "set-cookie", | 842 expectEntry(62, 98, "set-cookie", |
| 847 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 843 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
| 848 " max-age=3600; version=1"); | 844 " max-age=3600; version=1"); |
| 849 expectEntry(63, 52, "content-encoding", "gzip"); | 845 expectEntry(63, 52, "content-encoding", "gzip"); |
| 850 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); | 846 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); |
| 851 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); | 847 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); |
| 852 } | 848 } |
| 853 | 849 |
| 854 } // namespace | 850 } // namespace |
| 855 } // namespace test | 851 } // namespace test |
| 856 } // namespace net | 852 } // namespace net |
| OLD | NEW |