sdch_manager_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 3// found in the LICENSE file. 4 5#include <limits.h> 6 7#include <string> 8 9#include "base/logging.h" 10#include "base/memory/scoped_ptr.h" 11#include "net/base/sdch_manager.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace net { 15 16//------------------------------------------------------------------------------ 17// Provide sample data and compression results with a sample VCDIFF dictionary. 18// Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary. 19static const char kTestVcdiffDictionary[] = "DictionaryFor" 20 "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; 21 22//------------------------------------------------------------------------------ 23 24class SdchManagerTest : public testing::Test { 25 protected: 26 SdchManagerTest() 27 : sdch_manager_(new SdchManager) { 28 } 29 30 SdchManager* sdch_manager() { return sdch_manager_.get(); } 31 32 // Reset globals back to default state. 33 virtual void TearDown() { 34 SdchManager::EnableSdchSupport(true); 35 SdchManager::EnableSecureSchemeSupport(false); 36 } 37 38 private: 39 scoped_ptr<SdchManager> sdch_manager_; 40}; 41 42//------------------------------------------------------------------------------ 43static std::string NewSdchDictionary(const std::string& domain) { 44 std::string dictionary; 45 if (!domain.empty()) { 46 dictionary.append("Domain: "); 47 dictionary.append(domain); 48 dictionary.append("\n"); 49 } 50 dictionary.append("\n"); 51 dictionary.append(kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1); 52 return dictionary; 53} 54 55TEST_F(SdchManagerTest, DomainSupported) { 56 GURL google_url("http://www.google.com"); 57 58 SdchManager::EnableSdchSupport(false); 59 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url)); 60 SdchManager::EnableSdchSupport(true); 61 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url)); 62} 63 64TEST_F(SdchManagerTest, DomainBlacklisting) { 65 GURL test_url("http://www.test.com"); 66 GURL google_url("http://www.google.com"); 67 68 sdch_manager()->BlacklistDomain(test_url); 69 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test_url)); 70 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url)); 71 72 sdch_manager()->BlacklistDomain(google_url); 73 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url)); 74} 75 76TEST_F(SdchManagerTest, DomainBlacklistingCaseSensitivity) { 77 GURL test_url("http://www.TesT.com"); 78 GURL test2_url("http://www.tEst.com"); 79 80 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test_url)); 81 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test2_url)); 82 sdch_manager()->BlacklistDomain(test_url); 83 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test2_url)); 84} 85 86TEST_F(SdchManagerTest, BlacklistingReset) { 87 GURL gurl("http://mytest.DoMain.com"); 88 std::string domain(gurl.host()); 89 90 sdch_manager()->ClearBlacklistings(); 91 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); 92 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), 0); 93 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl)); 94} 95 96TEST_F(SdchManagerTest, BlacklistingSingleBlacklist) { 97 GURL gurl("http://mytest.DoMain.com"); 98 std::string domain(gurl.host()); 99 sdch_manager()->ClearBlacklistings(); 100 101 sdch_manager()->BlacklistDomain(gurl); 102 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 1); 103 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), 1); 104 105 // Check that any domain lookup reduces the blacklist counter. 106 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl)); 107 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); 108 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl)); 109} 110 111TEST_F(SdchManagerTest, BlacklistingExponential) { 112 GURL gurl("http://mytest.DoMain.com"); 113 std::string domain(gurl.host()); 114 sdch_manager()->ClearBlacklistings(); 115 116 int exponential = 1; 117 for (int i = 1; i < 100; ++i) { 118 sdch_manager()->BlacklistDomain(gurl); 119 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), exponential); 120 121 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), exponential); 122 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl)); 123 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), exponential - 1); 124 125 // Simulate a large number of domain checks (which eventually remove the 126 // blacklisting). 127 sdch_manager()->ClearDomainBlacklisting(domain); 128 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); 129 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl)); 130 131 // Predict what exponential backoff will be. 132 exponential = 1 + 2 * exponential; 133 if (exponential < 0) 134 exponential = INT_MAX; // We don't wrap. 135 } 136} 137 138TEST_F(SdchManagerTest, CanSetExactMatchDictionary) { 139 std::string dictionary_domain("x.y.z.google.com"); 140 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 141 142 // Perfect match should work. 143 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 144 GURL("http://" + dictionary_domain))); 145} 146 147TEST_F(SdchManagerTest, CanAdvertiseDictionaryOverHTTP) { 148 std::string dictionary_domain("x.y.z.google.com"); 149 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 150 151 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 152 GURL("http://" + dictionary_domain))); 153 154 std::string dictionary_list; 155 // HTTP target URL can advertise dictionary. 156 sdch_manager()->GetAvailDictionaryList( 157 GURL("http://" + dictionary_domain + "/test"), 158 &dictionary_list); 159 EXPECT_FALSE(dictionary_list.empty()); 160} 161 162TEST_F(SdchManagerTest, CanNotAdvertiseDictionaryOverHTTPS) { 163 std::string dictionary_domain("x.y.z.google.com"); 164 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 165 166 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 167 GURL("http://" + dictionary_domain))); 168 169 std::string dictionary_list; 170 // HTTPS target URL should NOT advertise dictionary. 171 sdch_manager()->GetAvailDictionaryList( 172 GURL("https://" + dictionary_domain + "/test"), 173 &dictionary_list); 174 EXPECT_TRUE(dictionary_list.empty()); 175} 176 177TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) { 178 std::string dictionary_domain("x.y.z.google.com"); 179 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 180 181 EXPECT_FALSE(sdch_manager()->AddSdchDictionary( 182 dictionary_text, GURL("https://" + dictionary_domain))); 183 SdchManager::EnableSecureSchemeSupport(true); 184 EXPECT_TRUE(sdch_manager()->AddSdchDictionary( 185 dictionary_text, GURL("https://" + dictionary_domain))); 186 187 GURL target_url("https://" + dictionary_domain + "/test"); 188 std::string dictionary_list; 189 // HTTPS target URL should advertise dictionary if secure scheme support is 190 // enabled. 191 sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list); 192 EXPECT_FALSE(dictionary_list.empty()); 193 194 // Dictionary should be available. 195 scoped_refptr<SdchManager::Dictionary> dictionary; 196 std::string client_hash; 197 std::string server_hash; 198 sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); 199 sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); 200 EXPECT_TRUE(dictionary != NULL); 201} 202 203TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) { 204 std::string dictionary_domain("x.y.z.google.com"); 205 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 206 207 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 208 GURL("http://" + dictionary_domain))); 209 210 GURL target_url("https://" + dictionary_domain + "/test"); 211 std::string dictionary_list; 212 // HTTPS target URL should not advertise dictionary acquired over HTTP even if 213 // secure scheme support is enabled. 214 SdchManager::EnableSecureSchemeSupport(true); 215 sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list); 216 EXPECT_TRUE(dictionary_list.empty()); 217 218 scoped_refptr<SdchManager::Dictionary> dictionary; 219 std::string client_hash; 220 std::string server_hash; 221 sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); 222 sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); 223 EXPECT_TRUE(dictionary == NULL); 224} 225 226TEST_F(SdchManagerTest, CanNotUseHTTPSDictionaryOverHTTP) { 227 std::string dictionary_domain("x.y.z.google.com"); 228 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 229 230 SdchManager::EnableSecureSchemeSupport(true); 231 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 232 GURL("https://" + dictionary_domain))); 233 234 GURL target_url("http://" + dictionary_domain + "/test"); 235 std::string dictionary_list; 236 // HTTP target URL should not advertise dictionary acquired over HTTPS even if 237 // secure scheme support is enabled. 238 sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list); 239 EXPECT_TRUE(dictionary_list.empty()); 240 241 scoped_refptr<SdchManager::Dictionary> dictionary; 242 std::string client_hash; 243 std::string server_hash; 244 sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); 245 sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); 246 EXPECT_TRUE(dictionary == NULL); 247} 248 249TEST_F(SdchManagerTest, FailToSetDomainMismatchDictionary) { 250 std::string dictionary_domain("x.y.z.google.com"); 251 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 252 253 // Fail the "domain match" requirement. 254 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, 255 GURL("http://y.z.google.com"))); 256} 257 258TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionary) { 259 std::string dictionary_domain("x.y.z.google.com"); 260 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 261 262 // Fail the HD with D being the domain and H having a dot requirement. 263 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, 264 GURL("http://w.x.y.z.google.com"))); 265} 266 267TEST_F(SdchManagerTest, FailToSetRepeatPrefixWithDotDictionary) { 268 // Make sure that a prefix that matches the domain postfix won't confuse 269 // the validation checks. 270 std::string dictionary_domain("www.google.com"); 271 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 272 273 // Fail the HD with D being the domain and H having a dot requirement. 274 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, 275 GURL("http://www.google.com.www.google.com"))); 276} 277 278TEST_F(SdchManagerTest, CanSetLeadingDotDomainDictionary) { 279 // Make sure that a prefix that matches the domain postfix won't confuse 280 // the validation checks. 281 std::string dictionary_domain(".google.com"); 282 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 283 284 // Verify that a leading dot in the domain is acceptable, as long as the host 285 // name does not contain any dots preceding the matched domain name. 286 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 287 GURL("http://www.google.com"))); 288} 289 290// Make sure the order of the tests is not helping us or confusing things. 291// See test CanSetExactMatchDictionary above for first try. 292TEST_F(SdchManagerTest, CanStillSetExactMatchDictionary) { 293 std::string dictionary_domain("x.y.z.google.com"); 294 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 295 296 // Perfect match should *STILL* work. 297 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 298 GURL("http://" + dictionary_domain))); 299} 300 301// Make sure the DOS protection precludes the addition of too many dictionaries. 302TEST_F(SdchManagerTest, TooManyDictionaries) { 303 std::string dictionary_domain(".google.com"); 304 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 305 306 size_t count = 0; 307 while (count <= SdchManager::kMaxDictionaryCount + 1) { 308 if (!sdch_manager()->AddSdchDictionary(dictionary_text, 309 GURL("http://www.google.com"))) 310 break; 311 312 dictionary_text += " "; // Create dictionary with different SHA signature. 313 ++count; 314 } 315 EXPECT_EQ(SdchManager::kMaxDictionaryCount, count); 316} 317 318TEST_F(SdchManagerTest, DictionaryNotTooLarge) { 319 std::string dictionary_domain(".google.com"); 320 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 321 322 dictionary_text.append( 323 SdchManager::kMaxDictionarySize - dictionary_text.size(), ' '); 324 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, 325 GURL("http://" + dictionary_domain))); 326} 327 328TEST_F(SdchManagerTest, DictionaryTooLarge) { 329 std::string dictionary_domain(".google.com"); 330 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 331 332 dictionary_text.append( 333 SdchManager::kMaxDictionarySize + 1 - dictionary_text.size(), ' '); 334 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, 335 GURL("http://" + dictionary_domain))); 336} 337 338TEST_F(SdchManagerTest, PathMatch) { 339 bool (*PathMatch)(const std::string& path, const std::string& restriction) = 340 SdchManager::Dictionary::PathMatch; 341 // Perfect match is supported. 342 EXPECT_TRUE(PathMatch("/search", "/search")); 343 EXPECT_TRUE(PathMatch("/search/", "/search/")); 344 345 // Prefix only works if last character of restriction is a slash, or first 346 // character in path after a match is a slash. Validate each case separately. 347 348 // Rely on the slash in the path (not at the end of the restriction). 349 EXPECT_TRUE(PathMatch("/search/something", "/search")); 350 EXPECT_TRUE(PathMatch("/search/s", "/search")); 351 EXPECT_TRUE(PathMatch("/search/other", "/search")); 352 EXPECT_TRUE(PathMatch("/search/something", "/search")); 353 354 // Rely on the slash at the end of the restriction. 355 EXPECT_TRUE(PathMatch("/search/something", "/search/")); 356 EXPECT_TRUE(PathMatch("/search/s", "/search/")); 357 EXPECT_TRUE(PathMatch("/search/other", "/search/")); 358 EXPECT_TRUE(PathMatch("/search/something", "/search/")); 359 360 // Make sure less that sufficient prefix match is false. 361 EXPECT_FALSE(PathMatch("/sear", "/search")); 362 EXPECT_FALSE(PathMatch("/", "/search")); 363 EXPECT_FALSE(PathMatch(std::string(), "/search")); 364 365 // Add examples with several levels of direcories in the restriction. 366 EXPECT_FALSE(PathMatch("/search/something", "search/s")); 367 EXPECT_FALSE(PathMatch("/search/", "/search/s")); 368 369 // Make sure adding characters to path will also fail. 370 EXPECT_FALSE(PathMatch("/searching", "/search/")); 371 EXPECT_FALSE(PathMatch("/searching", "/search")); 372 373 // Make sure we're case sensitive. 374 EXPECT_FALSE(PathMatch("/ABC", "/abc")); 375 EXPECT_FALSE(PathMatch("/abc", "/ABC")); 376} 377 378// The following are only applicable while we have a latency test in the code, 379// and can be removed when that functionality is stripped. 380TEST_F(SdchManagerTest, LatencyTestControls) { 381 GURL url("http://www.google.com"); 382 GURL url2("http://www.google2.com"); 383 384 // First make sure we default to false. 385 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); 386 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); 387 388 // That we can set each to true. 389 sdch_manager()->SetAllowLatencyExperiment(url, true); 390 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url)); 391 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); 392 393 sdch_manager()->SetAllowLatencyExperiment(url2, true); 394 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url)); 395 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2)); 396 397 // And can reset them to false. 398 sdch_manager()->SetAllowLatencyExperiment(url, false); 399 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); 400 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2)); 401 402 sdch_manager()->SetAllowLatencyExperiment(url2, false); 403 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); 404 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); 405} 406 407TEST_F(SdchManagerTest, CanUseMultipleManagers) { 408 SdchManager second_manager; 409 410 std::string dictionary_domain_1("x.y.z.google.com"); 411 std::string dictionary_domain_2("x.y.z.chromium.org"); 412 413 std::string dictionary_text_1(NewSdchDictionary(dictionary_domain_1)); 414 std::string dictionary_text_2(NewSdchDictionary(dictionary_domain_2)); 415 416 std::string tmp_hash; 417 std::string server_hash_1; 418 std::string server_hash_2; 419 420 SdchManager::GenerateHash(dictionary_text_1, &tmp_hash, &server_hash_1); 421 SdchManager::GenerateHash(dictionary_text_2, &tmp_hash, &server_hash_2); 422 423 // Confirm that if you add directories to one manager, you 424 // can't get them from the other. 425 EXPECT_TRUE(sdch_manager()->AddSdchDictionary( 426 dictionary_text_1, GURL("http://" + dictionary_domain_1))); 427 scoped_refptr<SdchManager::Dictionary> dictionary; 428 sdch_manager()->GetVcdiffDictionary( 429 server_hash_1, 430 GURL("http://" + dictionary_domain_1 + "/random_url"), 431 &dictionary); 432 EXPECT_TRUE(dictionary); 433 434 EXPECT_TRUE(second_manager.AddSdchDictionary( 435 dictionary_text_2, GURL("http://" + dictionary_domain_2))); 436 second_manager.GetVcdiffDictionary( 437 server_hash_2, 438 GURL("http://" + dictionary_domain_2 + "/random_url"), 439 &dictionary); 440 EXPECT_TRUE(dictionary); 441 442 sdch_manager()->GetVcdiffDictionary( 443 server_hash_2, 444 GURL("http://" + dictionary_domain_2 + "/random_url"), 445 &dictionary); 446 EXPECT_FALSE(dictionary); 447 448 second_manager.GetVcdiffDictionary( 449 server_hash_1, 450 GURL("http://" + dictionary_domain_1 + "/random_url"), 451 &dictionary); 452 EXPECT_FALSE(dictionary); 453} 454 455TEST_F(SdchManagerTest, HttpsCorrectlySupported) { 456 GURL url("http://www.google.com"); 457 GURL secure_url("https://www.google.com"); 458 459 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url)); 460 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(secure_url)); 461 462 SdchManager::EnableSecureSchemeSupport(true); 463 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url)); 464 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(secure_url)); 465} 466 467TEST_F(SdchManagerTest, ClearDictionaryData) { 468 std::string dictionary_domain("x.y.z.google.com"); 469 GURL blacklist_url("http://bad.chromium.org"); 470 471 std::string dictionary_text(NewSdchDictionary(dictionary_domain)); 472 std::string tmp_hash; 473 std::string server_hash; 474 475 SdchManager::GenerateHash(dictionary_text, &tmp_hash, &server_hash); 476 477 EXPECT_TRUE(sdch_manager()->AddSdchDictionary( 478 dictionary_text, GURL("http://" + dictionary_domain))); 479 scoped_refptr<SdchManager::Dictionary> dictionary; 480 sdch_manager()->GetVcdiffDictionary( 481 server_hash, 482 GURL("http://" + dictionary_domain + "/random_url"), 483 &dictionary); 484 EXPECT_TRUE(dictionary); 485 486 sdch_manager()->BlacklistDomain(GURL(blacklist_url)); 487 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(blacklist_url)); 488 489 sdch_manager()->ClearData(); 490 491 dictionary = NULL; 492 sdch_manager()->GetVcdiffDictionary( 493 server_hash, 494 GURL("http://" + dictionary_domain + "/random_url"), 495 &dictionary); 496 EXPECT_FALSE(dictionary); 497 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(blacklist_url)); 498} 499 500} // namespace net 501 502