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 |