Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: net/spdy/hpack_decoder_test.cc

Issue 269183008: HPACK changes required for specification draft '07 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Write '07 examples as a new file name. Remove previous one. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
13 #include "net/spdy/hpack_encoder.h" 14 #include "net/spdy/hpack_encoder.h"
14 #include "net/spdy/hpack_input_stream.h" 15 #include "net/spdy/hpack_input_stream.h"
15 #include "net/spdy/hpack_output_stream.h" 16 #include "net/spdy/hpack_output_stream.h"
16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
18 19
19 namespace net { 20 namespace net {
20 21
21 namespace test { 22 namespace test {
22 23
23 using base::StringPiece; 24 using base::StringPiece;
24 using std::string; 25 using std::string;
25 26
26 class HpackDecoderPeer { 27 class HpackDecoderPeer {
27 public: 28 public:
28 explicit HpackDecoderPeer(HpackDecoder* decoder) 29 explicit HpackDecoderPeer(HpackDecoder* decoder)
29 : decoder_(decoder) {} 30 : decoder_(decoder) {}
30 31
31 void HandleHeaderRepresentation(StringPiece name, StringPiece value) { 32 void HandleHeaderRepresentation(StringPiece name, StringPiece value) {
32 decoder_->HandleHeaderRepresentation(name, value); 33 decoder_->HandleHeaderRepresentation(name, value);
33 } 34 }
34 bool DecodeNextName(HpackInputStream* in, StringPiece* out) { 35 bool DecodeNextName(HpackInputStream* in, StringPiece* out) {
35 return decoder_->DecodeNextName(in, out); 36 return decoder_->DecodeNextName(in, out);
36 } 37 }
37 const HpackHeaderTable& header_table() { 38 HpackHeaderTable* header_table() {
38 return decoder_->header_table_; 39 return &decoder_->header_table_;
39 }
40 void set_cookie_name(string name) {
41 decoder_->cookie_name_ = name;
42 }
43 string cookie_name() {
44 return decoder_->cookie_name_;
45 } 40 }
46 void set_cookie_value(string value) { 41 void set_cookie_value(string value) {
47 decoder_->cookie_value_ = value; 42 decoder_->cookie_value_ = value;
48 } 43 }
49 string cookie_value() { 44 string cookie_value() {
50 return decoder_->cookie_value_; 45 return decoder_->cookie_value_;
51 } 46 }
52 const std::map<string, string>& decoded_block() const { 47 const std::map<string, string>& decoded_block() const {
53 return decoder_->decoded_block_; 48 return decoder_->decoded_block_;
54 } 49 }
(...skipping 20 matching lines...) Expand all
75 class HpackDecoderTest : public ::testing::Test { 70 class HpackDecoderTest : public ::testing::Test {
76 protected: 71 protected:
77 HpackDecoderTest() 72 HpackDecoderTest()
78 : decoder_(ObtainHpackHuffmanTable()), 73 : decoder_(ObtainHpackHuffmanTable()),
79 decoder_peer_(&decoder_) {} 74 decoder_peer_(&decoder_) {}
80 75
81 bool DecodeHeaderBlock(StringPiece str) { 76 bool DecodeHeaderBlock(StringPiece str) {
82 return decoder_.HandleControlFrameHeadersData(0, str.data(), str.size()) && 77 return decoder_.HandleControlFrameHeadersData(0, str.data(), str.size()) &&
83 decoder_.HandleControlFrameHeadersComplete(0); 78 decoder_.HandleControlFrameHeadersComplete(0);
84 } 79 }
80
85 const std::map<string, string>& decoded_block() const { 81 const std::map<string, string>& decoded_block() const {
86 // TODO(jgraettinger): HpackDecoderTest should implement 82 // TODO(jgraettinger): HpackDecoderTest should implement
87 // SpdyHeadersHandlerInterface, and collect headers for examination. 83 // SpdyHeadersHandlerInterface, and collect headers for examination.
88 return decoder_peer_.decoded_block(); 84 return decoder_peer_.decoded_block();
89 } 85 }
90 // TODO(jgraettinger): Eliminate uses of this in tests below. Prefer 86
91 // DecodeHeaderBlock(). 87 const std::map<string, string>& DecodeBlockExpectingSuccess(StringPiece str) {
92 const std::map<string, string>& DecodeUniqueHeaderSet(StringPiece str) {
93 EXPECT_TRUE(DecodeHeaderBlock(str)); 88 EXPECT_TRUE(DecodeHeaderBlock(str));
94 return decoded_block(); 89 return decoded_block();
95 } 90 }
96 91
92 void expectEntry(size_t index, size_t size, const string& name,
93 const string& value) {
94 HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index);
95 EXPECT_EQ(name, entry->name()) << "index " << index;
96 EXPECT_EQ(value, entry->value());
97 EXPECT_EQ(size, entry->Size());
98 EXPECT_EQ(index, entry->Index());
99 }
100
101 void expectStaticEntry(size_t index) {
102 HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index);
103 EXPECT_TRUE(entry->IsStatic()) << "index " << index;
104 }
105
106 string a2b_hex(const char* hex_data) {
107 std::vector<uint8> output;
108 string result;
109 if (base::HexStringToBytes(hex_data, &output))
110 result.assign(reinterpret_cast<const char*>(&output[0]), output.size());
111 return result;
112 }
113
97 HpackDecoder decoder_; 114 HpackDecoder decoder_;
98 test::HpackDecoderPeer decoder_peer_; 115 test::HpackDecoderPeer decoder_peer_;
99 }; 116 };
100 117
101 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) { 118 TEST_F(HpackDecoderTest, HandleControlFrameHeadersData) {
102 // Strings under threshold are concatenated in the buffer. 119 // Strings under threshold are concatenated in the buffer.
103 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( 120 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(
104 0, "small string one", 16)); 121 0, "small string one", 16));
105 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData( 122 EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(
106 0, "small string two", 16)); 123 0, "small string two", 16));
107 // A string which would push the buffer over the threshold is refused. 124 // A string which would push the buffer over the threshold is refused.
108 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData( 125 EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(
109 0, "fails", kMaxDecodeBufferSize - 32 + 1)); 126 0, "fails", kMaxDecodeBufferSize - 32 + 1));
110 127
111 EXPECT_EQ(decoder_peer_.headers_block_buffer(), 128 EXPECT_EQ(decoder_peer_.headers_block_buffer(),
112 "small string onesmall string two"); 129 "small string onesmall string two");
113 } 130 }
114 131
115 TEST_F(HpackDecoderTest, HandleControlFrameHeadersComplete) { 132 TEST_F(HpackDecoderTest, HandleControlFrameHeadersComplete) {
116 // Decode a block which toggles two static headers into the reference set. 133 // Decode a block which toggles two static headers into the reference set.
117 EXPECT_TRUE(DecodeHeaderBlock("\x82\x86")); 134 EXPECT_TRUE(DecodeHeaderBlock("\x82\x86"));
118 135
119 decoder_peer_.set_cookie_name("CooKie");
120 decoder_peer_.set_cookie_value("foobar=baz"); 136 decoder_peer_.set_cookie_value("foobar=baz");
121 137
122 // Headers in the reference set should be emitted. 138 // Headers in the reference set should be emitted.
123 // Incremental cookie buffer should be emitted and cleared. 139 // Incremental cookie buffer should be emitted and cleared.
124 decoder_.HandleControlFrameHeadersData(0, NULL, 0); 140 decoder_.HandleControlFrameHeadersData(0, NULL, 0);
125 decoder_.HandleControlFrameHeadersComplete(0); 141 decoder_.HandleControlFrameHeadersComplete(0);
126 142
127 EXPECT_THAT(decoded_block(), ElementsAre( 143 EXPECT_THAT(decoded_block(), ElementsAre(
128 Pair(":method", "GET"), 144 Pair(":method", "GET"),
129 Pair(":path", "/index.html"), 145 Pair(":path", "/index.html"),
130 Pair("CooKie", "foobar=baz"))); 146 Pair("cookie", "foobar=baz")));
131
132 EXPECT_EQ(decoder_peer_.cookie_name(), "");
133 EXPECT_EQ(decoder_peer_.cookie_value(), ""); 147 EXPECT_EQ(decoder_peer_.cookie_value(), "");
134 } 148 }
135 149
136 TEST_F(HpackDecoderTest, HandleHeaderRepresentation) { 150 TEST_F(HpackDecoderTest, HandleHeaderRepresentation) {
137 // Casing of first Cookie is retained, but all instances are joined. 151 // All cookie crumbs are joined.
138 decoder_peer_.HandleHeaderRepresentation("cOOkie", " part 1"); 152 decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
139 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 "); 153 decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
140 decoder_peer_.HandleHeaderRepresentation("cookie", "part3"); 154 decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
141 155
142 // Already-delimited headers are passed through. 156 // Already-delimited headers are passed through.
143 decoder_peer_.HandleHeaderRepresentation("passed-through", 157 decoder_peer_.HandleHeaderRepresentation("passed-through",
144 string("foo\0baz", 7)); 158 string("foo\0baz", 7));
145 159
146 // Other headers are joined on \0. Case matters. 160 // Other headers are joined on \0. Case matters.
147 decoder_peer_.HandleHeaderRepresentation("joined", "not joined"); 161 decoder_peer_.HandleHeaderRepresentation("joined", "not joined");
148 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1"); 162 decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
149 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2"); 163 decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
150 164
151 // Empty headers remain empty. 165 // Empty headers remain empty.
152 decoder_peer_.HandleHeaderRepresentation("empty", ""); 166 decoder_peer_.HandleHeaderRepresentation("empty", "");
153 167
154 // Joined empty headers work as expected. 168 // Joined empty headers work as expected.
155 decoder_peer_.HandleHeaderRepresentation("empty-joined", ""); 169 decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
156 decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo"); 170 decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
157 decoder_peer_.HandleHeaderRepresentation("empty-joined", ""); 171 decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
158 decoder_peer_.HandleHeaderRepresentation("empty-joined", ""); 172 decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
159 173
160 // Non-contiguous cookie crumb. 174 // Non-contiguous cookie crumb.
161 decoder_peer_.HandleHeaderRepresentation("Cookie", " fin!"); 175 decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
162 176
163 // Finish and emit all headers. 177 // Finish and emit all headers.
164 decoder_.HandleControlFrameHeadersComplete(0); 178 decoder_.HandleControlFrameHeadersComplete(0);
165 179
166 EXPECT_THAT(decoded_block(), ElementsAre( 180 EXPECT_THAT(decoded_block(), ElementsAre(
167 Pair("cOOkie", " part 1; part 2 ; part3; fin!"), 181 Pair("cookie", " part 1; part 2 ; part3; fin!"),
168 Pair("empty", ""), 182 Pair("empty", ""),
169 Pair("empty-joined", string("\0foo\0\0", 6)), 183 Pair("empty-joined", string("\0foo\0\0", 6)),
170 Pair("joineD", string("value 1\0value 2", 15)), 184 Pair("joineD", string("value 1\0value 2", 15)),
171 Pair("joined", "not joined"), 185 Pair("joined", "not joined"),
172 Pair("passed-through", string("foo\0baz", 7)))); 186 Pair("passed-through", string("foo\0baz", 7))));
173 } 187 }
174 188
175 // Decoding an encoded name with a valid string literal should work. 189 // Decoding an encoded name with a valid string literal should work.
176 TEST_F(HpackDecoderTest, DecodeNextNameLiteral) { 190 TEST_F(HpackDecoderTest, DecodeNextNameLiteral) {
177 HpackInputStream input_stream(kLiteralBound, StringPiece("\x00\x04name", 6)); 191 HpackInputStream input_stream(kLiteralBound, StringPiece("\x00\x04name", 6));
178 192
179 StringPiece string_piece; 193 StringPiece string_piece;
180 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); 194 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
181 EXPECT_EQ("name", string_piece); 195 EXPECT_EQ("name", string_piece);
182 EXPECT_FALSE(input_stream.HasMoreData()); 196 EXPECT_FALSE(input_stream.HasMoreData());
183 } 197 }
184 198
185 TEST_F(HpackDecoderTest, DecodeNextNameLiteralWithHuffmanEncoding) { 199 TEST_F(HpackDecoderTest, DecodeNextNameLiteralWithHuffmanEncoding) {
186 char input[] = "\x00\x88\x4e\xb0\x8b\x74\x97\x90\xfa\x7f"; 200 string input = a2b_hex("0088571c5cdb737b2faf");
187 StringPiece foo(input, arraysize(input) - 1); 201 HpackInputStream input_stream(kLiteralBound, input);
188 HpackInputStream input_stream(kLiteralBound, foo);
189 202
190 StringPiece string_piece; 203 StringPiece string_piece;
191 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); 204 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
192 EXPECT_EQ("custom-key", string_piece); 205 EXPECT_EQ("custom-key", string_piece);
193 EXPECT_FALSE(input_stream.HasMoreData()); 206 EXPECT_FALSE(input_stream.HasMoreData());
194 } 207 }
195 208
196 // Decoding an encoded name with a valid index should work. 209 // Decoding an encoded name with a valid index should work.
197 TEST_F(HpackDecoderTest, DecodeNextNameIndexed) { 210 TEST_F(HpackDecoderTest, DecodeNextNameIndexed) {
198 HpackInputStream input_stream(kLiteralBound, "\x01"); 211 HpackInputStream input_stream(kLiteralBound, "\x01");
199 212
200 StringPiece string_piece; 213 StringPiece string_piece;
201 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); 214 EXPECT_TRUE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
202 EXPECT_EQ(":authority", string_piece); 215 EXPECT_EQ(":authority", string_piece);
203 EXPECT_FALSE(input_stream.HasMoreData()); 216 EXPECT_FALSE(input_stream.HasMoreData());
204 } 217 }
205 218
206 // Decoding an encoded name with an invalid index should fail. 219 // Decoding an encoded name with an invalid index should fail.
207 TEST_F(HpackDecoderTest, DecodeNextNameInvalidIndex) { 220 TEST_F(HpackDecoderTest, DecodeNextNameInvalidIndex) {
208 // One more than the number of static table entries. 221 // One more than the number of static table entries.
209 HpackInputStream input_stream(kLiteralBound, "\x3d"); 222 HpackInputStream input_stream(kLiteralBound, "\x3e");
210 223
211 StringPiece string_piece; 224 StringPiece string_piece;
212 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece)); 225 EXPECT_FALSE(decoder_peer_.DecodeNextName(&input_stream, &string_piece));
213 } 226 }
214 227
215 // Decoding an indexed header should toggle the index's presence in 228 // Decoding an indexed header should toggle the index's presence in
216 // the reference set, making a copy of static table entries if 229 // the reference set, making a copy of static table entries if
217 // necessary. It should also emit the header if toggled on (and only 230 // necessary. It should also emit the header if toggled on (and only
218 // as many times as it was toggled on). 231 // as many times as it was toggled on).
219 TEST_F(HpackDecoderTest, IndexedHeaderBasic) { 232 TEST_F(HpackDecoderTest, IndexedHeaderBasic) {
220 // Toggle on static table entry #2 (and make a copy at index #1), 233 // Toggle on static table entry #2 (and make a copy at index #1),
221 // then toggle on static table entry #5 (which is now #6 because of 234 // then toggle on static table entry #5 (which is now #6 because of
222 // the copy of #2). 235 // the copy of #2).
223 std::map<string, string> header_set1 = 236 std::map<string, string> header_set1 =
224 DecodeUniqueHeaderSet("\x82\x86"); 237 DecodeBlockExpectingSuccess("\x82\x86");
225 std::map<string, string> expected_header_set1; 238 std::map<string, string> expected_header_set1;
226 expected_header_set1[":method"] = "GET"; 239 expected_header_set1[":method"] = "GET";
227 expected_header_set1[":path"] = "/index.html"; 240 expected_header_set1[":path"] = "/index.html";
228 EXPECT_EQ(expected_header_set1, header_set1); 241 EXPECT_EQ(expected_header_set1, header_set1);
229 242
230 std::map<string, string> expected_header_set2; 243 std::map<string, string> expected_header_set2;
231 expected_header_set2[":path"] = "/index.html"; 244 expected_header_set2[":path"] = "/index.html";
232 // Toggle off the copy of static table entry #5. 245 // Toggle off the copy of static table entry #5.
233 std::map<string, string> header_set2 = 246 std::map<string, string> header_set2 =
234 DecodeUniqueHeaderSet("\x82"); 247 DecodeBlockExpectingSuccess("\x82");
235 EXPECT_EQ(expected_header_set2, header_set2); 248 EXPECT_EQ(expected_header_set2, header_set2);
236 } 249 }
237 250
238 // Test a too-large indexed header. 251 // Test a too-large indexed header.
239 TEST_F(HpackDecoderTest, InvalidIndexedHeader) { 252 TEST_F(HpackDecoderTest, InvalidIndexedHeader) {
240 // High-bit set, and a prefix of one more than the number of static entries. 253 // High-bit set, and a prefix of one more than the number of static entries.
241 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbd", 1))); 254 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xbe", 1)));
242 } 255 }
243 256
244 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) { 257 TEST_F(HpackDecoderTest, ContextUpdateMaximumSize) {
245 EXPECT_EQ(kDefaultHeaderTableSizeSetting, 258 EXPECT_EQ(kDefaultHeaderTableSizeSetting,
246 decoder_peer_.header_table().max_size()); 259 decoder_peer_.header_table()->max_size());
260 string input;
247 { 261 {
248 // Maximum-size update with size 126. Succeeds. 262 // Maximum-size update with size 126. Succeeds.
249 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x80\x7e", 2))); 263 HpackOutputStream output_stream;
250 EXPECT_EQ(126u, decoder_peer_.header_table().max_size()); 264 output_stream.AppendPrefix(kEncodingContextOpcode);
265 output_stream.AppendPrefix(kEncodingContextNewMaximumSize);
266 output_stream.AppendUint32(126);
267
268 output_stream.TakeString(&input);
269 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
270 EXPECT_EQ(126u, decoder_peer_.header_table()->max_size());
251 } 271 }
252 string input;
253 { 272 {
254 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds. 273 // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
255 HpackOutputStream output_stream; 274 HpackOutputStream output_stream;
256 output_stream.AppendBits(0x80, 8); // Context update. 275 output_stream.AppendPrefix(kEncodingContextOpcode);
257 output_stream.AppendBits(0x00, 1); // Size update. 276 output_stream.AppendPrefix(kEncodingContextNewMaximumSize);
258 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting); 277 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
259 278
260 output_stream.TakeString(&input); 279 output_stream.TakeString(&input);
261 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input))); 280 EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
262 EXPECT_EQ(kDefaultHeaderTableSizeSetting, 281 EXPECT_EQ(kDefaultHeaderTableSizeSetting,
263 decoder_peer_.header_table().max_size()); 282 decoder_peer_.header_table()->max_size());
264 } 283 }
265 { 284 {
266 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails. 285 // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
267 HpackOutputStream output_stream; 286 HpackOutputStream output_stream;
268 output_stream.AppendBits(0x80, 8); // Context update. 287 output_stream.AppendPrefix(kEncodingContextOpcode);
269 output_stream.AppendBits(0x00, 1); // Size update. 288 output_stream.AppendPrefix(kEncodingContextNewMaximumSize);
270 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1); 289 output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
271 290
272 output_stream.TakeString(&input); 291 output_stream.TakeString(&input);
273 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input))); 292 EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
274 EXPECT_EQ(kDefaultHeaderTableSizeSetting, 293 EXPECT_EQ(kDefaultHeaderTableSizeSetting,
275 decoder_peer_.header_table().max_size()); 294 decoder_peer_.header_table()->max_size());
276 } 295 }
277 } 296 }
278 297
279 TEST_F(HpackDecoderTest, ContextUpdateClearReferenceSet) { 298 TEST_F(HpackDecoderTest, ContextUpdateClearReferenceSet) {
280 // Toggle on a couple of headers. 299 // Toggle on a couple of headers.
281 std::map<string, string> header_set1 = 300 std::map<string, string> header_set1 =
282 DecodeUniqueHeaderSet("\x82\x86"); 301 DecodeBlockExpectingSuccess("\x82\x86");
283 std::map<string, string> expected_header_set1; 302 std::map<string, string> expected_header_set1;
284 expected_header_set1[":method"] = "GET"; 303 expected_header_set1[":method"] = "GET";
285 expected_header_set1[":path"] = "/index.html"; 304 expected_header_set1[":path"] = "/index.html";
286 EXPECT_EQ(expected_header_set1, header_set1); 305 EXPECT_EQ(expected_header_set1, header_set1);
287 306
288 // Send a context update to clear the reference set. 307 // Send a context update to clear the reference set.
289 std::map<string, string> header_set2 = 308 std::map<string, string> header_set2 =
290 DecodeUniqueHeaderSet("\x80\x80"); 309 DecodeBlockExpectingSuccess("\x30");
291 std::map<string, string> expected_header_set2; 310 std::map<string, string> expected_header_set2;
292 EXPECT_EQ(expected_header_set2, header_set2); 311 EXPECT_EQ(expected_header_set2, header_set2);
293 } 312 }
294 313
295 // Decoding two valid encoded literal headers with no indexing should 314 // Decoding two valid encoded literal headers with no indexing should
296 // work. 315 // work.
297 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) { 316 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexing) {
298 // First header with indexed name, second header with string literal 317 // First header with indexed name, second header with string literal
299 // name. 318 // name.
319 const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
300 std::map<string, string> header_set = 320 std::map<string, string> header_set =
301 DecodeUniqueHeaderSet( 321 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
302 "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2");
303 322
304 std::map<string, string> expected_header_set; 323 std::map<string, string> expected_header_set;
305 expected_header_set[":path"] = "/sample/path"; 324 expected_header_set[":path"] = "/sample/path";
306 expected_header_set[":path2"] = "/sample/path/2"; 325 expected_header_set[":path2"] = "/sample/path/2";
307 EXPECT_EQ(expected_header_set, header_set); 326 EXPECT_EQ(expected_header_set, header_set);
308 } 327 }
309 328
310 // Decoding two valid encoded literal headers with incremental 329 // Decoding two valid encoded literal headers with incremental
311 // indexing and string literal names should work and add the headers 330 // indexing and string literal names should work and add the headers
312 // to the reference set. 331 // to the reference set.
313 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) { 332 TEST_F(HpackDecoderTest, LiteralHeaderIncrementalIndexing) {
314 std::map<string, string> header_set = DecodeUniqueHeaderSet( 333 const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
315 StringPiece("\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2", 37)); 334 std::map<string, string> header_set =
335 DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
316 336
317 std::map<string, string> expected_header_set; 337 std::map<string, string> expected_header_set;
318 expected_header_set[":path"] = "/sample/path"; 338 expected_header_set[":path"] = "/sample/path";
319 expected_header_set[":path2"] = "/sample/path/2"; 339 expected_header_set[":path2"] = "/sample/path/2";
320 EXPECT_EQ(expected_header_set, header_set); 340 EXPECT_EQ(expected_header_set, header_set);
321 341
322 // Decoding an empty string should just return the reference set. 342 // Decoding an empty string should just return the reference set.
323 std::map<string, string> header_set2 = DecodeUniqueHeaderSet(""); 343 std::map<string, string> header_set2 = DecodeBlockExpectingSuccess("");
324 EXPECT_EQ(expected_header_set, header_set2); 344 EXPECT_EQ(expected_header_set, header_set2);
325 } 345 }
326 346
327 // Decoding literal headers with invalid indices should fail 347 TEST_F(HpackDecoderTest, LiteralHeaderWithIndexingInvalidNameIndex) {
328 // gracefully. 348 decoder_.ApplyHeaderTableSizeSetting(0);
329 TEST_F(HpackDecoderTest, LiteralHeaderInvalidIndices) {
330 // No indexing.
331 349
332 // One more than the number of static table entries. 350 // Name is the last static index. Works.
333 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7d", 1))); 351 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo")));
334 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x40", 1))); 352 // Name is one beyond the last static index. Fails.
353 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo")));
354 }
335 355
336 // Incremental indexing. 356 TEST_F(HpackDecoderTest, LiteralHeaderNoIndexingInvalidNameIndex) {
357 // Name is the last static index. Works.
358 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x0f\x2e\x03ooo")));
359 // Name is one beyond the last static index. Fails.
360 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x0f\x2f\x03ooo")));
361 }
337 362
338 // One more than the number of static table entries. 363 TEST_F(HpackDecoderTest, LiteralHeaderNeverIndexedInvalidNameIndex) {
339 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x3d", 1))); 364 // Name is the last static index. Works.
340 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x00", 1))); 365 EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x1f\x2e\x03ooo")));
366 // Name is one beyond the last static index. Fails.
367 EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x1f\x2f\x03ooo")));
341 } 368 }
342 369
343 // Round-tripping the header set from E.2.1 should work. 370 // Round-tripping the header set from E.2.1 should work.
344 TEST_F(HpackDecoderTest, BasicE21) { 371 TEST_F(HpackDecoderTest, BasicE21) {
345 HpackEncoder encoder(ObtainHpackHuffmanTable()); 372 HpackEncoder encoder(ObtainHpackHuffmanTable());
346 373
347 std::map<string, string> expected_header_set; 374 std::map<string, string> expected_header_set;
348 expected_header_set[":method"] = "GET"; 375 expected_header_set[":method"] = "GET";
349 expected_header_set[":scheme"] = "http"; 376 expected_header_set[":scheme"] = "http";
350 expected_header_set[":path"] = "/"; 377 expected_header_set[":path"] = "/";
(...skipping 12 matching lines...) Expand all
363 390
364 // 82 | == Indexed - Add == 391 // 82 | == Indexed - Add ==
365 // | idx = 2 392 // | idx = 2
366 // | -> :method: GET 393 // | -> :method: GET
367 // 87 | == Indexed - Add == 394 // 87 | == Indexed - Add ==
368 // | idx = 7 395 // | idx = 7
369 // | -> :scheme: http 396 // | -> :scheme: http
370 // 86 | == Indexed - Add == 397 // 86 | == Indexed - Add ==
371 // | idx = 6 398 // | idx = 6
372 // | -> :path: / 399 // | -> :path: /
373 // 04 | == Literal indexed == 400 // 44 | == Literal indexed ==
374 // | Indexed name (idx = 4) 401 // | Indexed name (idx = 4)
375 // | :authority 402 // | :authority
376 // 8b | Literal value (len = 15) 403 // 8c | Literal value (len = 15)
377 // | Huffman encoded: 404 // | Huffman encoded:
378 // db6d 883e 68d1 cb12 25ba 7f | .m..h...%.. 405 // e7cf 9beb e89b 6fb1 6fa9 b6ff | ......o.o...
379 // | Decoded: 406 // | Decoded:
380 // | www.example.com 407 // | www.example.com
381 // | -> :authority: www.example.com 408 // | -> :authority: www.example.com
382 char first[] = 409 string first = a2b_hex("828786448ce7cf9bebe89b6fb16fa9b6ff");
383 "\x82\x87\x86\x04\x8b\xdb\x6d\x88\x3e\x68\xd1\xcb\x12\x25\xba\x7f"; 410 header_set = DecodeBlockExpectingSuccess(first);
384 header_set = DecodeUniqueHeaderSet(StringPiece(first, arraysize(first)-1));
385 411
386 // TODO(jgraettinger): Create HpackEncodingContext and
387 // HpackDecoder peers, and inspect the header table here.
388 EXPECT_THAT(header_set, ElementsAre( 412 EXPECT_THAT(header_set, ElementsAre(
389 Pair(":authority", "www.example.com"), 413 Pair(":authority", "www.example.com"),
390 Pair(":method", "GET"), 414 Pair(":method", "GET"),
391 Pair(":path", "/"), 415 Pair(":path", "/"),
392 Pair(":scheme", "http"))); 416 Pair(":scheme", "http")));
393 417
394 // 1b | == Literal indexed == 418 expectEntry(1, 57, ":authority", "www.example.com");
395 // | Indexed name (idx = 27) 419 expectEntry(2, 38, ":path", "/");
420 expectEntry(3, 43, ":scheme", "http");
421 expectEntry(4, 42, ":method", "GET");
422 expectStaticEntry(5);
423 EXPECT_EQ(180u, decoder_peer_.header_table()->size());
424
425 // 5c | == Literal indexed ==
426 // | Indexed name (idx = 28)
396 // | cache-control 427 // | cache-control
397 // 86 | Literal value (len = 8) 428 // 86 | Literal value (len = 8)
398 // | Huffman encoded: 429 // | Huffman encoded:
399 // 6365 4a13 98ff | ceJ... 430 // b9b9 9495 56bf | ....V.
400 // | Decoded: 431 // | Decoded:
401 // | no-cache 432 // | no-cache
402 // | -> cache-control: no-cache 433 // | -> cache-control: no-cache
403 char second[] = "\x1b\x86\x63\x65\x4a\x13\x98\xff"; 434 string second = a2b_hex("5c86b9b9949556bf");
404 header_set = DecodeUniqueHeaderSet(StringPiece(second, arraysize(second)-1)); 435 header_set = DecodeBlockExpectingSuccess(second);
405 436
406 EXPECT_THAT(header_set, ElementsAre( 437 EXPECT_THAT(header_set, ElementsAre(
407 Pair(":authority", "www.example.com"), 438 Pair(":authority", "www.example.com"),
408 Pair(":method", "GET"), 439 Pair(":method", "GET"),
409 Pair(":path", "/"), 440 Pair(":path", "/"),
410 Pair(":scheme", "http"), 441 Pair(":scheme", "http"),
411 Pair("cache-control", "no-cache"))); 442 Pair("cache-control", "no-cache")));
412 443
413 // 8080 | == Empty reference set == 444 expectEntry(1, 53, "cache-control", "no-cache");
445 expectEntry(2, 57, ":authority", "www.example.com");
446 expectEntry(3, 38, ":path", "/");
447 expectEntry(4, 43, ":scheme", "http");
448 expectEntry(5, 42, ":method", "GET");
449 expectStaticEntry(6);
450 EXPECT_EQ(233u, decoder_peer_.header_table()->size());
451
452 // 30 | == Empty reference set ==
414 // | idx = 0 453 // | idx = 0
415 // | flag = 1 454 // | flag = 1
416 // 85 | == Indexed - Add == 455 // 85 | == Indexed - Add ==
417 // | idx = 5 456 // | idx = 5
418 // | -> :method: GET 457 // | -> :method: GET
419 // 8c | == Indexed - Add == 458 // 8c | == Indexed - Add ==
420 // | idx = 12 459 // | idx = 12
421 // | -> :scheme: https 460 // | -> :scheme: https
422 // 8b | == Indexed - Add == 461 // 8b | == Indexed - Add ==
423 // | idx = 11 462 // | idx = 11
424 // | -> :path: /index.html 463 // | -> :path: /index.html
425 // 84 | == Indexed - Add == 464 // 84 | == Indexed - Add ==
426 // | idx = 4 465 // | idx = 4
427 // | -> :authority: www.example.com 466 // | -> :authority: www.example.com
428 // 00 | == Literal indexed == 467 // 40 | == Literal indexed ==
429 // 88 | Literal name (len = 10) 468 // 88 | Literal name (len = 10)
430 // | Huffman encoded: 469 // | Huffman encoded:
431 // 4eb0 8b74 9790 fa7f | N..t.... 470 // 571c 5cdb 737b 2faf | W.\.s{/.
432 // | Decoded: 471 // | Decoded:
433 // | custom-key 472 // | custom-key
434 // 89 | Literal value (len = 12) 473 // 89 | Literal value (len = 12)
435 // | Huffman encoded: 474 // | Huffman encoded:
436 // 4eb0 8b74 979a 17a8 ff | N..t..... 475 // 571c 5cdb 7372 4d9c 57 | W.\.srM.W
437 // | Decoded: 476 // | Decoded:
438 // | custom-value 477 // | custom-value
439 // | -> custom-key: custom-value 478 // | -> custom-key: custom-value
440 char third[] = 479 string third = a2b_hex("30858c8b844088571c5cdb737b2faf89"
441 "\x80\x80\x85\x8c\x8b\x84\x00\x88\x4e\xb0\x8b\x74\x97\x90\xfa\x7f\x89" 480 "571c5cdb73724d9c57");
442 "\x4e\xb0\x8b\x74\x97\x9a\x17\xa8\xff"; 481 header_set = DecodeBlockExpectingSuccess(third);
443 header_set = DecodeUniqueHeaderSet(StringPiece(third, arraysize(third)-1));
444 482
445 EXPECT_THAT(header_set, ElementsAre( 483 EXPECT_THAT(header_set, ElementsAre(
446 Pair(":authority", "www.example.com"), 484 Pair(":authority", "www.example.com"),
447 Pair(":method", "GET"), 485 Pair(":method", "GET"),
448 Pair(":path", "/index.html"), 486 Pair(":path", "/index.html"),
449 Pair(":scheme", "https"), 487 Pair(":scheme", "https"),
450 Pair("custom-key", "custom-value"))); 488 Pair("custom-key", "custom-value")));
489
490 expectEntry(1, 54, "custom-key", "custom-value");
491 expectEntry(2, 48, ":path", "/index.html");
492 expectEntry(3, 44, ":scheme", "https");
493 expectEntry(4, 53, "cache-control", "no-cache");
494 expectEntry(5, 57, ":authority", "www.example.com");
495 expectEntry(6, 38, ":path", "/");
496 expectEntry(7, 43, ":scheme", "http");
497 expectEntry(8, 42, ":method", "GET");
498 expectStaticEntry(9);
499 EXPECT_EQ(379u, decoder_peer_.header_table()->size());
451 } 500 }
452 501
453 TEST_F(HpackDecoderTest, SectionD5ResponseHuffmanExamples) { 502 TEST_F(HpackDecoderTest, SectionD5ResponseHuffmanExamples) {
454 std::map<string, string> header_set; 503 std::map<string, string> header_set;
455 decoder_.ApplyHeaderTableSizeSetting(256); 504 decoder_.ApplyHeaderTableSizeSetting(256);
456 505
457 // 08 | == Literal indexed == 506 // 48 | == Literal indexed ==
458 // | Indexed name (idx = 8) 507 // | Indexed name (idx = 8)
459 // | :status 508 // | :status
460 // 82 | Literal value (len = 3) 509 // 82 | Literal value (len = 3)
461 // | Huffman encoded: 510 // | Huffman encoded:
462 // 98a7 | .. 511 // 4017 | @.
463 // | Decoded: 512 // | Decoded:
464 // | 302 513 // | 302
465 // | -> :status: 302 514 // | -> :status: 302
466 // 18 | == Literal indexed == 515 // 59 | == Literal indexed ==
467 // | Indexed name (idx = 24) 516 // | Indexed name (idx = 25)
468 // | cache-control 517 // | cache-control
469 // 85 | Literal value (len = 7) 518 // 85 | Literal value (len = 7)
470 // | Huffman encoded: 519 // | Huffman encoded:
471 // 73d5 cd11 1f | s.... 520 // bf06 724b 97 | ..rK.
472 // | Decoded: 521 // | Decoded:
473 // | private 522 // | private
474 // | -> cache-control: private 523 // | -> cache-control: private
475 // 22 | == Literal indexed == 524 // 63 | == Literal indexed ==
476 // | Indexed name (idx = 34) 525 // | Indexed name (idx = 35)
477 // | date 526 // | date
478 // 98 | Literal value (len = 29) 527 // 93 | Literal value (len = 29)
479 // | Huffman encoded: 528 // | Huffman encoded:
480 // ef6b 3a7a 0e6e 8fa2 63d0 729a 6e83 97d8 | .k:z.n..c.r.n... 529 // d6db b298 84de 2a71 8805 0620 9851 3109 | ......*q... .Q1.
481 // 69bd 8737 47bb bfc7 | i..7G... 530 // b56b a3 | .k.
482 // | Decoded: 531 // | Decoded:
483 // | Mon, 21 Oct 2013 20:13:21 532 // | Mon, 21 Oct 2013 20:13:21
484 // | GMT 533 // | GMT
485 // | -> date: Mon, 21 Oct 2013 534 // | -> date: Mon, 21 Oct 2013
486 // | 20:13:21 GMT 535 // | 20:13:21 GMT
487 // 30 | == Literal indexed == 536 // 71 | == Literal indexed ==
488 // | Indexed name (idx = 48) 537 // | Indexed name (idx = 49)
489 // | location 538 // | location
490 // 90 | Literal value (len = 23) 539 // 91 | Literal value (len = 23)
491 // | Huffman encoded: 540 // | Huffman encoded:
492 // ce31 743d 801b 6db1 07cd 1a39 6244 b74f | .1t=..m....9bD.O 541 // adce bf19 8e7e 7cf9 bebe 89b6 fb16 fa9b | ......|.........
542 // 6f | o
493 // | Decoded: 543 // | Decoded:
494 // | https://www.example.com 544 // | https://www.example.com
495 // | -> location: https://www.e 545 // | -> location: https://www.e
496 // | xample.com 546 // | xample.com
497 char first[] = 547 string first = a2b_hex("488240175985bf06724b976393d6dbb2"
498 "\x08\x82\x98\xa7\x18\x85\x73\xd5\xcd\x11\x1f\x22\x98\xef\x6b" 548 "9884de2a718805062098513109b56ba3"
499 "\x3a\x7a\x0e\x6e\x8f\xa2\x63\xd0\x72\x9a\x6e\x83\x97\xd8\x69\xbd\x87" 549 "7191adcebf198e7e7cf9bebe89b6fb16"
500 "\x37\x47\xbb\xbf\xc7\x30\x90\xce\x31\x74\x3d\x80\x1b\x6d\xb1\x07\xcd" 550 "fa9b6f");
501 "\x1a\x39\x62\x44\xb7\x4f"; 551 header_set = DecodeBlockExpectingSuccess(first);
502 header_set = DecodeUniqueHeaderSet(StringPiece(first, arraysize(first)-1));
503 552
504 EXPECT_THAT(header_set, ElementsAre( 553 EXPECT_THAT(header_set, ElementsAre(
505 Pair(":status", "302"), 554 Pair(":status", "302"),
506 Pair("cache-control", "private"), 555 Pair("cache-control", "private"),
507 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 556 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
508 Pair("location", "https://www.example.com"))); 557 Pair("location", "https://www.example.com")));
509 558
559 expectEntry(1, 63, "location", "https://www.example.com");
560 expectEntry(2, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
561 expectEntry(3, 52, "cache-control", "private");
562 expectEntry(4, 42, ":status", "302");
563 expectStaticEntry(5);
564 EXPECT_EQ(222u, decoder_peer_.header_table()->size());
565
510 // 8c | == Indexed - Add == 566 // 8c | == Indexed - Add ==
511 // | idx = 12 567 // | idx = 12
512 // | - evict: :status: 302 568 // | - evict: :status: 302
513 // | -> :status: 200 569 // | -> :status: 200
514 char second[] = "\x8c"; 570 string second = a2b_hex("8c");
515 header_set = DecodeUniqueHeaderSet(StringPiece(second, arraysize(second)-1)); 571 header_set = DecodeBlockExpectingSuccess(second);
516 572
517 EXPECT_THAT(header_set, ElementsAre( 573 EXPECT_THAT(header_set, ElementsAre(
518 Pair(":status", "200"), 574 Pair(":status", "200"),
519 Pair("cache-control", "private"), 575 Pair("cache-control", "private"),
520 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 576 Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
521 Pair("location", "https://www.example.com"))); 577 Pair("location", "https://www.example.com")));
522 578
579 expectEntry(1, 42, ":status", "200");
580 expectEntry(2, 63, "location", "https://www.example.com");
581 expectEntry(3, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
582 expectEntry(4, 52, "cache-control", "private");
583 expectStaticEntry(5);
584 EXPECT_EQ(222u, decoder_peer_.header_table()->size());
585
523 // 84 | == Indexed - Remove == 586 // 84 | == Indexed - Remove ==
524 // | idx = 4 587 // | idx = 4
525 // | -> cache-control: private 588 // | -> cache-control: private
526 // 84 | == Indexed - Add == 589 // 84 | == Indexed - Add ==
527 // | idx = 4 590 // | idx = 4
528 // | -> cache-control: private 591 // | -> cache-control: private
529 // 03 | == Literal indexed == 592 // 43 | == Literal indexed ==
530 // | Indexed name (idx = 3) 593 // | Indexed name (idx = 3)
531 // | date 594 // | date
532 // 98 | Literal value (len = 29) 595 // 93 | Literal value (len = 29)
533 // | Huffman encoded: 596 // | Huffman encoded:
534 // ef6b 3a7a 0e6e 8fa2 63d0 729a 6e83 97d8 | .k:z.n..c.r.n... 597 // d6db b298 84de 2a71 8805 0620 9851 3111 | ......*q... .Q1.
535 // 69bd 873f 47bb bfc7 | i..?G... 598 // b56b a3 | .k.
536 // | Decoded: 599 // | Decoded:
537 // | Mon, 21 Oct 2013 20:13:22 600 // | Mon, 21 Oct 2013 20:13:22
538 // | GMT 601 // | GMT
539 // | - evict: cache-control: pr 602 // | - evict: cache-control: pr
540 // | ivate 603 // | ivate
541 // | -> date: Mon, 21 Oct 2013 604 // | -> date: Mon, 21 Oct 2013
542 // | 20:13:22 GMT 605 // | 20:13:22 GMT
543 // 1d | == Literal indexed == 606 // 5e | == Literal indexed ==
544 // | Indexed name (idx = 29) 607 // | Indexed name (idx = 30)
545 // | content-encoding 608 // | content-encoding
546 // 83 | Literal value (len = 4) 609 // 84 | Literal value (len = 4)
547 // | Huffman encoded: 610 // | Huffman encoded:
548 // cbd5 4e | ..N 611 // abdd 97ff | ....
549 // | Decoded: 612 // | Decoded:
550 // | gzip 613 // | gzip
551 // | - evict: date: Mon, 21 Oct 614 // | - evict: date: Mon, 21 Oct
552 // | 2013 20:13:21 GMT 615 // | 2013 20:13:21 GMT
553 // | -> content-encoding: gzip 616 // | -> content-encoding: gzip
554 // 84 | == Indexed - Remove == 617 // 84 | == Indexed - Remove ==
555 // | idx = 4 618 // | idx = 4
556 // | -> location: https://www.e 619 // | -> location: https://www.e
557 // | xample.com 620 // | xample.com
558 // 84 | == Indexed - Add == 621 // 84 | == Indexed - Add ==
559 // | idx = 4 622 // | idx = 4
560 // | -> location: https://www.e 623 // | -> location: https://www.e
561 // | xample.com 624 // | xample.com
562 // 83 | == Indexed - Remove == 625 // 83 | == Indexed - Remove ==
563 // | idx = 3 626 // | idx = 3
564 // | -> :status: 200 627 // | -> :status: 200
565 // 83 | == Indexed - Add == 628 // 83 | == Indexed - Add ==
566 // | idx = 3 629 // | idx = 3
567 // | -> :status: 200 630 // | -> :status: 200
568 // 3a | == Literal indexed == 631 // 7b | == Literal indexed ==
569 // | Indexed name (idx = 58) 632 // | Indexed name (idx = 59)
570 // | set-cookie 633 // | set-cookie
571 // b3 | Literal value (len = 56) 634 // b1 | Literal value (len = 56)
572 // | Huffman encoded: 635 // | Huffman encoded:
573 // c5ad b77f 876f c7fb f7fd bfbe bff3 f7f4 | .....o.......... 636 // e0d6 cf9f 6e8f 9fd3 e5f6 fa76 fefd 3c7e | ....n......v....
574 // fb7e bbbe 9f5f 87e3 7fef edfa eefa 7c3f | ....._........|? 637 // df9e ff1f 2f0f 3cfe 9f6f cf7f 8f87 9f61 | ..../....o.....a
575 // 1d5d 1a23 ce54 6436 cd49 4bd5 d1cc 5f05 | .].#.Td6.IK..._. 638 // ad4f 4cc9 a973 a220 0ec3 725e 18b1 b74e | .OL..s. ..r^...N
576 // 3596 9b | 5.. 639 // 3f | ?
577 // | Decoded: 640 // | Decoded:
578 // | foo=ASDJKHQKBZXOQWEOPIUAXQ 641 // | foo=ASDJKHQKBZXOQWEOPIUAXQ
579 // | WEOIU; max-age=3600; versi 642 // | WEOIU; max-age=3600; versi
580 // | on=1 643 // | on=1
581 // | - evict: location: https:/ 644 // | - evict: location: https:/
582 // | /www.example.com 645 // | /www.example.com
583 // | - evict: :status: 200 646 // | - evict: :status: 200
584 // | -> set-cookie: foo=ASDJKHQ 647 // | -> set-cookie: foo=ASDJKHQ
585 // | KBZXOQWEOPIUAXQWEOIU; ma 648 // | KBZXOQWEOPIUAXQWEOIU; ma
586 // | x-age=3600; version=1 649 // | x-age=3600; version=1
587 char third[] = 650 string third = a2b_hex("84844393d6dbb29884de2a7188050620"
588 "\x84\x84\x03\x98\xef\x6b\x3a\x7a\x0e\x6e\x8f\xa2\x63\xd0\x72" 651 "98513111b56ba35e84abdd97ff848483"
589 "\x9a\x6e\x83\x97\xd8\x69\xbd\x87\x3f\x47\xbb\xbf\xc7\x1d\x83\xcb\xd5" 652 "837bb1e0d6cf9f6e8f9fd3e5f6fa76fe"
590 "\x4e\x84\x84\x83\x83\x3a\xb3\xc5\xad\xb7\x7f\x87\x6f\xc7\xfb\xf7\xfd" 653 "fd3c7edf9eff1f2f0f3cfe9f6fcf7f8f"
591 "\xbf\xbe\xbf\xf3\xf7\xf4\xfb\x7e\xbb\xbe\x9f\x5f\x87\xe3\x7f\xef\xed" 654 "879f61ad4f4cc9a973a2200ec3725e18"
592 "\xfa\xee\xfa\x7c\x3f\x1d\x5d\x1a\x23\xce\x54\x64\x36\xcd\x49\x4b\xd5" 655 "b1b74e3f");
593 "\xd1\xcc\x5f\x05\x35\x96\x9b"; 656 header_set = DecodeBlockExpectingSuccess(third);
594 header_set = DecodeUniqueHeaderSet(StringPiece(third, arraysize(third)-1));
595 657
596 EXPECT_THAT(header_set, ElementsAre( 658 EXPECT_THAT(header_set, ElementsAre(
597 Pair(":status", "200"), 659 Pair(":status", "200"),
598 Pair("cache-control", "private"), 660 Pair("cache-control", "private"),
599 Pair("content-encoding", "gzip"), 661 Pair("content-encoding", "gzip"),
600 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), 662 Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
601 Pair("location", "https://www.example.com"), 663 Pair("location", "https://www.example.com"),
602 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;" 664 Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
603 " max-age=3600; version=1"))); 665 " max-age=3600; version=1")));
666
667 expectEntry(1, 98, "set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
668 " max-age=3600; version=1");
669 expectEntry(2, 52, "content-encoding", "gzip");
670 expectEntry(3, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
671 expectStaticEntry(4);
672 EXPECT_EQ(215u, decoder_peer_.header_table()->size());
604 } 673 }
605 674
606 } // namespace 675 } // namespace
607 676
608 } // namespace net 677 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698