| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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_decoder3.h" | 5 #include "net/spdy/hpack/hpack_decoder3.h" |
| 6 | 6 |
| 7 // Tests of HpackDecoder3. | 7 // Tests of HpackDecoder3. |
| 8 | 8 |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include <string> | |
| 12 #include <tuple> | 11 #include <tuple> |
| 13 #include <utility> | 12 #include <utility> |
| 14 #include <vector> | 13 #include <vector> |
| 15 | 14 |
| 16 #include "base/logging.h" | 15 #include "base/logging.h" |
| 17 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 18 #include "net/http2/hpack/decoder/hpack_decoder_state.h" | 17 #include "net/http2/hpack/decoder/hpack_decoder_state.h" |
| 19 #include "net/http2/hpack/decoder/hpack_decoder_tables.h" | 18 #include "net/http2/hpack/decoder/hpack_decoder_tables.h" |
| 20 #include "net/http2/hpack/tools/hpack_block_builder.h" | 19 #include "net/http2/hpack/tools/hpack_block_builder.h" |
| 21 #include "net/http2/tools/http2_random.h" | 20 #include "net/http2/tools/http2_random.h" |
| 22 #include "net/spdy/hpack/hpack_constants.h" | 21 #include "net/spdy/hpack/hpack_constants.h" |
| 23 #include "net/spdy/hpack/hpack_encoder.h" | 22 #include "net/spdy/hpack/hpack_encoder.h" |
| 24 #include "net/spdy/hpack/hpack_huffman_table.h" | 23 #include "net/spdy/hpack/hpack_huffman_table.h" |
| 25 #include "net/spdy/hpack/hpack_output_stream.h" | 24 #include "net/spdy/hpack/hpack_output_stream.h" |
| 25 #include "net/spdy/platform/api/spdy_string.h" |
| 26 #include "net/spdy/spdy_test_utils.h" | 26 #include "net/spdy/spdy_test_utils.h" |
| 27 #include "testing/gmock/include/gmock/gmock.h" | 27 #include "testing/gmock/include/gmock/gmock.h" |
| 28 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
| 29 | 29 |
| 30 using std::string; | |
| 31 using ::testing::ElementsAre; | 30 using ::testing::ElementsAre; |
| 32 using ::testing::Pair; | 31 using ::testing::Pair; |
| 33 | 32 |
| 34 namespace net { | 33 namespace net { |
| 35 namespace test { | 34 namespace test { |
| 36 | 35 |
| 37 class HpackDecoderStatePeer { | 36 class HpackDecoderStatePeer { |
| 38 public: | 37 public: |
| 39 static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { | 38 static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { |
| 40 return &state->decoder_tables_; | 39 return &state->decoder_tables_; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 } | 166 } |
| 168 } | 167 } |
| 169 | 168 |
| 170 const SpdyHeaderBlock& DecodeBlockExpectingSuccess(SpdyStringPiece str) { | 169 const SpdyHeaderBlock& DecodeBlockExpectingSuccess(SpdyStringPiece str) { |
| 171 EXPECT_TRUE(DecodeHeaderBlock(str)); | 170 EXPECT_TRUE(DecodeHeaderBlock(str)); |
| 172 return decoded_block(); | 171 return decoded_block(); |
| 173 } | 172 } |
| 174 | 173 |
| 175 void expectEntry(size_t index, | 174 void expectEntry(size_t index, |
| 176 size_t size, | 175 size_t size, |
| 177 const string& name, | 176 const SpdyString& name, |
| 178 const string& value) { | 177 const SpdyString& value) { |
| 179 const HpackStringPair* entry = decoder_peer_.GetTableEntry(index); | 178 const HpackStringPair* entry = decoder_peer_.GetTableEntry(index); |
| 180 EXPECT_EQ(name, entry->name) << "index " << index; | 179 EXPECT_EQ(name, entry->name) << "index " << index; |
| 181 EXPECT_EQ(value, entry->value); | 180 EXPECT_EQ(value, entry->value); |
| 182 EXPECT_EQ(size, entry->size()); | 181 EXPECT_EQ(size, entry->size()); |
| 183 } | 182 } |
| 184 | 183 |
| 185 SpdyHeaderBlock MakeHeaderBlock( | 184 SpdyHeaderBlock MakeHeaderBlock( |
| 186 const std::vector<std::pair<string, string>>& headers) { | 185 const std::vector<std::pair<SpdyString, SpdyString>>& headers) { |
| 187 SpdyHeaderBlock result; | 186 SpdyHeaderBlock result; |
| 188 for (const auto& kv : headers) { | 187 for (const auto& kv : headers) { |
| 189 result.AppendValueOrAddHeader(kv.first, kv.second); | 188 result.AppendValueOrAddHeader(kv.first, kv.second); |
| 190 } | 189 } |
| 191 return result; | 190 return result; |
| 192 } | 191 } |
| 193 | 192 |
| 194 Http2Random random_; | 193 Http2Random random_; |
| 195 HpackHuffmanTable huffman_table_; | 194 HpackHuffmanTable huffman_table_; |
| 196 HpackDecoder3 decoder_; | 195 HpackDecoder3 decoder_; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 207 ::testing::Combine( | 206 ::testing::Combine( |
| 208 ::testing::Values(START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START), | 207 ::testing::Values(START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START), |
| 209 ::testing::Bool())); | 208 ::testing::Bool())); |
| 210 | 209 |
| 211 TEST_P(HpackDecoder3Test, AddHeaderDataWithHandleControlFrameHeadersData) { | 210 TEST_P(HpackDecoder3Test, AddHeaderDataWithHandleControlFrameHeadersData) { |
| 212 // The hpack decode buffer size is limited in size. This test verifies that | 211 // The hpack decode buffer size is limited in size. This test verifies that |
| 213 // adding encoded data under that limit is accepted, and data that exceeds the | 212 // adding encoded data under that limit is accepted, and data that exceeds the |
| 214 // limit is rejected. | 213 // limit is rejected. |
| 215 HandleControlFrameHeadersStart(); | 214 HandleControlFrameHeadersStart(); |
| 216 const size_t kMaxBufferSizeBytes = 50; | 215 const size_t kMaxBufferSizeBytes = 50; |
| 217 const string a_value = string(49, 'x'); | 216 const SpdyString a_value = SpdyString(49, 'x'); |
| 218 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); | 217 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); |
| 219 HpackBlockBuilder hbb; | 218 HpackBlockBuilder hbb; |
| 220 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, | 219 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, |
| 221 false, "a", false, a_value); | 220 false, "a", false, a_value); |
| 222 const string& s = hbb.buffer(); | 221 const SpdyString& s = hbb.buffer(); |
| 223 EXPECT_GT(s.size(), kMaxBufferSizeBytes); | 222 EXPECT_GT(s.size(), kMaxBufferSizeBytes); |
| 224 | 223 |
| 225 // Any one in input buffer must not exceed kMaxBufferSizeBytes. | 224 // Any one in input buffer must not exceed kMaxBufferSizeBytes. |
| 226 EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(0, s.size() / 2))); | 225 EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(0, s.size() / 2))); |
| 227 EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(s.size() / 2))); | 226 EXPECT_TRUE(HandleControlFrameHeadersData(s.substr(s.size() / 2))); |
| 228 | 227 |
| 229 EXPECT_FALSE(HandleControlFrameHeadersData(s)); | 228 EXPECT_FALSE(HandleControlFrameHeadersData(s)); |
| 230 SpdyHeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}}); | 229 SpdyHeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}}); |
| 231 EXPECT_EQ(expected_block, decoded_block()); | 230 EXPECT_EQ(expected_block, decoded_block()); |
| 232 } | 231 } |
| 233 | 232 |
| 234 TEST_P(HpackDecoder3Test, NameTooLong) { | 233 TEST_P(HpackDecoder3Test, NameTooLong) { |
| 235 // Verify that a name longer than the allowed size generates an error. | 234 // Verify that a name longer than the allowed size generates an error. |
| 236 const size_t kMaxBufferSizeBytes = 50; | 235 const size_t kMaxBufferSizeBytes = 50; |
| 237 const string name = string(2 * kMaxBufferSizeBytes, 'x'); | 236 const SpdyString name = SpdyString(2 * kMaxBufferSizeBytes, 'x'); |
| 238 const string value = "abc"; | 237 const SpdyString value = "abc"; |
| 239 | 238 |
| 240 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); | 239 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); |
| 241 | 240 |
| 242 HpackBlockBuilder hbb; | 241 HpackBlockBuilder hbb; |
| 243 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, | 242 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, |
| 244 false, name, false, value); | 243 false, name, false, value); |
| 245 | 244 |
| 246 const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2; | 245 const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2; |
| 247 const string fragment = hbb.buffer().substr(0, fragment_size); | 246 const SpdyString fragment = hbb.buffer().substr(0, fragment_size); |
| 248 | 247 |
| 249 HandleControlFrameHeadersStart(); | 248 HandleControlFrameHeadersStart(); |
| 250 EXPECT_FALSE(HandleControlFrameHeadersData(fragment)); | 249 EXPECT_FALSE(HandleControlFrameHeadersData(fragment)); |
| 251 } | 250 } |
| 252 | 251 |
| 253 TEST_P(HpackDecoder3Test, HeaderTooLongToBuffer) { | 252 TEST_P(HpackDecoder3Test, HeaderTooLongToBuffer) { |
| 254 // Verify that a header longer than the allowed size generates an error if | 253 // Verify that a header longer than the allowed size generates an error if |
| 255 // it isn't all in one input buffer. | 254 // it isn't all in one input buffer. |
| 256 const string name = "some-key"; | 255 const SpdyString name = "some-key"; |
| 257 const string value = "some-value"; | 256 const SpdyString value = "some-value"; |
| 258 const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2; | 257 const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2; |
| 259 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); | 258 decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes); |
| 260 | 259 |
| 261 HpackBlockBuilder hbb; | 260 HpackBlockBuilder hbb; |
| 262 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, | 261 hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, |
| 263 false, name, false, value); | 262 false, name, false, value); |
| 264 const size_t fragment_size = hbb.size() - 1; | 263 const size_t fragment_size = hbb.size() - 1; |
| 265 const string fragment = hbb.buffer().substr(0, fragment_size); | 264 const SpdyString fragment = hbb.buffer().substr(0, fragment_size); |
| 266 | 265 |
| 267 HandleControlFrameHeadersStart(); | 266 HandleControlFrameHeadersStart(); |
| 268 EXPECT_FALSE(HandleControlFrameHeadersData(fragment)); | 267 EXPECT_FALSE(HandleControlFrameHeadersData(fragment)); |
| 269 } | 268 } |
| 270 | 269 |
| 271 // Decode with incomplete data in buffer. | 270 // Decode with incomplete data in buffer. |
| 272 TEST_P(HpackDecoder3Test, DecodeWithIncompleteData) { | 271 TEST_P(HpackDecoder3Test, DecodeWithIncompleteData) { |
| 273 HandleControlFrameHeadersStart(); | 272 HandleControlFrameHeadersStart(); |
| 274 | 273 |
| 275 // No need to wait for more data. | 274 // No need to wait for more data. |
| 276 EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82")); | 275 EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82")); |
| 277 std::vector<std::pair<string, string>> expected_headers = { | 276 std::vector<std::pair<SpdyString, SpdyString>> expected_headers = { |
| 278 {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}}; | 277 {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}}; |
| 279 | 278 |
| 280 SpdyHeaderBlock expected_block1 = MakeHeaderBlock(expected_headers); | 279 SpdyHeaderBlock expected_block1 = MakeHeaderBlock(expected_headers); |
| 281 EXPECT_EQ(expected_block1, decoded_block()); | 280 EXPECT_EQ(expected_block1, decoded_block()); |
| 282 | 281 |
| 283 // Full and partial headers, won't add partial to the headers. | 282 // Full and partial headers, won't add partial to the headers. |
| 284 EXPECT_TRUE( | 283 EXPECT_TRUE( |
| 285 HandleControlFrameHeadersData("\x40\x03goo" | 284 HandleControlFrameHeadersData("\x40\x03goo" |
| 286 "\x03gar\xbe\x40\x04spam")); | 285 "\x03gar\xbe\x40\x04spam")); |
| 287 expected_headers.push_back({"goo", "gar"}); | 286 expected_headers.push_back({"goo", "gar"}); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 308 HandleControlFrameHeadersStart(); | 307 HandleControlFrameHeadersStart(); |
| 309 HandleControlFrameHeadersData(""); | 308 HandleControlFrameHeadersData(""); |
| 310 | 309 |
| 311 // All cookie crumbs are joined. | 310 // All cookie crumbs are joined. |
| 312 decoder_peer_.HandleHeaderRepresentation("cookie", " part 1"); | 311 decoder_peer_.HandleHeaderRepresentation("cookie", " part 1"); |
| 313 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 "); | 312 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 "); |
| 314 decoder_peer_.HandleHeaderRepresentation("cookie", "part3"); | 313 decoder_peer_.HandleHeaderRepresentation("cookie", "part3"); |
| 315 | 314 |
| 316 // Already-delimited headers are passed through. | 315 // Already-delimited headers are passed through. |
| 317 decoder_peer_.HandleHeaderRepresentation("passed-through", | 316 decoder_peer_.HandleHeaderRepresentation("passed-through", |
| 318 string("foo\0baz", 7)); | 317 SpdyString("foo\0baz", 7)); |
| 319 | 318 |
| 320 // Other headers are joined on \0. Case matters. | 319 // Other headers are joined on \0. Case matters. |
| 321 decoder_peer_.HandleHeaderRepresentation("joined", "not joined"); | 320 decoder_peer_.HandleHeaderRepresentation("joined", "not joined"); |
| 322 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1"); | 321 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1"); |
| 323 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2"); | 322 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2"); |
| 324 | 323 |
| 325 // Empty headers remain empty. | 324 // Empty headers remain empty. |
| 326 decoder_peer_.HandleHeaderRepresentation("empty", ""); | 325 decoder_peer_.HandleHeaderRepresentation("empty", ""); |
| 327 | 326 |
| 328 // Joined empty headers work as expected. | 327 // Joined empty headers work as expected. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 394 |
| 396 // Test a too-large indexed header. | 395 // Test a too-large indexed header. |
| 397 TEST_P(HpackDecoder3Test, InvalidIndexedHeader) { | 396 TEST_P(HpackDecoder3Test, InvalidIndexedHeader) { |
| 398 // High-bit set, and a prefix of one more than the number of static entries. | 397 // High-bit set, and a prefix of one more than the number of static entries. |
| 399 EXPECT_FALSE(DecodeHeaderBlock("\xbe")); | 398 EXPECT_FALSE(DecodeHeaderBlock("\xbe")); |
| 400 } | 399 } |
| 401 | 400 |
| 402 TEST_P(HpackDecoder3Test, ContextUpdateMaximumSize) { | 401 TEST_P(HpackDecoder3Test, ContextUpdateMaximumSize) { |
| 403 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 402 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 404 decoder_peer_.header_table_size_limit()); | 403 decoder_peer_.header_table_size_limit()); |
| 405 string input; | 404 SpdyString input; |
| 406 { | 405 { |
| 407 // Maximum-size update with size 126. Succeeds. | 406 // Maximum-size update with size 126. Succeeds. |
| 408 HpackOutputStream output_stream; | 407 HpackOutputStream output_stream; |
| 409 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 408 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 410 output_stream.AppendUint32(126); | 409 output_stream.AppendUint32(126); |
| 411 | 410 |
| 412 output_stream.TakeString(&input); | 411 output_stream.TakeString(&input); |
| 413 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); | 412 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 414 EXPECT_EQ(126u, decoder_peer_.header_table_size_limit()); | 413 EXPECT_EQ(126u, decoder_peer_.header_table_size_limit()); |
| 415 } | 414 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 432 | 431 |
| 433 output_stream.TakeString(&input); | 432 output_stream.TakeString(&input); |
| 434 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 433 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 435 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 434 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 436 decoder_peer_.header_table_size_limit()); | 435 decoder_peer_.header_table_size_limit()); |
| 437 } | 436 } |
| 438 } | 437 } |
| 439 | 438 |
| 440 // Two HeaderTableSizeUpdates may appear at the beginning of the block | 439 // Two HeaderTableSizeUpdates may appear at the beginning of the block |
| 441 TEST_P(HpackDecoder3Test, TwoTableSizeUpdates) { | 440 TEST_P(HpackDecoder3Test, TwoTableSizeUpdates) { |
| 442 string input; | 441 SpdyString input; |
| 443 { | 442 { |
| 444 // Should accept two table size updates, update to second one | 443 // Should accept two table size updates, update to second one |
| 445 HpackOutputStream output_stream; | 444 HpackOutputStream output_stream; |
| 446 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 445 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 447 output_stream.AppendUint32(0); | 446 output_stream.AppendUint32(0); |
| 448 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 447 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 449 output_stream.AppendUint32(122); | 448 output_stream.AppendUint32(122); |
| 450 | 449 |
| 451 output_stream.TakeString(&input); | 450 output_stream.TakeString(&input); |
| 452 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); | 451 EXPECT_TRUE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 453 EXPECT_EQ(122u, decoder_peer_.header_table_size_limit()); | 452 EXPECT_EQ(122u, decoder_peer_.header_table_size_limit()); |
| 454 } | 453 } |
| 455 } | 454 } |
| 456 | 455 |
| 457 // Three HeaderTableSizeUpdates should result in an error | 456 // Three HeaderTableSizeUpdates should result in an error |
| 458 TEST_P(HpackDecoder3Test, ThreeTableSizeUpdatesError) { | 457 TEST_P(HpackDecoder3Test, ThreeTableSizeUpdatesError) { |
| 459 string input; | 458 SpdyString input; |
| 460 { | 459 { |
| 461 // Should reject three table size updates, update to second one | 460 // Should reject three table size updates, update to second one |
| 462 HpackOutputStream output_stream; | 461 HpackOutputStream output_stream; |
| 463 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 462 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 464 output_stream.AppendUint32(5); | 463 output_stream.AppendUint32(5); |
| 465 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 464 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 466 output_stream.AppendUint32(10); | 465 output_stream.AppendUint32(10); |
| 467 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 466 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 468 output_stream.AppendUint32(15); | 467 output_stream.AppendUint32(15); |
| 469 | 468 |
| 470 output_stream.TakeString(&input); | 469 output_stream.TakeString(&input); |
| 471 | 470 |
| 472 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 471 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 473 EXPECT_EQ(10u, decoder_peer_.header_table_size_limit()); | 472 EXPECT_EQ(10u, decoder_peer_.header_table_size_limit()); |
| 474 } | 473 } |
| 475 } | 474 } |
| 476 | 475 |
| 477 // HeaderTableSizeUpdates may only appear at the beginning of the block | 476 // HeaderTableSizeUpdates may only appear at the beginning of the block |
| 478 // Any other updates should result in an error | 477 // Any other updates should result in an error |
| 479 TEST_P(HpackDecoder3Test, TableSizeUpdateSecondError) { | 478 TEST_P(HpackDecoder3Test, TableSizeUpdateSecondError) { |
| 480 string input; | 479 SpdyString input; |
| 481 { | 480 { |
| 482 // Should reject a table size update appearing after a different entry | 481 // Should reject a table size update appearing after a different entry |
| 483 // The table size should remain as the default | 482 // The table size should remain as the default |
| 484 HpackOutputStream output_stream; | 483 HpackOutputStream output_stream; |
| 485 output_stream.AppendBytes("\x82\x85"); | 484 output_stream.AppendBytes("\x82\x85"); |
| 486 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 485 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 487 output_stream.AppendUint32(123); | 486 output_stream.AppendUint32(123); |
| 488 | 487 |
| 489 output_stream.TakeString(&input); | 488 output_stream.TakeString(&input); |
| 490 | 489 |
| 491 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); | 490 EXPECT_FALSE(DecodeHeaderBlock(SpdyStringPiece(input))); |
| 492 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 491 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 493 decoder_peer_.header_table_size_limit()); | 492 decoder_peer_.header_table_size_limit()); |
| 494 } | 493 } |
| 495 } | 494 } |
| 496 | 495 |
| 497 // HeaderTableSizeUpdates may only appear at the beginning of the block | 496 // HeaderTableSizeUpdates may only appear at the beginning of the block |
| 498 // Any other updates should result in an error | 497 // Any other updates should result in an error |
| 499 TEST_P(HpackDecoder3Test, TableSizeUpdateFirstThirdError) { | 498 TEST_P(HpackDecoder3Test, TableSizeUpdateFirstThirdError) { |
| 500 string input; | 499 SpdyString input; |
| 501 { | 500 { |
| 502 // Should reject the second table size update | 501 // Should reject the second table size update |
| 503 // if a different entry appears after the first update | 502 // if a different entry appears after the first update |
| 504 // The table size should update to the first but not the second | 503 // The table size should update to the first but not the second |
| 505 HpackOutputStream output_stream; | 504 HpackOutputStream output_stream; |
| 506 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 505 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 507 output_stream.AppendUint32(60); | 506 output_stream.AppendUint32(60); |
| 508 output_stream.AppendBytes("\x82\x85"); | 507 output_stream.AppendBytes("\x82\x85"); |
| 509 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); | 508 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 510 output_stream.AppendUint32(125); | 509 output_stream.AppendUint32(125); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 // 41 | == Literal indexed == | 580 // 41 | == Literal indexed == |
| 582 // | Indexed name (idx = 1) | 581 // | Indexed name (idx = 1) |
| 583 // | :authority | 582 // | :authority |
| 584 // 8c | Literal value (len = 12) | 583 // 8c | Literal value (len = 12) |
| 585 // | Huffman encoded: | 584 // | Huffman encoded: |
| 586 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... | 585 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... |
| 587 // | Decoded: | 586 // | Decoded: |
| 588 // | www.example.com | 587 // | www.example.com |
| 589 // | -> :authority: www.example.com | 588 // | -> :authority: www.example.com |
| 590 | 589 |
| 591 string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff"); | 590 SpdyString first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff"); |
| 592 EXPECT_TRUE(DecodeHeaderBlock(first)); | 591 EXPECT_TRUE(DecodeHeaderBlock(first)); |
| 593 first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4"); | 592 first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4"); |
| 594 EXPECT_FALSE(DecodeHeaderBlock(first)); | 593 EXPECT_FALSE(DecodeHeaderBlock(first)); |
| 595 } | 594 } |
| 596 | 595 |
| 597 TEST_P(HpackDecoder3Test, HuffmanEOSError) { | 596 TEST_P(HpackDecoder3Test, HuffmanEOSError) { |
| 598 // Literal value, Huffman encoded, but with an additional ff byte at the end | 597 // Literal value, Huffman encoded, but with an additional ff byte at the end |
| 599 // of the string, i.e. an EOS that is longer than permitted. | 598 // of the string, i.e. an EOS that is longer than permitted. |
| 600 // | 599 // |
| 601 // 41 | == Literal indexed == | 600 // 41 | == Literal indexed == |
| 602 // | Indexed name (idx = 1) | 601 // | Indexed name (idx = 1) |
| 603 // | :authority | 602 // | :authority |
| 604 // 8d | Literal value (len = 13) | 603 // 8d | Literal value (len = 13) |
| 605 // | Huffman encoded: | 604 // | Huffman encoded: |
| 606 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... | 605 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... |
| 607 // | Decoded: | 606 // | Decoded: |
| 608 // | www.example.com | 607 // | www.example.com |
| 609 // | -> :authority: www.example.com | 608 // | -> :authority: www.example.com |
| 610 | 609 |
| 611 string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff"); | 610 SpdyString first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff"); |
| 612 EXPECT_TRUE(DecodeHeaderBlock(first)); | 611 EXPECT_TRUE(DecodeHeaderBlock(first)); |
| 613 first = a2b_hex("418df1e3c2e5f23a6ba0ab90f4ffff"); | 612 first = a2b_hex("418df1e3c2e5f23a6ba0ab90f4ffff"); |
| 614 EXPECT_FALSE(DecodeHeaderBlock(first)); | 613 EXPECT_FALSE(DecodeHeaderBlock(first)); |
| 615 } | 614 } |
| 616 | 615 |
| 617 // Round-tripping the header set from RFC 7541 C.3.1 should work. | 616 // Round-tripping the header set from RFC 7541 C.3.1 should work. |
| 618 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 | 617 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 |
| 619 TEST_P(HpackDecoder3Test, BasicC31) { | 618 TEST_P(HpackDecoder3Test, BasicC31) { |
| 620 HpackEncoder encoder(ObtainHpackHuffmanTable()); | 619 HpackEncoder encoder(ObtainHpackHuffmanTable()); |
| 621 | 620 |
| 622 SpdyHeaderBlock expected_header_set; | 621 SpdyHeaderBlock expected_header_set; |
| 623 expected_header_set[":method"] = "GET"; | 622 expected_header_set[":method"] = "GET"; |
| 624 expected_header_set[":scheme"] = "http"; | 623 expected_header_set[":scheme"] = "http"; |
| 625 expected_header_set[":path"] = "/"; | 624 expected_header_set[":path"] = "/"; |
| 626 expected_header_set[":authority"] = "www.example.com"; | 625 expected_header_set[":authority"] = "www.example.com"; |
| 627 | 626 |
| 628 string encoded_header_set; | 627 SpdyString encoded_header_set; |
| 629 EXPECT_TRUE( | 628 EXPECT_TRUE( |
| 630 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); | 629 encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set)); |
| 631 | 630 |
| 632 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); | 631 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); |
| 633 EXPECT_EQ(expected_header_set, decoded_block()); | 632 EXPECT_EQ(expected_header_set, decoded_block()); |
| 634 } | 633 } |
| 635 | 634 |
| 636 // RFC 7541, Section C.4: Request Examples with Huffman Coding | 635 // RFC 7541, Section C.4: Request Examples with Huffman Coding |
| 637 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 | 636 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 |
| 638 TEST_P(HpackDecoder3Test, SectionC4RequestHuffmanExamples) { | 637 TEST_P(HpackDecoder3Test, SectionC4RequestHuffmanExamples) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 649 // | -> :path: / | 648 // | -> :path: / |
| 650 // 41 | == Literal indexed == | 649 // 41 | == Literal indexed == |
| 651 // | Indexed name (idx = 1) | 650 // | Indexed name (idx = 1) |
| 652 // | :authority | 651 // | :authority |
| 653 // 8c | Literal value (len = 12) | 652 // 8c | Literal value (len = 12) |
| 654 // | Huffman encoded: | 653 // | Huffman encoded: |
| 655 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... | 654 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... |
| 656 // | Decoded: | 655 // | Decoded: |
| 657 // | www.example.com | 656 // | www.example.com |
| 658 // | -> :authority: www.example.com | 657 // | -> :authority: www.example.com |
| 659 string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff"); | 658 SpdyString first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff"); |
| 660 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); | 659 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); |
| 661 | 660 |
| 662 EXPECT_THAT(first_header_set, | 661 EXPECT_THAT(first_header_set, |
| 663 ElementsAre( | 662 ElementsAre( |
| 664 // clang-format off | 663 // clang-format off |
| 665 Pair(":method", "GET"), | 664 Pair(":method", "GET"), |
| 666 Pair(":scheme", "http"), | 665 Pair(":scheme", "http"), |
| 667 Pair(":path", "/"), | 666 Pair(":path", "/"), |
| 668 Pair(":authority", "www.example.com"))); | 667 Pair(":authority", "www.example.com"))); |
| 669 // clang-format on | 668 // clang-format on |
| (...skipping 16 matching lines...) Expand all Loading... |
| 686 // 58 | == Literal indexed == | 685 // 58 | == Literal indexed == |
| 687 // | Indexed name (idx = 24) | 686 // | Indexed name (idx = 24) |
| 688 // | cache-control | 687 // | cache-control |
| 689 // 86 | Literal value (len = 8) | 688 // 86 | Literal value (len = 8) |
| 690 // | Huffman encoded: | 689 // | Huffman encoded: |
| 691 // a8eb 1064 9cbf | ...d.. | 690 // a8eb 1064 9cbf | ...d.. |
| 692 // | Decoded: | 691 // | Decoded: |
| 693 // | no-cache | 692 // | no-cache |
| 694 // | -> cache-control: no-cache | 693 // | -> cache-control: no-cache |
| 695 | 694 |
| 696 string second = a2b_hex("828684be5886a8eb10649cbf"); | 695 SpdyString second = a2b_hex("828684be5886a8eb10649cbf"); |
| 697 const SpdyHeaderBlock& second_header_set = | 696 const SpdyHeaderBlock& second_header_set = |
| 698 DecodeBlockExpectingSuccess(second); | 697 DecodeBlockExpectingSuccess(second); |
| 699 | 698 |
| 700 EXPECT_THAT(second_header_set, | 699 EXPECT_THAT(second_header_set, |
| 701 ElementsAre( | 700 ElementsAre( |
| 702 // clang-format off | 701 // clang-format off |
| 703 Pair(":method", "GET"), | 702 Pair(":method", "GET"), |
| 704 Pair(":scheme", "http"), | 703 Pair(":scheme", "http"), |
| 705 Pair(":path", "/"), | 704 Pair(":path", "/"), |
| 706 Pair(":authority", "www.example.com"), | 705 Pair(":authority", "www.example.com"), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 728 // | Huffman encoded: | 727 // | Huffman encoded: |
| 729 // 25a8 49e9 5ba9 7d7f | %.I.[.}. | 728 // 25a8 49e9 5ba9 7d7f | %.I.[.}. |
| 730 // | Decoded: | 729 // | Decoded: |
| 731 // | custom-key | 730 // | custom-key |
| 732 // 89 | Literal value (len = 12) | 731 // 89 | Literal value (len = 12) |
| 733 // | Huffman encoded: | 732 // | Huffman encoded: |
| 734 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... | 733 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... |
| 735 // | Decoded: | 734 // | Decoded: |
| 736 // | custom-value | 735 // | custom-value |
| 737 // | -> custom-key: custom-value | 736 // | -> custom-key: custom-value |
| 738 string third = a2b_hex("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf"); | 737 SpdyString third = |
| 738 a2b_hex("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf"); |
| 739 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); | 739 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); |
| 740 | 740 |
| 741 EXPECT_THAT( | 741 EXPECT_THAT( |
| 742 third_header_set, | 742 third_header_set, |
| 743 ElementsAre( | 743 ElementsAre( |
| 744 // clang-format off | 744 // clang-format off |
| 745 Pair(":method", "GET"), | 745 Pair(":method", "GET"), |
| 746 Pair(":scheme", "https"), | 746 Pair(":scheme", "https"), |
| 747 Pair(":path", "/index.html"), | 747 Pair(":path", "/index.html"), |
| 748 Pair(":authority", "www.example.com"), | 748 Pair(":authority", "www.example.com"), |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 // | location | 797 // | location |
| 798 // 91 | Literal value (len = 23) | 798 // 91 | Literal value (len = 23) |
| 799 // | Huffman encoded: | 799 // | Huffman encoded: |
| 800 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C | 800 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C |
| 801 // d3 | . | 801 // d3 | . |
| 802 // | Decoded: | 802 // | Decoded: |
| 803 // | https://www.example.com | 803 // | https://www.example.com |
| 804 // | -> location: https://www.e | 804 // | -> location: https://www.e |
| 805 // | xample.com | 805 // | xample.com |
| 806 | 806 |
| 807 string first = a2b_hex( | 807 SpdyString first = a2b_hex( |
| 808 "488264025885aec3771a4b6196d07abe" | 808 "488264025885aec3771a4b6196d07abe" |
| 809 "941054d444a8200595040b8166e082a6" | 809 "941054d444a8200595040b8166e082a6" |
| 810 "2d1bff6e919d29ad171863c78f0b97c8" | 810 "2d1bff6e919d29ad171863c78f0b97c8" |
| 811 "e9ae82ae43d3"); | 811 "e9ae82ae43d3"); |
| 812 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); | 812 const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first); |
| 813 | 813 |
| 814 EXPECT_THAT(first_header_set, | 814 EXPECT_THAT(first_header_set, |
| 815 ElementsAre( | 815 ElementsAre( |
| 816 // clang-format off | 816 // clang-format off |
| 817 Pair(":status", "302"), | 817 Pair(":status", "302"), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 840 // | idx = 65 | 840 // | idx = 65 |
| 841 // | -> cache-control: private | 841 // | -> cache-control: private |
| 842 // c0 | == Indexed - Add == | 842 // c0 | == Indexed - Add == |
| 843 // | idx = 64 | 843 // | idx = 64 |
| 844 // | -> date: Mon, 21 Oct 2013 | 844 // | -> date: Mon, 21 Oct 2013 |
| 845 // | 20:13:21 GMT | 845 // | 20:13:21 GMT |
| 846 // bf | == Indexed - Add == | 846 // bf | == Indexed - Add == |
| 847 // | idx = 63 | 847 // | idx = 63 |
| 848 // | -> location: | 848 // | -> location: |
| 849 // | https://www.example.com | 849 // | https://www.example.com |
| 850 string second = a2b_hex("4883640effc1c0bf"); | 850 SpdyString second = a2b_hex("4883640effc1c0bf"); |
| 851 const SpdyHeaderBlock& second_header_set = | 851 const SpdyHeaderBlock& second_header_set = |
| 852 DecodeBlockExpectingSuccess(second); | 852 DecodeBlockExpectingSuccess(second); |
| 853 | 853 |
| 854 EXPECT_THAT(second_header_set, | 854 EXPECT_THAT(second_header_set, |
| 855 ElementsAre( | 855 ElementsAre( |
| 856 // clang-format off | 856 // clang-format off |
| 857 Pair(":status", "307"), | 857 Pair(":status", "307"), |
| 858 Pair("cache-control", "private"), | 858 Pair("cache-control", "private"), |
| 859 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), | 859 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), |
| 860 Pair("location", "https://www.example.com"))); | 860 Pair("location", "https://www.example.com"))); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 // | Decoded: | 912 // | Decoded: |
| 913 // | foo=ASDJKHQKBZXOQWEOPIUAXQ | 913 // | foo=ASDJKHQKBZXOQWEOPIUAXQ |
| 914 // | WEOIU; max-age=3600; versi | 914 // | WEOIU; max-age=3600; versi |
| 915 // | on=1 | 915 // | on=1 |
| 916 // | - evict: location: | 916 // | - evict: location: |
| 917 // | https://www.example.com | 917 // | https://www.example.com |
| 918 // | - evict: :status: 307 | 918 // | - evict: :status: 307 |
| 919 // | -> set-cookie: foo=ASDJKHQ | 919 // | -> set-cookie: foo=ASDJKHQ |
| 920 // | KBZXOQWEOPIUAXQWEOIU; | 920 // | KBZXOQWEOPIUAXQWEOIU; |
| 921 // | max-age=3600; version=1 | 921 // | max-age=3600; version=1 |
| 922 string third = a2b_hex( | 922 SpdyString third = a2b_hex( |
| 923 "88c16196d07abe941054d444a8200595" | 923 "88c16196d07abe941054d444a8200595" |
| 924 "040b8166e084a62d1bffc05a839bd9ab" | 924 "040b8166e084a62d1bffc05a839bd9ab" |
| 925 "77ad94e7821dd7f2e6c7b335dfdfcd5b" | 925 "77ad94e7821dd7f2e6c7b335dfdfcd5b" |
| 926 "3960d5af27087f3672c1ab270fb5291f" | 926 "3960d5af27087f3672c1ab270fb5291f" |
| 927 "9587316065c003ed4ee5b1063d5007"); | 927 "9587316065c003ed4ee5b1063d5007"); |
| 928 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); | 928 const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third); |
| 929 | 929 |
| 930 EXPECT_THAT(third_header_set, | 930 EXPECT_THAT(third_header_set, |
| 931 ElementsAre( | 931 ElementsAre( |
| 932 // clang-format off | 932 // clang-format off |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 SpdyHeaderBlock expected_header_set; | 993 SpdyHeaderBlock expected_header_set; |
| 994 expected_header_set.AppendValueOrAddHeader(name, value1); | 994 expected_header_set.AppendValueOrAddHeader(name, value1); |
| 995 expected_header_set.AppendValueOrAddHeader(name, value1); | 995 expected_header_set.AppendValueOrAddHeader(name, value1); |
| 996 expected_header_set.AppendValueOrAddHeader(name, value2); | 996 expected_header_set.AppendValueOrAddHeader(name, value2); |
| 997 expected_header_set.AppendValueOrAddHeader(name, value2); | 997 expected_header_set.AppendValueOrAddHeader(name, value2); |
| 998 expected_header_set.AppendValueOrAddHeader(name, value3); | 998 expected_header_set.AppendValueOrAddHeader(name, value3); |
| 999 expected_header_set.AppendValueOrAddHeader(name, value3); | 999 expected_header_set.AppendValueOrAddHeader(name, value3); |
| 1000 | 1000 |
| 1001 // SpdyHeaderBlock stores these 6 strings as '\0' separated values. | 1001 // SpdyHeaderBlock stores these 6 strings as '\0' separated values. |
| 1002 // Make sure that is what happened. | 1002 // Make sure that is what happened. |
| 1003 string joined_values = expected_header_set[name].as_string(); | 1003 SpdyString joined_values = expected_header_set[name].as_string(); |
| 1004 EXPECT_EQ(joined_values.size(), | 1004 EXPECT_EQ(joined_values.size(), |
| 1005 2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5); | 1005 2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5); |
| 1006 | 1006 |
| 1007 EXPECT_EQ(expected_header_set, decoded_block()); | 1007 EXPECT_EQ(expected_header_set, decoded_block()); |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 } // namespace | 1010 } // namespace |
| 1011 } // namespace test | 1011 } // namespace test |
| 1012 } // namespace net | 1012 } // namespace net |
| OLD | NEW |