| 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> | 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/hpack_encoder.h" | 13 #include "net/spdy/hpack/hpack_encoder.h" |
| 14 #include "net/spdy/hpack/hpack_input_stream.h" | 14 #include "net/spdy/hpack/hpack_input_stream.h" |
| 15 #include "net/spdy/hpack/hpack_output_stream.h" | 15 #include "net/spdy/hpack/hpack_output_stream.h" |
| 16 #include "net/spdy/spdy_test_utils.h" | 16 #include "net/spdy/spdy_test_utils.h" |
| 17 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 19 |
| 20 namespace net { | 20 namespace net { |
| 21 | |
| 22 namespace test { | 21 namespace test { |
| 23 | 22 |
| 24 using base::StringPiece; | 23 using base::StringPiece; |
| 25 using std::string; | 24 using std::string; |
| 26 | 25 |
| 27 class HpackDecoderPeer { | 26 class HpackDecoderPeer { |
| 28 public: | 27 public: |
| 29 explicit HpackDecoderPeer(HpackDecoder* decoder) : decoder_(decoder) {} | 28 explicit HpackDecoderPeer(HpackDecoder* decoder) : decoder_(decoder) {} |
| 30 | 29 |
| 31 void HandleHeaderRepresentation(StringPiece name, StringPiece value) { | 30 void HandleHeaderRepresentation(StringPiece name, StringPiece value) { |
| 32 decoder_->HandleHeaderRepresentation(name, value); | 31 decoder_->HandleHeaderRepresentation(name, value); |
| 33 } | 32 } |
| 34 bool DecodeNextName(HpackInputStream* in, StringPiece* out) { | 33 bool DecodeNextName(HpackInputStream* in, StringPiece* out) { |
| 35 return decoder_->DecodeNextName(in, out); | 34 return decoder_->DecodeNextName(in, out); |
| 36 } | 35 } |
| 37 HpackHeaderTable* header_table() { return &decoder_->header_table_; } | 36 HpackHeaderTable* header_table() { return &decoder_->header_table_; } |
| 38 void set_cookie_value(string value) { decoder_->cookie_value_ = value; } | 37 void set_cookie_value(string value) { decoder_->cookie_value_ = value; } |
| 39 string cookie_value() { return decoder_->cookie_value_; } | 38 string cookie_value() { return decoder_->cookie_value_; } |
| 40 const SpdyHeaderBlock& decoded_block() const { | 39 const SpdyHeaderBlock& decoded_block() const { |
| 41 return decoder_->decoded_block_; | 40 return decoder_->decoded_block_; |
| 42 } | 41 } |
| 43 const string& headers_block_buffer() const { | 42 const string& headers_block_buffer() const { |
| 44 return decoder_->headers_block_buffer_; | 43 return decoder_->headers_block_buffer_; |
| 45 } | 44 } |
| 46 | 45 |
| 47 private: | 46 private: |
| 48 HpackDecoder* decoder_; | 47 HpackDecoder* decoder_; |
| 49 }; | 48 }; |
| 50 | 49 |
| 51 } // namespace test | |
| 52 | |
| 53 namespace { | 50 namespace { |
| 54 | 51 |
| 55 using base::StringPiece; | 52 using base::StringPiece; |
| 56 using std::string; | 53 using std::string; |
| 57 using test::a2b_hex; | 54 using test::a2b_hex; |
| 58 | 55 |
| 59 using testing::ElementsAre; | 56 using testing::ElementsAre; |
| 60 using testing::Pair; | 57 using testing::Pair; |
| 61 | 58 |
| 62 const size_t kLiteralBound = 1024; | 59 const size_t kLiteralBound = 1024; |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 199 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| 203 } | 200 } |
| 204 | 201 |
| 205 // Decoding indexed static table field should work. | 202 // Decoding indexed static table field should work. |
| 206 TEST_F(HpackDecoderTest, IndexedHeaderStatic) { | 203 TEST_F(HpackDecoderTest, IndexedHeaderStatic) { |
| 207 // Reference static table entries #2 and #5. | 204 // Reference static table entries #2 and #5. |
| 208 SpdyHeaderBlock header_set1 = DecodeBlockExpectingSuccess("\x82\x85"); | 205 SpdyHeaderBlock header_set1 = DecodeBlockExpectingSuccess("\x82\x85"); |
| 209 SpdyHeaderBlock expected_header_set1; | 206 SpdyHeaderBlock expected_header_set1; |
| 210 expected_header_set1[":method"] = "GET"; | 207 expected_header_set1[":method"] = "GET"; |
| 211 expected_header_set1[":path"] = "/index.html"; | 208 expected_header_set1[":path"] = "/index.html"; |
| 212 EXPECT_EQ(expected_header_set1, header_set1); | 209 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set1, header_set1)); |
| 213 | 210 |
| 214 // Reference static table entry #2. | 211 // Reference static table entry #2. |
| 215 SpdyHeaderBlock header_set2 = DecodeBlockExpectingSuccess("\x82"); | 212 SpdyHeaderBlock header_set2 = DecodeBlockExpectingSuccess("\x82"); |
| 216 SpdyHeaderBlock expected_header_set2; | 213 SpdyHeaderBlock expected_header_set2; |
| 217 expected_header_set2[":method"] = "GET"; | 214 expected_header_set2[":method"] = "GET"; |
| 218 EXPECT_EQ(expected_header_set2, header_set2); | 215 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set2, header_set2)); |
| 219 } | 216 } |
| 220 | 217 |
| 221 TEST_F(HpackDecoderTest, IndexedHeaderDynamic) { | 218 TEST_F(HpackDecoderTest, IndexedHeaderDynamic) { |
| 222 // First header block: add an entry to header table. | 219 // First header block: add an entry to header table. |
| 223 SpdyHeaderBlock header_set1 = DecodeBlockExpectingSuccess( | 220 SpdyHeaderBlock header_set1 = DecodeBlockExpectingSuccess( |
| 224 "\x40\x03" | 221 "\x40\x03" |
| 225 "foo" | 222 "foo" |
| 226 "\x03" | 223 "\x03" |
| 227 "bar"); | 224 "bar"); |
| 228 SpdyHeaderBlock expected_header_set1; | 225 SpdyHeaderBlock expected_header_set1; |
| 229 expected_header_set1["foo"] = "bar"; | 226 expected_header_set1["foo"] = "bar"; |
| 230 EXPECT_EQ(expected_header_set1, header_set1); | 227 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set1, header_set1)); |
| 231 | 228 |
| 232 // Second header block: add another entry to header table. | 229 // Second header block: add another entry to header table. |
| 233 SpdyHeaderBlock header_set2 = DecodeBlockExpectingSuccess( | 230 SpdyHeaderBlock header_set2 = DecodeBlockExpectingSuccess( |
| 234 "\xbe\x40\x04" | 231 "\xbe\x40\x04" |
| 235 "spam" | 232 "spam" |
| 236 "\x04" | 233 "\x04" |
| 237 "eggs"); | 234 "eggs"); |
| 238 SpdyHeaderBlock expected_header_set2; | 235 SpdyHeaderBlock expected_header_set2; |
| 239 expected_header_set2["foo"] = "bar"; | 236 expected_header_set2["foo"] = "bar"; |
| 240 expected_header_set2["spam"] = "eggs"; | 237 expected_header_set2["spam"] = "eggs"; |
| 241 EXPECT_EQ(expected_header_set2, header_set2); | 238 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set2, header_set2)); |
| 242 | 239 |
| 243 // Third header block: refer to most recently added entry. | 240 // Third header block: refer to most recently added entry. |
| 244 SpdyHeaderBlock header_set3 = DecodeBlockExpectingSuccess("\xbe"); | 241 SpdyHeaderBlock header_set3 = DecodeBlockExpectingSuccess("\xbe"); |
| 245 SpdyHeaderBlock expected_header_set3; | 242 SpdyHeaderBlock expected_header_set3; |
| 246 expected_header_set3["spam"] = "eggs"; | 243 expected_header_set3["spam"] = "eggs"; |
| 247 EXPECT_EQ(expected_header_set3, header_set3); | 244 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set3, header_set3)); |
| 248 } | 245 } |
| 249 | 246 |
| 250 // Test a too-large indexed header. | 247 // Test a too-large indexed header. |
| 251 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { | 248 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { |
| 252 // High-bit set, and a prefix of one more than the number of static entries. | 249 // High-bit set, and a prefix of one more than the number of static entries. |
| 253 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1))); | 250 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1))); |
| 254 } | 251 } |
| 255 | 252 |
| 256 // Test that a header block with a pseudo-header field following a regular one | 253 // Test that a header block with a pseudo-header field following a regular one |
| 257 // is treated as malformed. (HTTP2 draft-14 8.1.2.1., HPACK draft-09 3.1.) | 254 // is treated as malformed. (HTTP2 draft-14 8.1.2.1., HPACK draft-09 3.1.) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) { | 310 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) { |
| 314 // First header with indexed name, second header with string literal | 311 // First header with indexed name, second header with string literal |
| 315 // name. | 312 // name. |
| 316 const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2"; | 313 const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2"; |
| 317 SpdyHeaderBlock header_set = | 314 SpdyHeaderBlock header_set = |
| 318 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); | 315 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); |
| 319 | 316 |
| 320 SpdyHeaderBlock expected_header_set; | 317 SpdyHeaderBlock expected_header_set; |
| 321 expected_header_set[":path"] = "/sample/path"; | 318 expected_header_set[":path"] = "/sample/path"; |
| 322 expected_header_set[":path2"] = "/sample/path/2"; | 319 expected_header_set[":path2"] = "/sample/path/2"; |
| 323 EXPECT_EQ(expected_header_set, header_set); | 320 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set, header_set)); |
| 324 } | 321 } |
| 325 | 322 |
| 326 // Decoding two valid encoded literal headers with incremental | 323 // Decoding two valid encoded literal headers with incremental |
| 327 // indexing and string literal names should work. | 324 // indexing and string literal names should work. |
| 328 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) { | 325 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) { |
| 329 const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2"; | 326 const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2"; |
| 330 SpdyHeaderBlock header_set = | 327 SpdyHeaderBlock header_set = |
| 331 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); | 328 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); |
| 332 | 329 |
| 333 SpdyHeaderBlock expected_header_set; | 330 SpdyHeaderBlock expected_header_set; |
| 334 expected_header_set[":path"] = "/sample/path"; | 331 expected_header_set[":path"] = "/sample/path"; |
| 335 expected_header_set[":path2"] = "/sample/path/2"; | 332 expected_header_set[":path2"] = "/sample/path/2"; |
| 336 EXPECT_EQ(expected_header_set, header_set); | 333 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set, header_set)); |
| 337 } | 334 } |
| 338 | 335 |
| 339 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) { | 336 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) { |
| 340 decoder_.ApplyHeaderTableSizeSetting(0); | 337 decoder_.ApplyHeaderTableSizeSetting(0); |
| 341 | 338 |
| 342 // Name is the last static index. Works. | 339 // Name is the last static index. Works. |
| 343 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo"))); | 340 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo"))); |
| 344 // Name is one beyond the last static index. Fails. | 341 // Name is one beyond the last static index. Fails. |
| 345 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo"))); | 342 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo"))); |
| 346 } | 343 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 367 expected_header_set[":method"] = "GET"; | 364 expected_header_set[":method"] = "GET"; |
| 368 expected_header_set[":scheme"] = "http"; | 365 expected_header_set[":scheme"] = "http"; |
| 369 expected_header_set[":path"] = "/"; | 366 expected_header_set[":path"] = "/"; |
| 370 expected_header_set[":authority"] = "www.example.com"; | 367 expected_header_set[":authority"] = "www.example.com"; |
| 371 | 368 |
| 372 string encoded_header_set; | 369 string encoded_header_set; |
| 373 EXPECT_TRUE( | 370 EXPECT_TRUE( |
| 374 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); | 371 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); |
| 375 | 372 |
| 376 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); | 373 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); |
| 377 EXPECT_EQ(expected_header_set, decoded_block()); | 374 EXPECT_TRUE(CompareSpdyHeaderBlocks(expected_header_set, decoded_block())); |
| 378 } | 375 } |
| 379 | 376 |
| 380 TEST_F(HpackDecoderTest, SectionD4RequestHuffmanExamples) { | 377 TEST_F(HpackDecoderTest, SectionD4RequestHuffmanExamples) { |
| 381 SpdyHeaderBlock header_set; | 378 SpdyHeaderBlock header_set; |
| 382 | 379 |
| 383 // 82 | == Indexed - Add == | 380 // 82 | == Indexed - Add == |
| 384 // | idx = 2 | 381 // | idx = 2 |
| 385 // | -> :method: GET | 382 // | -> :method: GET |
| 386 // 86 | == Indexed - Add == | 383 // 86 | == Indexed - Add == |
| 387 // | idx = 6 | 384 // | idx = 6 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 | 658 |
| 662 expectEntry(62, 98, "set-cookie", | 659 expectEntry(62, 98, "set-cookie", |
| 663 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 660 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
| 664 " max-age=3600; version=1"); | 661 " max-age=3600; version=1"); |
| 665 expectEntry(63, 52, "content-encoding", "gzip"); | 662 expectEntry(63, 52, "content-encoding", "gzip"); |
| 666 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); | 663 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); |
| 667 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); | 664 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); |
| 668 } | 665 } |
| 669 | 666 |
| 670 } // namespace | 667 } // namespace |
| 671 | 668 } // namespace test |
| 672 } // namespace net | 669 } // namespace net |
| OLD | NEW |