| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/hpack_decoder.h" | 5 #include "net/spdy/hpack_decoder.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 | 92 |
| 93 void expectEntry(size_t index, size_t size, const string& name, | 93 void expectEntry(size_t index, size_t size, const string& name, |
| 94 const string& value) { | 94 const string& value) { |
| 95 HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index); | 95 HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index); |
| 96 EXPECT_EQ(name, entry->name()) << "index " << index; | 96 EXPECT_EQ(name, entry->name()) << "index " << index; |
| 97 EXPECT_EQ(value, entry->value()); | 97 EXPECT_EQ(value, entry->value()); |
| 98 EXPECT_EQ(size, entry->Size()); | 98 EXPECT_EQ(size, entry->Size()); |
| 99 EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry)); | 99 EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry)); |
| 100 } | 100 } |
| 101 | 101 |
| 102 void expectStaticEntry(size_t index) { | |
| 103 HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index); | |
| 104 EXPECT_TRUE(entry->IsStatic()) << "index " << index; | |
| 105 } | |
| 106 | |
| 107 HpackDecoder decoder_; | 102 HpackDecoder decoder_; |
| 108 test::HpackDecoderPeer decoder_peer_; | 103 test::HpackDecoderPeer decoder_peer_; |
| 109 }; | 104 }; |
| 110 | 105 |
| 111 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) { | 106 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) { |
| 112 // Strings under threshold are concatenated in the buffer. | 107 // Strings under threshold are concatenated in the buffer. |
| 113 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( | 108 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( |
| 114 0, "small string one", 16)); | 109 0, "small string one", 16)); |
| 115 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( | 110 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( |
| 116 0, "small string two", 16)); | 111 0, "small string two", 16)); |
| 117 // A string which would push the buffer over the threshold is refused. | 112 // A string which would push the buffer over the threshold is refused. |
| 118 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData( | 113 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData( |
| 119 0, "fails", kMaxDecodeBufferSize - 32 + 1)); | 114 0, "fails", kMaxDecodeBufferSize - 32 + 1)); |
| 120 | 115 |
| 121 EXPECT_EQ(decoder_peer_.headers_block_buffer(), | 116 EXPECT_EQ(decoder_peer_.headers_block_buffer(), |
| 122 "small string onesmall string two"); | 117 "small string onesmall string two"); |
| 123 } | 118 } |
| 124 | 119 |
| 125 TEST_F(HpackDecoderTest, HandleControlFrameHeadersComplete) { | 120 TEST_F(HpackDecoderTest, HandleControlFrameHeadersComplete) { |
| 126 // Decode a block which toggles two static headers into the reference set. | |
| 127 EXPECT_TRUE(DecodeHeaderBlock("\x82\x86")); | |
| 128 | |
| 129 decoder_peer_.set_cookie_value("foobar=baz"); | 121 decoder_peer_.set_cookie_value("foobar=baz"); |
| 130 | 122 |
| 131 // Headers in the reference set should be emitted. | |
| 132 // Incremental cookie buffer should be emitted and cleared. | 123 // Incremental cookie buffer should be emitted and cleared. |
| 133 decoder_.HandleControlFrameHeadersData(0, NULL, 0); | 124 decoder_.HandleControlFrameHeadersData(0, "\x82\x85", 2); |
| 134 decoder_.HandleControlFrameHeadersComplete(0); | 125 decoder_.HandleControlFrameHeadersComplete(0); |
| 135 | 126 |
| 136 EXPECT_THAT(decoded_block(), ElementsAre( | 127 EXPECT_THAT(decoded_block(), ElementsAre( |
| 137 Pair(":method", "GET"), | 128 Pair(":method", "GET"), |
| 138 Pair(":path", "/index.html"), | 129 Pair(":path", "/index.html"), |
| 139 Pair("cookie", "foobar=baz"))); | 130 Pair("cookie", "foobar=baz"))); |
| 140 EXPECT_EQ(decoder_peer_.cookie_value(), ""); | 131 EXPECT_EQ(decoder_peer_.cookie_value(), ""); |
| 141 } | 132 } |
| 142 | 133 |
| 143 TEST_F(HpackDecoderTest, HandleHeaderRepresentation) { | 134 TEST_F(HpackDecoderTest, HandleHeaderRepresentation) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 | 202 |
| 212 // Decoding an encoded name with an invalid index should fail. | 203 // Decoding an encoded name with an invalid index should fail. |
| 213 TEST_F(HpackDecoderTest, DecodeNextNameInvalidIndex) { | 204 TEST_F(HpackDecoderTest, DecodeNextNameInvalidIndex) { |
| 214 // One more than the number of static table entries. | 205 // One more than the number of static table entries. |
| 215 HpackInputStream input_stream(kLiteralBound, "\x3e"); | 206 HpackInputStream input_stream(kLiteralBound, "\x3e"); |
| 216 | 207 |
| 217 StringPiece string_piece; | 208 StringPiece string_piece; |
| 218 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); | 209 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); |
| 219 } | 210 } |
| 220 | 211 |
| 221 // Decoding an indexed header should toggle the index's presence in | 212 // Decoding indexed header fields should work. |
| 222 // the reference set, making a copy of static table entries if | |
| 223 // necessary. It should also emit the header if toggled on (and only | |
| 224 // as many times as it was toggled on). | |
| 225 TEST_F(HpackDecoderTest, IndexedHeaderBasic) { | 213 TEST_F(HpackDecoderTest, IndexedHeaderBasic) { |
| 226 // Toggle on static table entry #2 (and make a copy at index #1), | 214 // Reference static table entries #2 and #5. |
| 227 // then toggle on static table entry #5 (which is now #6 because of | |
| 228 // the copy of #2). | |
| 229 std::map<string, string> header_set1 = | 215 std::map<string, string> header_set1 = |
| 230 DecodeBlockExpectingSuccess("\x82\x86"); | 216 DecodeBlockExpectingSuccess("\x82\x85"); |
| 231 std::map<string, string> expected_header_set1; | 217 std::map<string, string> expected_header_set1; |
| 232 expected_header_set1[":method"] = "GET"; | 218 expected_header_set1[":method"] = "GET"; |
| 233 expected_header_set1[":path"] = "/index.html"; | 219 expected_header_set1[":path"] = "/index.html"; |
| 234 EXPECT_EQ(expected_header_set1, header_set1); | 220 EXPECT_EQ(expected_header_set1, header_set1); |
| 235 | 221 |
| 236 std::map<string, string> expected_header_set2; | 222 // Reference static table entry #2. |
| 237 expected_header_set2[":path"] = "/index.html"; | |
| 238 // Toggle off the copy of static table entry #5. | |
| 239 std::map<string, string> header_set2 = | 223 std::map<string, string> header_set2 = |
| 240 DecodeBlockExpectingSuccess("\x82"); | 224 DecodeBlockExpectingSuccess("\x82"); |
| 225 std::map<string, string> expected_header_set2; |
| 226 expected_header_set2[":method"] = "GET"; |
| 241 EXPECT_EQ(expected_header_set2, header_set2); | 227 EXPECT_EQ(expected_header_set2, header_set2); |
| 242 } | 228 } |
| 243 | 229 |
| 244 // Test a too-large indexed header. | 230 // Test a too-large indexed header. |
| 245 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { | 231 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { |
| 246 // High-bit set, and a prefix of one more than the number of static entries. | 232 // High-bit set, and a prefix of one more than the number of static entries. |
| 247 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1))); | 233 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1))); |
| 248 } | 234 } |
| 249 | 235 |
| 250 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) { | 236 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) { |
| 251 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 237 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 252 decoder_peer_.header_table()->max_size()); | 238 decoder_peer_.header_table()->max_size()); |
| 253 string input; | 239 string input; |
| 254 { | 240 { |
| 255 // Maximum-size update with size 126. Succeeds. | 241 // Maximum-size update with size 126. Succeeds. |
| 256 HpackOutputStream output_stream; | 242 HpackOutputStream output_stream; |
| 257 output_stream.AppendPrefix(kEncodingContextOpcode); | 243 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 258 output_stream.AppendPrefix(kEncodingContextNewMaximumSize); | |
| 259 output_stream.AppendUint32(126); | 244 output_stream.AppendUint32(126); |
| 260 | 245 |
| 261 output_stream.TakeString(&input); | 246 output_stream.TakeString(&input); |
| 262 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); | 247 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); |
| 263 EXPECT_EQ(126u, decoder_peer_.header_table()->max_size()); | 248 EXPECT_EQ(126u, decoder_peer_.header_table()->max_size()); |
| 264 } | 249 } |
| 265 { | 250 { |
| 266 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds. | 251 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds. |
| 267 HpackOutputStream output_stream; | 252 HpackOutputStream output_stream; |
| 268 output_stream.AppendPrefix(kEncodingContextOpcode); | 253 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 269 output_stream.AppendPrefix(kEncodingContextNewMaximumSize); | |
| 270 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting); | 254 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting); |
| 271 | 255 |
| 272 output_stream.TakeString(&input); | 256 output_stream.TakeString(&input); |
| 273 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); | 257 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); |
| 274 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 258 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 275 decoder_peer_.header_table()->max_size()); | 259 decoder_peer_.header_table()->max_size()); |
| 276 } | 260 } |
| 277 { | 261 { |
| 278 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails. | 262 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails. |
| 279 HpackOutputStream output_stream; | 263 HpackOutputStream output_stream; |
| 280 output_stream.AppendPrefix(kEncodingContextOpcode); | 264 output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode); |
| 281 output_stream.AppendPrefix(kEncodingContextNewMaximumSize); | |
| 282 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1); | 265 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1); |
| 283 | 266 |
| 284 output_stream.TakeString(&input); | 267 output_stream.TakeString(&input); |
| 285 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input))); | 268 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input))); |
| 286 EXPECT_EQ(kDefaultHeaderTableSizeSetting, | 269 EXPECT_EQ(kDefaultHeaderTableSizeSetting, |
| 287 decoder_peer_.header_table()->max_size()); | 270 decoder_peer_.header_table()->max_size()); |
| 288 } | 271 } |
| 289 } | 272 } |
| 290 | 273 |
| 291 TEST_F(HpackDecoderTest, ContextUpdateClearReferenceSet) { | |
| 292 // Toggle on a couple of headers. | |
| 293 std::map<string, string> header_set1 = | |
| 294 DecodeBlockExpectingSuccess("\x82\x86"); | |
| 295 std::map<string, string> expected_header_set1; | |
| 296 expected_header_set1[":method"] = "GET"; | |
| 297 expected_header_set1[":path"] = "/index.html"; | |
| 298 EXPECT_EQ(expected_header_set1, header_set1); | |
| 299 | |
| 300 // Send a context update to clear the reference set. | |
| 301 std::map<string, string> header_set2 = | |
| 302 DecodeBlockExpectingSuccess("\x30"); | |
| 303 std::map<string, string> expected_header_set2; | |
| 304 EXPECT_EQ(expected_header_set2, header_set2); | |
| 305 } | |
| 306 | |
| 307 // Decoding two valid encoded literal headers with no indexing should | 274 // Decoding two valid encoded literal headers with no indexing should |
| 308 // work. | 275 // work. |
| 309 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) { | 276 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) { |
| 310 // First header with indexed name, second header with string literal | 277 // First header with indexed name, second header with string literal |
| 311 // name. | 278 // name. |
| 312 const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2"; | 279 const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2"; |
| 313 std::map<string, string> header_set = | 280 std::map<string, string> header_set = |
| 314 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); | 281 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); |
| 315 | 282 |
| 316 std::map<string, string> expected_header_set; | 283 std::map<string, string> expected_header_set; |
| 317 expected_header_set[":path"] = "/sample/path"; | 284 expected_header_set[":path"] = "/sample/path"; |
| 318 expected_header_set[":path2"] = "/sample/path/2"; | 285 expected_header_set[":path2"] = "/sample/path/2"; |
| 319 EXPECT_EQ(expected_header_set, header_set); | 286 EXPECT_EQ(expected_header_set, header_set); |
| 320 } | 287 } |
| 321 | 288 |
| 322 // Decoding two valid encoded literal headers with incremental | 289 // Decoding two valid encoded literal headers with incremental |
| 323 // indexing and string literal names should work and add the headers | 290 // indexing and string literal names should work. |
| 324 // to the reference set. | |
| 325 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) { | 291 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) { |
| 326 const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2"; | 292 const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2"; |
| 327 std::map<string, string> header_set = | 293 std::map<string, string> header_set = |
| 328 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); | 294 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1)); |
| 329 | 295 |
| 330 std::map<string, string> expected_header_set; | 296 std::map<string, string> expected_header_set; |
| 331 expected_header_set[":path"] = "/sample/path"; | 297 expected_header_set[":path"] = "/sample/path"; |
| 332 expected_header_set[":path2"] = "/sample/path/2"; | 298 expected_header_set[":path2"] = "/sample/path/2"; |
| 333 EXPECT_EQ(expected_header_set, header_set); | 299 EXPECT_EQ(expected_header_set, header_set); |
| 334 | |
| 335 // Decoding an empty string should just return the reference set. | |
| 336 std::map<string, string> header_set2 = DecodeBlockExpectingSuccess(""); | |
| 337 EXPECT_EQ(expected_header_set, header_set2); | |
| 338 } | 300 } |
| 339 | 301 |
| 340 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) { | 302 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) { |
| 341 decoder_.ApplyHeaderTableSizeSetting(0); | 303 decoder_.ApplyHeaderTableSizeSetting(0); |
| 342 | 304 |
| 343 // Name is the last static index. Works. | 305 // Name is the last static index. Works. |
| 344 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo"))); | 306 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo"))); |
| 345 // Name is one beyond the last static index. Fails. | 307 // Name is one beyond the last static index. Fails. |
| 346 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo"))); | 308 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo"))); |
| 347 } | 309 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 371 expected_header_set[":authority"] = "www.example.com"; | 333 expected_header_set[":authority"] = "www.example.com"; |
| 372 | 334 |
| 373 string encoded_header_set; | 335 string encoded_header_set; |
| 374 EXPECT_TRUE(encoder.EncodeHeaderSet( | 336 EXPECT_TRUE(encoder.EncodeHeaderSet( |
| 375 expected_header_set, &encoded_header_set)); | 337 expected_header_set, &encoded_header_set)); |
| 376 | 338 |
| 377 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); | 339 EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set)); |
| 378 EXPECT_EQ(expected_header_set, decoded_block()); | 340 EXPECT_EQ(expected_header_set, decoded_block()); |
| 379 } | 341 } |
| 380 | 342 |
| 381 TEST_F(HpackDecoderTest, SectionD3RequestHuffmanExamples) { | 343 TEST_F(HpackDecoderTest, SectionD4RequestHuffmanExamples) { |
| 382 std::map<string, string> header_set; | 344 std::map<string, string> header_set; |
| 383 | 345 |
| 384 // 82 | == Indexed - Add == | 346 // 82 | == Indexed - Add == |
| 385 // | idx = 2 | 347 // | idx = 2 |
| 386 // | -> :method: GET | 348 // | -> :method: GET |
| 387 // 87 | == Indexed - Add == | |
| 388 // | idx = 7 | |
| 389 // | -> :scheme: http | |
| 390 // 86 | == Indexed - Add == | 349 // 86 | == Indexed - Add == |
| 391 // | idx = 6 | 350 // | idx = 6 |
| 351 // | -> :scheme: http |
| 352 // 84 | == Indexed - Add == |
| 353 // | idx = 4 |
| 392 // | -> :path: / | 354 // | -> :path: / |
| 393 // 44 | == Literal indexed == | 355 // 41 | == Literal indexed == |
| 394 // | Indexed name (idx = 4) | 356 // | Indexed name (idx = 1) |
| 395 // | :authority | 357 // | :authority |
| 396 // 8c | Literal value (len = 15) | 358 // 8c | Literal value (len = 15) |
| 397 // | Huffman encoded: | 359 // | Huffman encoded: |
| 398 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... | 360 // f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... |
| 399 // | Decoded: | 361 // | Decoded: |
| 400 // | www.example.com | 362 // | www.example.com |
| 401 // | -> :authority: www.example.com | 363 // | -> :authority: www.example.com |
| 402 string first = a2b_hex("828786448cf1e3c2e5f23a6ba0ab90f4" | 364 string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4" |
| 403 "ff"); | 365 "ff"); |
| 404 header_set = DecodeBlockExpectingSuccess(first); | 366 header_set = DecodeBlockExpectingSuccess(first); |
| 405 | 367 |
| 406 EXPECT_THAT(header_set, ElementsAre( | 368 EXPECT_THAT(header_set, ElementsAre( |
| 407 Pair(":authority", "www.example.com"), | 369 Pair(":authority", "www.example.com"), |
| 408 Pair(":method", "GET"), | 370 Pair(":method", "GET"), |
| 409 Pair(":path", "/"), | 371 Pair(":path", "/"), |
| 410 Pair(":scheme", "http"))); | 372 Pair(":scheme", "http"))); |
| 411 | 373 |
| 412 expectEntry(1, 57, ":authority", "www.example.com"); | 374 expectEntry(62, 57, ":authority", "www.example.com"); |
| 413 expectEntry(2, 38, ":path", "/"); | 375 EXPECT_EQ(57u, decoder_peer_.header_table()->size()); |
| 414 expectEntry(3, 43, ":scheme", "http"); | |
| 415 expectEntry(4, 42, ":method", "GET"); | |
| 416 expectStaticEntry(5); | |
| 417 EXPECT_EQ(180u, decoder_peer_.header_table()->size()); | |
| 418 | 376 |
| 419 // 5c | == Literal indexed == | 377 // 82 | == Indexed - Add == |
| 420 // | Indexed name (idx = 28) | 378 // | idx = 2 |
| 379 // | -> :method: GET |
| 380 // 86 | == Indexed - Add == |
| 381 // | idx = 6 |
| 382 // | -> :scheme: http |
| 383 // 84 | == Indexed - Add == |
| 384 // | idx = 4 |
| 385 // | -> :path: / |
| 386 // be | == Indexed - Add == |
| 387 // | idx = 62 |
| 388 // | -> :authority: www.example.com |
| 389 // 58 | == Literal indexed == |
| 390 // | Indexed name (idx = 24) |
| 421 // | cache-control | 391 // | cache-control |
| 422 // 86 | Literal value (len = 8) | 392 // 86 | Literal value (len = 8) |
| 423 // | Huffman encoded: | 393 // | Huffman encoded: |
| 424 // a8eb 1064 9cbf | ...d.. | 394 // a8eb 1064 9cbf | ...d.. |
| 425 // | Decoded: | 395 // | Decoded: |
| 426 // | no-cache | 396 // | no-cache |
| 427 // | -> cache-control: no-cache | 397 // | -> cache-control: no-cache |
| 428 string second = a2b_hex("5c86a8eb10649cbf"); | 398 |
| 399 string second = a2b_hex("828684be5886a8eb10649cbf"); |
| 429 header_set = DecodeBlockExpectingSuccess(second); | 400 header_set = DecodeBlockExpectingSuccess(second); |
| 430 | 401 |
| 431 EXPECT_THAT(header_set, ElementsAre( | 402 EXPECT_THAT(header_set, ElementsAre( |
| 432 Pair(":authority", "www.example.com"), | 403 Pair(":authority", "www.example.com"), |
| 433 Pair(":method", "GET"), | 404 Pair(":method", "GET"), |
| 434 Pair(":path", "/"), | 405 Pair(":path", "/"), |
| 435 Pair(":scheme", "http"), | 406 Pair(":scheme", "http"), |
| 436 Pair("cache-control", "no-cache"))); | 407 Pair("cache-control", "no-cache"))); |
| 437 | 408 |
| 438 expectEntry(1, 53, "cache-control", "no-cache"); | 409 expectEntry(62, 53, "cache-control", "no-cache"); |
| 439 expectEntry(2, 57, ":authority", "www.example.com"); | 410 expectEntry(63, 57, ":authority", "www.example.com"); |
| 440 expectEntry(3, 38, ":path", "/"); | 411 EXPECT_EQ(110u, decoder_peer_.header_table()->size()); |
| 441 expectEntry(4, 43, ":scheme", "http"); | |
| 442 expectEntry(5, 42, ":method", "GET"); | |
| 443 expectStaticEntry(6); | |
| 444 EXPECT_EQ(233u, decoder_peer_.header_table()->size()); | |
| 445 | 412 |
| 446 // 30 | == Empty reference set == | 413 // 82 | == Indexed - Add == |
| 447 // | idx = 0 | 414 // | idx = 2 |
| 448 // | flag = 1 | 415 // | -> :method: GET |
| 416 // 87 | == Indexed - Add == |
| 417 // | idx = 7 |
| 418 // | -> :scheme: https |
| 449 // 85 | == Indexed - Add == | 419 // 85 | == Indexed - Add == |
| 450 // | idx = 5 | 420 // | idx = 5 |
| 451 // | -> :method: GET | |
| 452 // 8c | == Indexed - Add == | |
| 453 // | idx = 12 | |
| 454 // | -> :scheme: https | |
| 455 // 8b | == Indexed - Add == | |
| 456 // | idx = 11 | |
| 457 // | -> :path: /index.html | 421 // | -> :path: /index.html |
| 458 // 84 | == Indexed - Add == | 422 // bf | == Indexed - Add == |
| 459 // | idx = 4 | 423 // | idx = 63 |
| 460 // | -> :authority: www.example.com | 424 // | -> :authority: www.example.com |
| 461 // 40 | == Literal indexed == | 425 // 40 | == Literal indexed == |
| 462 // 88 | Literal name (len = 10) | 426 // 88 | Literal name (len = 10) |
| 463 // | Huffman encoded: | 427 // | Huffman encoded: |
| 464 // 25a8 49e9 5ba9 7d7f | %.I.[.}. | 428 // 25a8 49e9 5ba9 7d7f | %.I.[.}. |
| 465 // | Decoded: | 429 // | Decoded: |
| 466 // | custom-key | 430 // | custom-key |
| 467 // 89 | Literal value (len = 12) | 431 // 89 | Literal value (len = 12) |
| 468 // | Huffman encoded: | 432 // | Huffman encoded: |
| 469 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... | 433 // 25a8 49e9 5bb8 e8b4 bf | %.I.[.... |
| 470 // | Decoded: | 434 // | Decoded: |
| 471 // | custom-value | 435 // | custom-value |
| 472 // | -> custom-key: custom-value | 436 // | -> custom-key: custom-value |
| 473 string third = a2b_hex("30858c8b84408825a849e95ba97d7f89" | 437 string third = a2b_hex("828785bf408825a849e95ba97d7f89" |
| 474 "25a849e95bb8e8b4bf"); | 438 "25a849e95bb8e8b4bf"); |
| 475 header_set = DecodeBlockExpectingSuccess(third); | 439 header_set = DecodeBlockExpectingSuccess(third); |
| 476 | 440 |
| 477 EXPECT_THAT(header_set, ElementsAre( | 441 EXPECT_THAT(header_set, ElementsAre( |
| 478 Pair(":authority", "www.example.com"), | 442 Pair(":authority", "www.example.com"), |
| 479 Pair(":method", "GET"), | 443 Pair(":method", "GET"), |
| 480 Pair(":path", "/index.html"), | 444 Pair(":path", "/index.html"), |
| 481 Pair(":scheme", "https"), | 445 Pair(":scheme", "https"), |
| 482 Pair("custom-key", "custom-value"))); | 446 Pair("custom-key", "custom-value"))); |
| 483 | 447 |
| 484 expectEntry(1, 54, "custom-key", "custom-value"); | 448 expectEntry(62, 54, "custom-key", "custom-value"); |
| 485 expectEntry(2, 48, ":path", "/index.html"); | 449 expectEntry(63, 53, "cache-control", "no-cache"); |
| 486 expectEntry(3, 44, ":scheme", "https"); | 450 expectEntry(64, 57, ":authority", "www.example.com"); |
| 487 expectEntry(4, 53, "cache-control", "no-cache"); | 451 EXPECT_EQ(164u, decoder_peer_.header_table()->size()); |
| 488 expectEntry(5, 57, ":authority", "www.example.com"); | |
| 489 expectEntry(6, 38, ":path", "/"); | |
| 490 expectEntry(7, 43, ":scheme", "http"); | |
| 491 expectEntry(8, 42, ":method", "GET"); | |
| 492 expectStaticEntry(9); | |
| 493 EXPECT_EQ(379u, decoder_peer_.header_table()->size()); | |
| 494 } | 452 } |
| 495 | 453 |
| 496 TEST_F(HpackDecoderTest, SectionD5ResponseHuffmanExamples) { | 454 TEST_F(HpackDecoderTest, SectionD6ResponseHuffmanExamples) { |
| 497 std::map<string, string> header_set; | 455 std::map<string, string> header_set; |
| 498 decoder_.ApplyHeaderTableSizeSetting(256); | 456 decoder_.ApplyHeaderTableSizeSetting(256); |
| 499 | 457 |
| 500 // 48 | == Literal indexed == | 458 // 48 | == Literal indexed == |
| 501 // | Indexed name (idx = 8) | 459 // | Indexed name (idx = 8) |
| 502 // | :status | 460 // | :status |
| 503 // 82 | Literal value (len = 3) | 461 // 82 | Literal value (len = 3) |
| 504 // | Huffman encoded: | 462 // | Huffman encoded: |
| 505 // 6402 | d. | 463 // 6402 | d. |
| 506 // | Decoded: | 464 // | Decoded: |
| 507 // | 302 | 465 // | 302 |
| 508 // | -> :status: 302 | 466 // | -> :status: 302 |
| 509 // 59 | == Literal indexed == | 467 // 58 | == Literal indexed == |
| 510 // | Indexed name (idx = 25) | 468 // | Indexed name (idx = 24) |
| 511 // | cache-control | 469 // | cache-control |
| 512 // 85 | Literal value (len = 7) | 470 // 85 | Literal value (len = 7) |
| 513 // | Huffman encoded: | 471 // | Huffman encoded: |
| 514 // aec3 771a 4b | ..w.K | 472 // aec3 771a 4b | ..w.K |
| 515 // | Decoded: | 473 // | Decoded: |
| 516 // | private | 474 // | private |
| 517 // | -> cache-control: private | 475 // | -> cache-control: private |
| 518 // 63 | == Literal indexed == | 476 // 61 | == Literal indexed == |
| 519 // | Indexed name (idx = 35) | 477 // | Indexed name (idx = 33) |
| 520 // | date | 478 // | date |
| 521 // 96 | Literal value (len = 29) | 479 // 96 | Literal value (len = 29) |
| 522 // | Huffman encoded: | 480 // | Huffman encoded: |
| 523 // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f | 481 // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f |
| 524 // e082 a62d 1bff | ...-.. | 482 // e082 a62d 1bff | ...-.. |
| 525 // | Decoded: | 483 // | Decoded: |
| 526 // | Mon, 21 Oct 2013 20:13:21 | 484 // | Mon, 21 Oct 2013 20:13:21 |
| 527 // | GMT | 485 // | GMT |
| 528 // | -> date: Mon, 21 Oct 2013 | 486 // | -> date: Mon, 21 Oct 2013 |
| 529 // | 20:13:21 GMT | 487 // | 20:13:21 GMT |
| 530 // 71 | == Literal indexed == | 488 // 6e | == Literal indexed == |
| 531 // | Indexed name (idx = 49) | 489 // | Indexed name (idx = 46) |
| 532 // | location | 490 // | location |
| 533 // 91 | Literal value (len = 23) | 491 // 91 | Literal value (len = 23) |
| 534 // | Huffman encoded: | 492 // | Huffman encoded: |
| 535 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C | 493 // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C |
| 536 // d3 | . | 494 // d3 | . |
| 537 // | Decoded: | 495 // | Decoded: |
| 538 // | https://www.example.com | 496 // | https://www.example.com |
| 539 // | -> location: https://www.e | 497 // | -> location: https://www.e |
| 540 // | xample.com | 498 // | xample.com |
| 541 string first = a2b_hex("488264025985aec3771a4b6396d07abe" | 499 |
| 500 string first = a2b_hex("488264025885aec3771a4b6196d07abe" |
| 542 "941054d444a8200595040b8166e082a6" | 501 "941054d444a8200595040b8166e082a6" |
| 543 "2d1bff71919d29ad171863c78f0b97c8" | 502 "2d1bff6e919d29ad171863c78f0b97c8" |
| 544 "e9ae82ae43d3"); | 503 "e9ae82ae43d3"); |
| 545 header_set = DecodeBlockExpectingSuccess(first); | 504 header_set = DecodeBlockExpectingSuccess(first); |
| 546 | 505 |
| 547 EXPECT_THAT(header_set, ElementsAre( | 506 EXPECT_THAT(header_set, ElementsAre( |
| 548 Pair(":status", "302"), | 507 Pair(":status", "302"), |
| 549 Pair("cache-control", "private"), | 508 Pair("cache-control", "private"), |
| 550 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), | 509 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), |
| 551 Pair("location", "https://www.example.com"))); | 510 Pair("location", "https://www.example.com"))); |
| 552 | 511 |
| 553 expectEntry(1, 63, "location", "https://www.example.com"); | 512 expectEntry(62, 63, "location", "https://www.example.com"); |
| 554 expectEntry(2, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT"); | 513 expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT"); |
| 555 expectEntry(3, 52, "cache-control", "private"); | 514 expectEntry(64, 52, "cache-control", "private"); |
| 556 expectEntry(4, 42, ":status", "302"); | 515 expectEntry(65, 42, ":status", "302"); |
| 557 expectStaticEntry(5); | |
| 558 EXPECT_EQ(222u, decoder_peer_.header_table()->size()); | 516 EXPECT_EQ(222u, decoder_peer_.header_table()->size()); |
| 559 | 517 |
| 560 // 8c | == Indexed - Add == | 518 // 48 | == Literal indexed == |
| 561 // | idx = 12 | 519 // | Indexed name (idx = 8) |
| 520 // | :status |
| 521 // 83 | Literal value (len = 3) |
| 522 // | Huffman encoded: |
| 523 // 640e ff | d.. |
| 524 // | Decoded: |
| 525 // | 307 |
| 562 // | - evict: :status: 302 | 526 // | - evict: :status: 302 |
| 563 // | -> :status: 200 | 527 // | -> :status: 307 |
| 564 string second = a2b_hex("8c"); | 528 // c1 | == Indexed - Add == |
| 529 // | idx = 65 |
| 530 // | -> cache-control: private |
| 531 // c0 | == Indexed - Add == |
| 532 // | idx = 64 |
| 533 // | -> date: Mon, 21 Oct 2013 |
| 534 // | 20:13:21 GMT |
| 535 // bf | == Indexed - Add == |
| 536 // | idx = 63 |
| 537 // | -> location: |
| 538 // | https://www.example.com |
| 539 string second = a2b_hex("4883640effc1c0bf"); |
| 565 header_set = DecodeBlockExpectingSuccess(second); | 540 header_set = DecodeBlockExpectingSuccess(second); |
| 566 | 541 |
| 567 EXPECT_THAT(header_set, ElementsAre( | 542 EXPECT_THAT(header_set, ElementsAre( |
| 568 Pair(":status", "200"), | 543 Pair(":status", "307"), |
| 569 Pair("cache-control", "private"), | 544 Pair("cache-control", "private"), |
| 570 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), | 545 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), |
| 571 Pair("location", "https://www.example.com"))); | 546 Pair("location", "https://www.example.com"))); |
| 572 | 547 |
| 573 expectEntry(1, 42, ":status", "200"); | 548 expectEntry(62, 42, ":status", "307"); |
| 574 expectEntry(2, 63, "location", "https://www.example.com"); | 549 expectEntry(63, 63, "location", "https://www.example.com"); |
| 575 expectEntry(3, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT"); | 550 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT"); |
| 576 expectEntry(4, 52, "cache-control", "private"); | 551 expectEntry(65, 52, "cache-control", "private"); |
| 577 expectStaticEntry(5); | |
| 578 EXPECT_EQ(222u, decoder_peer_.header_table()->size()); | 552 EXPECT_EQ(222u, decoder_peer_.header_table()->size()); |
| 579 | 553 |
| 580 // 84 | == Indexed - Remove == | 554 // 88 | == Indexed - Add == |
| 581 // | idx = 4 | 555 // | idx = 8 |
| 556 // | -> :status: 200 |
| 557 // c1 | == Indexed - Add == |
| 558 // | idx = 65 |
| 582 // | -> cache-control: private | 559 // | -> cache-control: private |
| 583 // 84 | == Indexed - Add == | 560 // 61 | == Literal indexed == |
| 584 // | idx = 4 | 561 // | Indexed name (idx = 33) |
| 585 // | -> cache-control: private | |
| 586 // 43 | == Literal indexed == | |
| 587 // | Indexed name (idx = 3) | |
| 588 // | date | 562 // | date |
| 589 // 96 | Literal value (len = 29) | 563 // 96 | Literal value (len = 22) |
| 590 // | Huffman encoded: | 564 // | Huffman encoded: |
| 591 // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f | 565 // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f |
| 592 // e084 a62d 1bff | ...-.. | 566 // e084 a62d 1bff | ...-.. |
| 593 // | Decoded: | 567 // | Decoded: |
| 594 // | Mon, 21 Oct 2013 20:13:22 | 568 // | Mon, 21 Oct 2013 20:13:22 |
| 595 // | GMT | 569 // | GMT |
| 596 // | - evict: cache-control: pr | 570 // | - evict: cache-control: |
| 597 // | ivate | 571 // | private |
| 598 // | -> date: Mon, 21 Oct 2013 | 572 // | -> date: Mon, 21 Oct 2013 |
| 599 // | 20:13:22 GMT | 573 // | 20:13:22 GMT |
| 600 // 5e | == Literal indexed == | 574 // c0 | == Indexed - Add == |
| 601 // | Indexed name (idx = 30) | 575 // | idx = 64 |
| 576 // | -> location: |
| 577 // | https://www.example.com |
| 578 // 5a | == Literal indexed == |
| 579 // | Indexed name (idx = 26) |
| 602 // | content-encoding | 580 // | content-encoding |
| 603 // 83 | Literal value (len = 4) | 581 // 83 | Literal value (len = 3) |
| 604 // | Huffman encoded: | 582 // | Huffman encoded: |
| 605 // 9bd9 ab | ... | 583 // 9bd9 ab | ... |
| 606 // | Decoded: | 584 // | Decoded: |
| 607 // | gzip | 585 // | gzip |
| 608 // | - evict: date: Mon, 21 Oct | 586 // | - evict: date: Mon, 21 Oct |
| 609 // | 2013 20:13:21 GMT | 587 // | 2013 20:13:21 GMT |
| 610 // | -> content-encoding: gzip | 588 // | -> content-encoding: gzip |
| 611 // 84 | == Indexed - Remove == | 589 // 77 | == Literal indexed == |
| 612 // | idx = 4 | 590 // | Indexed name (idx = 55) |
| 613 // | -> location: https://www.e | |
| 614 // | xample.com | |
| 615 // 84 | == Indexed - Add == | |
| 616 // | idx = 4 | |
| 617 // | -> location: https://www.e | |
| 618 // | xample.com | |
| 619 // 83 | == Indexed - Remove == | |
| 620 // | idx = 3 | |
| 621 // | -> :status: 200 | |
| 622 // 83 | == Indexed - Add == | |
| 623 // | idx = 3 | |
| 624 // | -> :status: 200 | |
| 625 // 7b | == Literal indexed == | |
| 626 // | Indexed name (idx = 59) | |
| 627 // | set-cookie | 591 // | set-cookie |
| 628 // ad | Literal value (len = 56) | 592 // ad | Literal value (len = 45) |
| 629 // | Huffman encoded: | 593 // | Huffman encoded: |
| 630 // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9` | 594 // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9` |
| 631 // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)... | 595 // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)... |
| 632 // 3160 65c0 03ed 4ee5 b106 3d50 07 | 1`e...N...=P. | 596 // 3160 65c0 03ed 4ee5 b106 3d50 07 | 1`e...N...=P. |
| 633 // | Decoded: | 597 // | Decoded: |
| 634 // | foo=ASDJKHQKBZXOQWEOPIUAXQ | 598 // | foo=ASDJKHQKBZXOQWEOPIUAXQ |
| 635 // | WEOIU; max-age=3600; versi | 599 // | WEOIU; max-age=3600; versi |
| 636 // | on=1 | 600 // | on=1 |
| 637 // | - evict: location: https:/ | 601 // | - evict: location: |
| 638 // | /www.example.com | 602 // | https://www.example.com |
| 639 // | - evict: :status: 200 | 603 // | - evict: :status: 307 |
| 640 // | -> set-cookie: foo=ASDJKHQ | 604 // | -> set-cookie: foo=ASDJKHQ |
| 641 // | KBZXOQWEOPIUAXQWEOIU; ma | 605 // | KBZXOQWEOPIUAXQWEOIU; |
| 642 // | x-age=3600; version=1 | 606 // | max-age=3600; version=1 |
| 643 string third = a2b_hex("84844396d07abe941054d444a8200595" | 607 string third = a2b_hex("88c16196d07abe941054d444a8200595" |
| 644 "040b8166e084a62d1bff5e839bd9ab84" | 608 "040b8166e084a62d1bffc05a839bd9ab" |
| 645 "8483837bad94e7821dd7f2e6c7b335df" | 609 "77ad94e7821dd7f2e6c7b335dfdfcd5b" |
| 646 "dfcd5b3960d5af27087f3672c1ab270f" | 610 "3960d5af27087f3672c1ab270fb5291f" |
| 647 "b5291f9587316065c003ed4ee5b1063d" | 611 "9587316065c003ed4ee5b1063d5007"); |
| 648 "5007"); | |
| 649 header_set = DecodeBlockExpectingSuccess(third); | 612 header_set = DecodeBlockExpectingSuccess(third); |
| 650 | 613 |
| 651 EXPECT_THAT(header_set, ElementsAre( | 614 EXPECT_THAT(header_set, ElementsAre( |
| 652 Pair(":status", "200"), | 615 Pair(":status", "200"), |
| 653 Pair("cache-control", "private"), | 616 Pair("cache-control", "private"), |
| 654 Pair("content-encoding", "gzip"), | 617 Pair("content-encoding", "gzip"), |
| 655 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), | 618 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), |
| 656 Pair("location", "https://www.example.com"), | 619 Pair("location", "https://www.example.com"), |
| 657 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 620 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
| 658 " max-age=3600; version=1"))); | 621 " max-age=3600; version=1"))); |
| 659 | 622 |
| 660 expectEntry(1, 98, "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" | 623 expectEntry(62, 98, "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" |
| 661 " max-age=3600; version=1"); | 624 " max-age=3600; version=1"); |
| 662 expectEntry(2, 52, "content-encoding", "gzip"); | 625 expectEntry(63, 52, "content-encoding", "gzip"); |
| 663 expectEntry(3, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); | 626 expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT"); |
| 664 expectStaticEntry(4); | |
| 665 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); | 627 EXPECT_EQ(215u, decoder_peer_.header_table()->size()); |
| 666 } | 628 } |
| 667 | 629 |
| 668 } // namespace | 630 } // namespace |
| 669 | 631 |
| 670 } // namespace net | 632 } // namespace net |
| OLD | NEW |