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