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