| 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 |