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

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

Powered by Google App Engine
This is Rietveld 408576698