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_encoder.h" | 5 #include "net/spdy/hpack_encoder.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "testing/gmock/include/gmock/gmock.h" | 10 #include "testing/gmock/include/gmock/gmock.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 // Disable Huffman coding by default. Most tests don't care about it. | 105 // Disable Huffman coding by default. Most tests don't care about it. |
106 peer_.set_allow_huffman_compression(false); | 106 peer_.set_allow_huffman_compression(false); |
107 } | 107 } |
108 | 108 |
109 void ExpectIndex(size_t index) { | 109 void ExpectIndex(size_t index) { |
110 expected_.AppendPrefix(kIndexedOpcode); | 110 expected_.AppendPrefix(kIndexedOpcode); |
111 expected_.AppendUint32(index); | 111 expected_.AppendUint32(index); |
112 } | 112 } |
113 void ExpectIndexedLiteral(HpackEntry* key_entry, StringPiece value) { | 113 void ExpectIndexedLiteral(HpackEntry* key_entry, StringPiece value) { |
114 expected_.AppendPrefix(kLiteralIncrementalIndexOpcode); | 114 expected_.AppendPrefix(kLiteralIncrementalIndexOpcode); |
115 expected_.AppendUint32(key_entry->Index()); | 115 expected_.AppendUint32(IndexOf(key_entry)); |
116 expected_.AppendPrefix(kStringLiteralIdentityEncoded); | 116 expected_.AppendPrefix(kStringLiteralIdentityEncoded); |
117 expected_.AppendUint32(value.size()); | 117 expected_.AppendUint32(value.size()); |
118 expected_.AppendBytes(value); | 118 expected_.AppendBytes(value); |
119 } | 119 } |
120 void ExpectIndexedLiteral(StringPiece name, StringPiece value) { | 120 void ExpectIndexedLiteral(StringPiece name, StringPiece value) { |
121 expected_.AppendPrefix(kLiteralIncrementalIndexOpcode); | 121 expected_.AppendPrefix(kLiteralIncrementalIndexOpcode); |
122 expected_.AppendUint32(0); | 122 expected_.AppendUint32(0); |
123 expected_.AppendPrefix(kStringLiteralIdentityEncoded); | 123 expected_.AppendPrefix(kStringLiteralIdentityEncoded); |
124 expected_.AppendUint32(name.size()); | 124 expected_.AppendUint32(name.size()); |
125 expected_.AppendBytes(name); | 125 expected_.AppendBytes(name); |
(...skipping 10 matching lines...) Expand all Loading... |
136 expected_.AppendPrefix(kStringLiteralIdentityEncoded); | 136 expected_.AppendPrefix(kStringLiteralIdentityEncoded); |
137 expected_.AppendUint32(value.size()); | 137 expected_.AppendUint32(value.size()); |
138 expected_.AppendBytes(value); | 138 expected_.AppendBytes(value); |
139 } | 139 } |
140 void CompareWithExpectedEncoding(const map<string, string>& header_set) { | 140 void CompareWithExpectedEncoding(const map<string, string>& header_set) { |
141 string expected_out, actual_out; | 141 string expected_out, actual_out; |
142 expected_.TakeString(&expected_out); | 142 expected_.TakeString(&expected_out); |
143 EXPECT_TRUE(encoder_.EncodeHeaderSet(header_set, &actual_out)); | 143 EXPECT_TRUE(encoder_.EncodeHeaderSet(header_set, &actual_out)); |
144 EXPECT_EQ(expected_out, actual_out); | 144 EXPECT_EQ(expected_out, actual_out); |
145 } | 145 } |
| 146 size_t IndexOf(HpackEntry* entry) { |
| 147 return peer_.table()->IndexOf(entry); |
| 148 } |
146 | 149 |
147 HpackEncoder encoder_; | 150 HpackEncoder encoder_; |
148 test::HpackEncoderPeer peer_; | 151 test::HpackEncoderPeer peer_; |
149 | 152 |
150 HpackEntry* static_; | 153 HpackEntry* static_; |
151 HpackEntry* key_1_; | 154 HpackEntry* key_1_; |
152 HpackEntry* key_2_; | 155 HpackEntry* key_2_; |
153 HpackEntry* cookie_a_; | 156 HpackEntry* cookie_a_; |
154 HpackEntry* cookie_c_; | 157 HpackEntry* cookie_c_; |
155 | 158 |
156 HpackOutputStream expected_; | 159 HpackOutputStream expected_; |
157 }; | 160 }; |
158 | 161 |
159 TEST_F(HpackEncoderTest, SingleDynamicIndex) { | 162 TEST_F(HpackEncoderTest, SingleDynamicIndex) { |
160 ExpectIndex(key_2_->Index()); | 163 ExpectIndex(IndexOf(key_2_)); |
161 | 164 |
162 map<string, string> headers; | 165 map<string, string> headers; |
163 headers[key_2_->name()] = key_2_->value(); | 166 headers[key_2_->name()] = key_2_->value(); |
164 CompareWithExpectedEncoding(headers); | 167 CompareWithExpectedEncoding(headers); |
165 | 168 |
166 // |key_2_| was added to the reference set. | 169 // |key_2_| was added to the reference set. |
167 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(key_2_)); | 170 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(key_2_)); |
168 } | 171 } |
169 | 172 |
170 TEST_F(HpackEncoderTest, SingleStaticIndex) { | 173 TEST_F(HpackEncoderTest, SingleStaticIndex) { |
171 ExpectIndex(static_->Index()); | 174 ExpectIndex(IndexOf(static_)); |
172 | 175 |
173 map<string, string> headers; | 176 map<string, string> headers; |
174 headers[static_->name()] = static_->value(); | 177 headers[static_->name()] = static_->value(); |
175 CompareWithExpectedEncoding(headers); | 178 CompareWithExpectedEncoding(headers); |
176 | 179 |
177 // A new entry copying |static_| was inserted and added to the reference set. | 180 // A new entry copying |static_| was inserted and added to the reference set. |
178 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); | 181 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); |
179 EXPECT_NE(static_, new_entry); | 182 EXPECT_NE(static_, new_entry); |
180 EXPECT_EQ(static_->name(), new_entry->name()); | 183 EXPECT_EQ(static_->name(), new_entry->name()); |
181 EXPECT_EQ(static_->value(), new_entry->value()); | 184 EXPECT_EQ(static_->value(), new_entry->value()); |
182 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(new_entry)); | 185 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(new_entry)); |
183 } | 186 } |
184 | 187 |
185 TEST_F(HpackEncoderTest, SingleStaticIndexTooLarge) { | 188 TEST_F(HpackEncoderTest, SingleStaticIndexTooLarge) { |
186 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. | 189 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. |
187 ExpectIndex(static_->Index()); | 190 ExpectIndex(IndexOf(static_)); |
188 | 191 |
189 map<string, string> headers; | 192 map<string, string> headers; |
190 headers[static_->name()] = static_->value(); | 193 headers[static_->name()] = static_->value(); |
191 CompareWithExpectedEncoding(headers); | 194 CompareWithExpectedEncoding(headers); |
192 | 195 |
193 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); | 196 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); |
194 EXPECT_EQ(0u, peer_.table()->reference_set().size()); | 197 EXPECT_EQ(0u, peer_.table()->reference_set().size()); |
195 } | 198 } |
196 | 199 |
197 TEST_F(HpackEncoderTest, SingleLiteralWithIndexName) { | 200 TEST_F(HpackEncoderTest, SingleLiteralWithIndexName) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 map<string, string> headers; | 247 map<string, string> headers; |
245 headers[key_2_->name()] = key_2_->value(); | 248 headers[key_2_->name()] = key_2_->value(); |
246 CompareWithExpectedEncoding(headers); | 249 CompareWithExpectedEncoding(headers); |
247 } | 250 } |
248 | 251 |
249 TEST_F(HpackEncoderTest, ExplicitToggleOff) { | 252 TEST_F(HpackEncoderTest, ExplicitToggleOff) { |
250 peer_.table()->Toggle(key_1_); | 253 peer_.table()->Toggle(key_1_); |
251 peer_.table()->Toggle(key_2_); | 254 peer_.table()->Toggle(key_2_); |
252 | 255 |
253 // |key_1_| is explicitly toggled off. | 256 // |key_1_| is explicitly toggled off. |
254 ExpectIndex(key_1_->Index()); | 257 ExpectIndex(IndexOf(key_1_)); |
255 | 258 |
256 map<string, string> headers; | 259 map<string, string> headers; |
257 headers[key_2_->name()] = key_2_->value(); | 260 headers[key_2_->name()] = key_2_->value(); |
258 CompareWithExpectedEncoding(headers); | 261 CompareWithExpectedEncoding(headers); |
259 } | 262 } |
260 | 263 |
261 TEST_F(HpackEncoderTest, ImplicitToggleOff) { | 264 TEST_F(HpackEncoderTest, ImplicitToggleOff) { |
262 peer_.table()->Toggle(key_1_); | 265 peer_.table()->Toggle(key_1_); |
263 peer_.table()->Toggle(key_2_); | 266 peer_.table()->Toggle(key_2_); |
264 | 267 |
265 // |key_1_| is evicted. No explicit toggle required. | 268 // |key_1_| is evicted. No explicit toggle required. |
266 ExpectIndexedLiteral("key3", "value3"); | 269 ExpectIndexedLiteral("key3", "value3"); |
267 | 270 |
268 map<string, string> headers; | 271 map<string, string> headers; |
269 headers[key_2_->name()] = key_2_->value(); | 272 headers[key_2_->name()] = key_2_->value(); |
270 headers["key3"] = "value3"; | 273 headers["key3"] = "value3"; |
271 CompareWithExpectedEncoding(headers); | 274 CompareWithExpectedEncoding(headers); |
272 } | 275 } |
273 | 276 |
274 TEST_F(HpackEncoderTest, ExplicitDoubleToggle) { | 277 TEST_F(HpackEncoderTest, ExplicitDoubleToggle) { |
275 peer_.table()->Toggle(key_1_); | 278 peer_.table()->Toggle(key_1_); |
276 | 279 |
277 // |key_1_| is double-toggled prior to being evicted. | 280 // |key_1_| is double-toggled prior to being evicted. |
278 ExpectIndex(key_1_->Index()); | 281 ExpectIndex(IndexOf(key_1_)); |
279 ExpectIndex(key_1_->Index()); | 282 ExpectIndex(IndexOf(key_1_)); |
280 ExpectIndexedLiteral("key3", "value3"); | 283 ExpectIndexedLiteral("key3", "value3"); |
281 | 284 |
282 map<string, string> headers; | 285 map<string, string> headers; |
283 headers[key_1_->name()] = key_1_->value(); | 286 headers[key_1_->name()] = key_1_->value(); |
284 headers["key3"] = "value3"; | 287 headers["key3"] = "value3"; |
285 CompareWithExpectedEncoding(headers); | 288 CompareWithExpectedEncoding(headers); |
286 } | 289 } |
287 | 290 |
288 TEST_F(HpackEncoderTest, EmitThanEvict) { | 291 TEST_F(HpackEncoderTest, EmitThanEvict) { |
289 // |key_1_| is toggled and placed into the reference set, | 292 // |key_1_| is toggled and placed into the reference set, |
290 // and then immediately evicted by "key3". | 293 // and then immediately evicted by "key3". |
291 ExpectIndex(key_1_->Index()); | 294 ExpectIndex(IndexOf(key_1_)); |
292 ExpectIndexedLiteral("key3", "value3"); | 295 ExpectIndexedLiteral("key3", "value3"); |
293 | 296 |
294 map<string, string> headers; | 297 map<string, string> headers; |
295 headers[key_1_->name()] = key_1_->value(); | 298 headers[key_1_->name()] = key_1_->value(); |
296 headers["key3"] = "value3"; | 299 headers["key3"] = "value3"; |
297 CompareWithExpectedEncoding(headers); | 300 CompareWithExpectedEncoding(headers); |
298 } | 301 } |
299 | 302 |
300 TEST_F(HpackEncoderTest, CookieHeaderIsCrumbled) { | 303 TEST_F(HpackEncoderTest, CookieHeaderIsCrumbled) { |
301 peer_.table()->Toggle(cookie_a_); | 304 peer_.table()->Toggle(cookie_a_); |
302 | 305 |
303 // |cookie_a_| is already in the reference set. |cookie_c_| is | 306 // |cookie_a_| is already in the reference set. |cookie_c_| is |
304 // toggled, and "e=ff" is emitted with an indexed name. | 307 // toggled, and "e=ff" is emitted with an indexed name. |
305 ExpectIndex(cookie_c_->Index()); | 308 ExpectIndex(IndexOf(cookie_c_)); |
306 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); | 309 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); |
307 | 310 |
308 map<string, string> headers; | 311 map<string, string> headers; |
309 headers["cookie"] = "e=ff; a=bb; c=dd"; | 312 headers["cookie"] = "e=ff; a=bb; c=dd"; |
310 CompareWithExpectedEncoding(headers); | 313 CompareWithExpectedEncoding(headers); |
311 } | 314 } |
312 | 315 |
313 TEST_F(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) { | 316 TEST_F(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) { |
314 peer_.set_allow_huffman_compression(true); | 317 peer_.set_allow_huffman_compression(true); |
315 | 318 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 EXPECT_EQ(expected_out, actual_out); | 353 EXPECT_EQ(expected_out, actual_out); |
351 } | 354 } |
352 | 355 |
353 TEST_F(HpackEncoderTest, MultipleEncodingPasses) { | 356 TEST_F(HpackEncoderTest, MultipleEncodingPasses) { |
354 // Pass 1: key_1_ and cookie_a_ are toggled on. | 357 // Pass 1: key_1_ and cookie_a_ are toggled on. |
355 { | 358 { |
356 map<string, string> headers; | 359 map<string, string> headers; |
357 headers["key1"] = "value1"; | 360 headers["key1"] = "value1"; |
358 headers["cookie"] = "a=bb"; | 361 headers["cookie"] = "a=bb"; |
359 | 362 |
360 ExpectIndex(cookie_a_->Index()); | 363 ExpectIndex(IndexOf(cookie_a_)); |
361 ExpectIndex(key_1_->Index()); | 364 ExpectIndex(IndexOf(key_1_)); |
362 CompareWithExpectedEncoding(headers); | 365 CompareWithExpectedEncoding(headers); |
363 } | 366 } |
364 // Pass 2: |key_1_| is double-toggled and evicted. | 367 // Pass 2: |key_1_| is double-toggled and evicted. |
365 // |key_2_| & |cookie_c_| are toggled on. | 368 // |key_2_| & |cookie_c_| are toggled on. |
366 // |cookie_a_| is toggled off. | 369 // |cookie_a_| is toggled off. |
367 // A new cookie entry is added. | 370 // A new cookie entry is added. |
368 { | 371 { |
369 map<string, string> headers; | 372 map<string, string> headers; |
370 headers["key1"] = "value1"; | 373 headers["key1"] = "value1"; |
371 headers["key2"] = "value2"; | 374 headers["key2"] = "value2"; |
372 headers["cookie"] = "c=dd; e=ff"; | 375 headers["cookie"] = "c=dd; e=ff"; |
373 | 376 |
374 ExpectIndex(cookie_c_->Index()); // Toggle on. | 377 ExpectIndex(IndexOf(cookie_c_)); // Toggle on. |
375 ExpectIndex(key_1_->Index()); // Double-toggle before eviction. | 378 ExpectIndex(IndexOf(key_1_)); // Double-toggle before eviction. |
376 ExpectIndex(key_1_->Index()); | 379 ExpectIndex(IndexOf(key_1_)); |
377 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); | 380 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); |
378 ExpectIndex(key_2_->Index() + 1); // Toggle on. Add 1 to reflect insertion. | 381 |
379 ExpectIndex(cookie_a_->Index() + 1); // Toggle off. | 382 ExpectIndex(IndexOf(key_2_) + 1); // Toggle on. Add 1 to reflect insertion. |
| 383 ExpectIndex(IndexOf(cookie_a_) + 1); // Toggle off. |
380 CompareWithExpectedEncoding(headers); | 384 CompareWithExpectedEncoding(headers); |
381 } | 385 } |
382 // Pass 3: |key_2_| is evicted and implicitly toggled off. | 386 // Pass 3: |key_2_| is evicted and implicitly toggled off. |
383 // |cookie_c_| is explicitly toggled off. | 387 // |cookie_c_| is explicitly toggled off. |
384 // "key1" is re-inserted. | 388 // "key1" is re-inserted. |
385 { | 389 { |
386 map<string, string> headers; | 390 map<string, string> headers; |
387 headers["key1"] = "value1"; | 391 headers["key1"] = "value1"; |
388 headers["key3"] = "value3"; | 392 headers["key3"] = "value3"; |
389 headers["cookie"] = "e=ff"; | 393 headers["cookie"] = "e=ff"; |
390 | 394 |
391 ExpectIndexedLiteral("key1", "value1"); | 395 ExpectIndexedLiteral("key1", "value1"); |
392 ExpectIndexedLiteral("key3", "value3"); | 396 ExpectIndexedLiteral("key3", "value3"); |
393 ExpectIndex(cookie_c_->Index() + 2); // Toggle off. Add 1 for insertion. | 397 ExpectIndex(IndexOf(cookie_c_) + 2); // Toggle off. Add 1 for insertion. |
394 | 398 |
395 CompareWithExpectedEncoding(headers); | 399 CompareWithExpectedEncoding(headers); |
396 } | 400 } |
397 } | 401 } |
398 | 402 |
399 TEST_F(HpackEncoderTest, CookieToCrumbs) { | 403 TEST_F(HpackEncoderTest, CookieToCrumbs) { |
400 test::HpackEncoderPeer peer(NULL); | 404 test::HpackEncoderPeer peer(NULL); |
401 std::vector<StringPiece> out; | 405 std::vector<StringPiece> out; |
402 | 406 |
403 // A space after ';' is consumed. All other spaces remain. ';' at beginning | 407 // A space after ';' is consumed. All other spaces remain. ';' at beginning |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 expect[static_cast<uint8>('\xff')] = 1; | 444 expect[static_cast<uint8>('\xff')] = 1; |
441 expect[static_cast<uint8>('b')] = 1; | 445 expect[static_cast<uint8>('b')] = 1; |
442 | 446 |
443 EXPECT_EQ(expect, counts); | 447 EXPECT_EQ(expect, counts); |
444 EXPECT_EQ(9u, total_counts); | 448 EXPECT_EQ(9u, total_counts); |
445 } | 449 } |
446 | 450 |
447 } // namespace | 451 } // namespace |
448 | 452 |
449 } // namespace net | 453 } // namespace net |
OLD | NEW |