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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 | 158 |
159 HpackOutputStream expected_; | 159 HpackOutputStream expected_; |
160 }; | 160 }; |
161 | 161 |
162 TEST_F(HpackEncoderTest, SingleDynamicIndex) { | 162 TEST_F(HpackEncoderTest, SingleDynamicIndex) { |
163 ExpectIndex(IndexOf(key_2_)); | 163 ExpectIndex(IndexOf(key_2_)); |
164 | 164 |
165 map<string, string> headers; | 165 map<string, string> headers; |
166 headers[key_2_->name()] = key_2_->value(); | 166 headers[key_2_->name()] = key_2_->value(); |
167 CompareWithExpectedEncoding(headers); | 167 CompareWithExpectedEncoding(headers); |
168 | |
169 // |key_2_| was added to the reference set. | |
170 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(key_2_)); | |
171 } | 168 } |
172 | 169 |
173 TEST_F(HpackEncoderTest, SingleStaticIndex) { | 170 TEST_F(HpackEncoderTest, SingleStaticIndex) { |
174 ExpectIndex(IndexOf(static_)); | 171 ExpectIndex(IndexOf(static_)); |
175 | 172 |
176 map<string, string> headers; | 173 map<string, string> headers; |
177 headers[static_->name()] = static_->value(); | 174 headers[static_->name()] = static_->value(); |
178 CompareWithExpectedEncoding(headers); | 175 CompareWithExpectedEncoding(headers); |
179 | |
180 // A new entry copying |static_| was inserted and added to the reference set. | |
181 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); | |
182 EXPECT_NE(static_, new_entry); | |
183 EXPECT_EQ(static_->name(), new_entry->name()); | |
184 EXPECT_EQ(static_->value(), new_entry->value()); | |
185 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(new_entry)); | |
186 } | 176 } |
187 | 177 |
188 TEST_F(HpackEncoderTest, SingleStaticIndexTooLarge) { | 178 TEST_F(HpackEncoderTest, SingleStaticIndexTooLarge) { |
189 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. | 179 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. |
190 ExpectIndex(IndexOf(static_)); | 180 ExpectIndex(IndexOf(static_)); |
191 | 181 |
192 map<string, string> headers; | 182 map<string, string> headers; |
193 headers[static_->name()] = static_->value(); | 183 headers[static_->name()] = static_->value(); |
194 CompareWithExpectedEncoding(headers); | 184 CompareWithExpectedEncoding(headers); |
195 | 185 |
196 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); | 186 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); |
197 EXPECT_EQ(0u, peer_.table()->reference_set().size()); | |
198 } | 187 } |
199 | 188 |
200 TEST_F(HpackEncoderTest, SingleLiteralWithIndexName) { | 189 TEST_F(HpackEncoderTest, SingleLiteralWithIndexName) { |
201 ExpectIndexedLiteral(key_2_, "value3"); | 190 ExpectIndexedLiteral(key_2_, "value3"); |
202 | 191 |
203 map<string, string> headers; | 192 map<string, string> headers; |
204 headers[key_2_->name()] = "value3"; | 193 headers[key_2_->name()] = "value3"; |
205 CompareWithExpectedEncoding(headers); | 194 CompareWithExpectedEncoding(headers); |
206 | 195 |
207 // A new entry was inserted and added to the reference set. | 196 // A new entry was inserted and added to the reference set. |
208 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); | 197 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); |
209 EXPECT_EQ(new_entry->name(), key_2_->name()); | 198 EXPECT_EQ(new_entry->name(), key_2_->name()); |
210 EXPECT_EQ(new_entry->value(), "value3"); | 199 EXPECT_EQ(new_entry->value(), "value3"); |
211 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(new_entry)); | |
212 } | 200 } |
213 | 201 |
214 TEST_F(HpackEncoderTest, SingleLiteralWithLiteralName) { | 202 TEST_F(HpackEncoderTest, SingleLiteralWithLiteralName) { |
215 ExpectIndexedLiteral("key3", "value3"); | 203 ExpectIndexedLiteral("key3", "value3"); |
216 | 204 |
217 map<string, string> headers; | 205 map<string, string> headers; |
218 headers["key3"] = "value3"; | 206 headers["key3"] = "value3"; |
219 CompareWithExpectedEncoding(headers); | 207 CompareWithExpectedEncoding(headers); |
220 | 208 |
221 // A new entry was inserted and added to the reference set. | |
222 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); | 209 HpackEntry* new_entry = &peer_.table_peer().dynamic_entries()->front(); |
223 EXPECT_EQ(new_entry->name(), "key3"); | 210 EXPECT_EQ(new_entry->name(), "key3"); |
224 EXPECT_EQ(new_entry->value(), "value3"); | 211 EXPECT_EQ(new_entry->value(), "value3"); |
225 EXPECT_THAT(peer_.table()->reference_set(), ElementsAre(new_entry)); | |
226 } | 212 } |
227 | 213 |
228 TEST_F(HpackEncoderTest, SingleLiteralTooLarge) { | 214 TEST_F(HpackEncoderTest, SingleLiteralTooLarge) { |
229 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. | 215 peer_.table()->SetMaxSize(1); // Also evicts all fixtures. |
230 | 216 |
231 ExpectIndexedLiteral("key3", "value3"); | 217 ExpectIndexedLiteral("key3", "value3"); |
232 | 218 |
233 // A header overflowing the header table is still emitted. | 219 // A header overflowing the header table is still emitted. |
234 // The header table is empty. | 220 // The header table is empty. |
235 map<string, string> headers; | 221 map<string, string> headers; |
236 headers["key3"] = "value3"; | 222 headers["key3"] = "value3"; |
237 CompareWithExpectedEncoding(headers); | 223 CompareWithExpectedEncoding(headers); |
238 | 224 |
239 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); | 225 EXPECT_EQ(0u, peer_.table_peer().dynamic_entries()->size()); |
240 EXPECT_EQ(0u, peer_.table()->reference_set().size()); | |
241 } | |
242 | |
243 TEST_F(HpackEncoderTest, SingleInReferenceSet) { | |
244 peer_.table()->Toggle(key_2_); | |
245 | |
246 // Nothing is emitted. | |
247 map<string, string> headers; | |
248 headers[key_2_->name()] = key_2_->value(); | |
249 CompareWithExpectedEncoding(headers); | |
250 } | |
251 | |
252 TEST_F(HpackEncoderTest, ExplicitToggleOff) { | |
253 peer_.table()->Toggle(key_1_); | |
254 peer_.table()->Toggle(key_2_); | |
255 | |
256 // |key_1_| is explicitly toggled off. | |
257 ExpectIndex(IndexOf(key_1_)); | |
258 | |
259 map<string, string> headers; | |
260 headers[key_2_->name()] = key_2_->value(); | |
261 CompareWithExpectedEncoding(headers); | |
262 } | |
263 | |
264 TEST_F(HpackEncoderTest, ImplicitToggleOff) { | |
265 peer_.table()->Toggle(key_1_); | |
266 peer_.table()->Toggle(key_2_); | |
267 | |
268 // |key_1_| is evicted. No explicit toggle required. | |
269 ExpectIndexedLiteral("key3", "value3"); | |
270 | |
271 map<string, string> headers; | |
272 headers[key_2_->name()] = key_2_->value(); | |
273 headers["key3"] = "value3"; | |
274 CompareWithExpectedEncoding(headers); | |
275 } | |
276 | |
277 TEST_F(HpackEncoderTest, ExplicitDoubleToggle) { | |
278 peer_.table()->Toggle(key_1_); | |
279 | |
280 // |key_1_| is double-toggled prior to being evicted. | |
281 ExpectIndex(IndexOf(key_1_)); | |
282 ExpectIndex(IndexOf(key_1_)); | |
283 ExpectIndexedLiteral("key3", "value3"); | |
284 | |
285 map<string, string> headers; | |
286 headers[key_1_->name()] = key_1_->value(); | |
287 headers["key3"] = "value3"; | |
288 CompareWithExpectedEncoding(headers); | |
289 } | 226 } |
290 | 227 |
291 TEST_F(HpackEncoderTest, EmitThanEvict) { | 228 TEST_F(HpackEncoderTest, EmitThanEvict) { |
292 // |key_1_| is toggled and placed into the reference set, | 229 // |key_1_| is toggled and placed into the reference set, |
293 // and then immediately evicted by "key3". | 230 // and then immediately evicted by "key3". |
294 ExpectIndex(IndexOf(key_1_)); | 231 ExpectIndex(IndexOf(key_1_)); |
295 ExpectIndexedLiteral("key3", "value3"); | 232 ExpectIndexedLiteral("key3", "value3"); |
296 | 233 |
297 map<string, string> headers; | 234 map<string, string> headers; |
298 headers[key_1_->name()] = key_1_->value(); | 235 headers[key_1_->name()] = key_1_->value(); |
299 headers["key3"] = "value3"; | 236 headers["key3"] = "value3"; |
300 CompareWithExpectedEncoding(headers); | 237 CompareWithExpectedEncoding(headers); |
301 } | 238 } |
302 | 239 |
303 TEST_F(HpackEncoderTest, CookieHeaderIsCrumbled) { | 240 TEST_F(HpackEncoderTest, CookieHeaderIsCrumbled) { |
304 peer_.table()->Toggle(cookie_a_); | 241 ExpectIndex(IndexOf(cookie_a_)); |
305 | |
306 // |cookie_a_| is already in the reference set. |cookie_c_| is | |
307 // toggled, and "e=ff" is emitted with an indexed name. | |
308 ExpectIndex(IndexOf(cookie_c_)); | 242 ExpectIndex(IndexOf(cookie_c_)); |
309 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); | 243 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); |
310 | 244 |
311 map<string, string> headers; | 245 map<string, string> headers; |
312 headers["cookie"] = "e=ff; a=bb; c=dd"; | 246 headers["cookie"] = "e=ff; a=bb; c=dd"; |
313 CompareWithExpectedEncoding(headers); | 247 CompareWithExpectedEncoding(headers); |
314 } | 248 } |
315 | 249 |
316 TEST_F(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) { | 250 TEST_F(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) { |
317 peer_.set_allow_huffman_compression(true); | 251 peer_.set_allow_huffman_compression(true); |
(...skipping 29 matching lines...) Expand all Loading... |
347 headers["cookie"] = "foo=bar; baz=bing"; | 281 headers["cookie"] = "foo=bar; baz=bing"; |
348 headers["hello"] = "goodbye"; | 282 headers["hello"] = "goodbye"; |
349 | 283 |
350 string expected_out, actual_out; | 284 string expected_out, actual_out; |
351 expected_.TakeString(&expected_out); | 285 expected_.TakeString(&expected_out); |
352 encoder_.EncodeHeaderSetWithoutCompression(headers, &actual_out); | 286 encoder_.EncodeHeaderSetWithoutCompression(headers, &actual_out); |
353 EXPECT_EQ(expected_out, actual_out); | 287 EXPECT_EQ(expected_out, actual_out); |
354 } | 288 } |
355 | 289 |
356 TEST_F(HpackEncoderTest, MultipleEncodingPasses) { | 290 TEST_F(HpackEncoderTest, MultipleEncodingPasses) { |
357 // Pass 1: key_1_ and cookie_a_ are toggled on. | 291 // Pass 1. |
358 { | 292 { |
359 map<string, string> headers; | 293 map<string, string> headers; |
360 headers["key1"] = "value1"; | 294 headers["key1"] = "value1"; |
361 headers["cookie"] = "a=bb"; | 295 headers["cookie"] = "a=bb"; |
362 | 296 |
363 ExpectIndex(IndexOf(cookie_a_)); | 297 ExpectIndex(IndexOf(cookie_a_)); |
364 ExpectIndex(IndexOf(key_1_)); | 298 ExpectIndex(IndexOf(key_1_)); |
365 CompareWithExpectedEncoding(headers); | 299 CompareWithExpectedEncoding(headers); |
366 } | 300 } |
367 // Pass 2: |key_1_| is double-toggled and evicted. | 301 // Header table is: |
368 // |key_2_| & |cookie_c_| are toggled on. | 302 // 65: key1: value1 |
369 // |cookie_a_| is toggled off. | 303 // 64: key2: value2 |
370 // A new cookie entry is added. | 304 // 63: cookie: a=bb |
| 305 // 62: cookie: c=dd |
| 306 // Pass 2. |
371 { | 307 { |
372 map<string, string> headers; | 308 map<string, string> headers; |
373 headers["key1"] = "value1"; | 309 headers["key1"] = "value1"; |
374 headers["key2"] = "value2"; | 310 headers["key2"] = "value2"; |
375 headers["cookie"] = "c=dd; e=ff"; | 311 headers["cookie"] = "c=dd; e=ff"; |
376 | 312 |
377 ExpectIndex(IndexOf(cookie_c_)); // Toggle on. | 313 ExpectIndex(IndexOf(cookie_c_)); |
378 ExpectIndex(IndexOf(key_1_)); // Double-toggle before eviction. | 314 // This cookie evicts |key1| from the header table. |
379 ExpectIndex(IndexOf(key_1_)); | |
380 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); | 315 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); |
| 316 // |key1| is inserted to the header table, which evicts |key2|. |
| 317 ExpectIndexedLiteral("key1", "value1"); |
| 318 // |key2| is inserted to the header table, which evicts |cookie_a|. |
| 319 ExpectIndexedLiteral("key2", "value2"); |
381 | 320 |
382 ExpectIndex(IndexOf(key_2_) + 1); // Toggle on. Add 1 to reflect insertion. | |
383 ExpectIndex(IndexOf(cookie_a_) + 1); // Toggle off. | |
384 CompareWithExpectedEncoding(headers); | 321 CompareWithExpectedEncoding(headers); |
385 } | 322 } |
386 // Pass 3: |key_2_| is evicted and implicitly toggled off. | 323 // Header table is: |
387 // |cookie_c_| is explicitly toggled off. | 324 // 65: cookie: c=dd |
388 // "key1" is re-inserted. | 325 // 64: cookie: e=ff |
| 326 // 63: key1: value1 |
| 327 // 62: key2: value2 |
| 328 // Pass 3. |
389 { | 329 { |
390 map<string, string> headers; | 330 map<string, string> headers; |
391 headers["key1"] = "value1"; | 331 headers["key1"] = "value1"; |
392 headers["key3"] = "value3"; | 332 headers["key3"] = "value3"; |
393 headers["cookie"] = "e=ff"; | 333 headers["cookie"] = "e=ff"; |
394 | 334 |
395 ExpectIndexedLiteral("key1", "value1"); | 335 ExpectIndex(64); |
| 336 ExpectIndex(63); |
396 ExpectIndexedLiteral("key3", "value3"); | 337 ExpectIndexedLiteral("key3", "value3"); |
397 ExpectIndex(IndexOf(cookie_c_) + 2); // Toggle off. Add 1 for insertion. | |
398 | 338 |
399 CompareWithExpectedEncoding(headers); | 339 CompareWithExpectedEncoding(headers); |
400 } | 340 } |
401 } | 341 } |
402 | 342 |
403 TEST_F(HpackEncoderTest, CookieToCrumbs) { | 343 TEST_F(HpackEncoderTest, CookieToCrumbs) { |
404 test::HpackEncoderPeer peer(NULL); | 344 test::HpackEncoderPeer peer(NULL); |
405 std::vector<StringPiece> out; | 345 std::vector<StringPiece> out; |
406 | 346 |
407 // A space after ';' is consumed. All other spaces remain. ';' at beginning | 347 // A space after ';' is consumed. All other spaces remain. ';' at beginning |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 expect[static_cast<uint8>('\xff')] = 1; | 384 expect[static_cast<uint8>('\xff')] = 1; |
445 expect[static_cast<uint8>('b')] = 1; | 385 expect[static_cast<uint8>('b')] = 1; |
446 | 386 |
447 EXPECT_EQ(expect, counts); | 387 EXPECT_EQ(expect, counts); |
448 EXPECT_EQ(9u, total_counts); | 388 EXPECT_EQ(9u, total_counts); |
449 } | 389 } |
450 | 390 |
451 } // namespace | 391 } // namespace |
452 | 392 |
453 } // namespace net | 393 } // namespace net |
OLD | NEW |