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 |