// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "base/test/simple_test_clock.h" #include "net/base/net_log.h" #include "net/base/sdch_manager.h" #include "net/base/sdch_observer.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace net { // Workaround for http://crbug.com/437794; remove when fixed. #if !defined(OS_IOS) //------------------------------------------------------------------------------ // Provide sample data and compression results with a sample VCDIFF dictionary. // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary. static const char kTestVcdiffDictionary[] = "DictionaryFor" "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; //------------------------------------------------------------------------------ class MockSdchObserver : public SdchObserver { public: MockSdchObserver() : dictionary_used_notifications_(0), get_dictionary_notifications_(0), clear_dictionaries_notifications_(0) {} std::string last_server_hash() const { return last_server_hash_; } int dictionary_used_notifications() const { return dictionary_used_notifications_; } const GURL& last_dictionary_request_url() const { return last_dictionary_request_url_; } const GURL& last_dictionary_url() const { return last_dictionary_url_; } int get_dictionary_notifications() const { return get_dictionary_notifications_; } int clear_dictionary_notifications() const { return clear_dictionaries_notifications_; } // SdchObserver implementation void OnDictionaryUsed(SdchManager* manager, const std::string& server_hash) override { last_server_hash_ = server_hash; ++dictionary_used_notifications_; } void OnGetDictionary(SdchManager* manager, const GURL& request_url, const GURL& dictionary_url) override { ++get_dictionary_notifications_; last_dictionary_request_url_ = request_url; last_dictionary_url_ = dictionary_url; } void OnClearDictionaries(SdchManager* manager) override { ++clear_dictionaries_notifications_; } private: int dictionary_used_notifications_; int get_dictionary_notifications_; int clear_dictionaries_notifications_; std::string last_server_hash_; GURL last_dictionary_request_url_; GURL last_dictionary_url_; DISALLOW_COPY_AND_ASSIGN(MockSdchObserver); }; class SdchManagerTest : public testing::Test { protected: SdchManagerTest() : sdch_manager_(new SdchManager), default_support_(false), default_https_support_(false) { default_support_ = sdch_manager_->sdch_enabled(); default_https_support_ = sdch_manager_->secure_scheme_supported(); } ~SdchManagerTest() override {} SdchManager* sdch_manager() { return sdch_manager_.get(); } // Reset globals back to default state. void TearDown() override { SdchManager::EnableSdchSupport(default_support_); SdchManager::EnableSecureSchemeSupport(default_https_support_); } // Attempt to add a dictionary to the manager and probe for success or // failure. bool AddSdchDictionary(const std::string& dictionary_text, const GURL& gurl) { return sdch_manager_->AddSdchDictionary(dictionary_text, gurl, nullptr) == SDCH_OK; } private: scoped_ptr sdch_manager_; bool default_support_; bool default_https_support_; }; static std::string NewSdchDictionary(const std::string& domain) { std::string dictionary; if (!domain.empty()) { dictionary.append("Domain: "); dictionary.append(domain); dictionary.append("\n"); } dictionary.append("\n"); dictionary.append(kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1); return dictionary; } TEST_F(SdchManagerTest, DomainSupported) { GURL google_url("http://www.google.com"); SdchManager::EnableSdchSupport(false); EXPECT_EQ(SDCH_DISABLED, sdch_manager()->IsInSupportedDomain(google_url)); SdchManager::EnableSdchSupport(true); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(google_url)); } TEST_F(SdchManagerTest, DomainBlacklisting) { GURL test_url("http://www.test.com"); GURL google_url("http://www.google.com"); sdch_manager()->BlacklistDomain(test_url, SDCH_OK); EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(test_url)); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(google_url)); sdch_manager()->BlacklistDomain(google_url, SDCH_OK); EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(google_url)); } TEST_F(SdchManagerTest, DomainBlacklistingCaseSensitivity) { GURL test_url("http://www.TesT.com"); GURL test2_url("http://www.tEst.com"); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(test_url)); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(test2_url)); sdch_manager()->BlacklistDomain(test_url, SDCH_OK); EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(test2_url)); } TEST_F(SdchManagerTest, BlacklistingReset) { GURL gurl("http://mytest.DoMain.com"); std::string domain(gurl.host()); sdch_manager()->ClearBlacklistings(); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), 0); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(gurl)); } TEST_F(SdchManagerTest, BlacklistingSingleBlacklist) { GURL gurl("http://mytest.DoMain.com"); std::string domain(gurl.host()); sdch_manager()->ClearBlacklistings(); sdch_manager()->BlacklistDomain(gurl, SDCH_OK); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 1); EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), 1); // Check that any domain lookup reduces the blacklist counter. EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(gurl)); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(gurl)); } TEST_F(SdchManagerTest, BlacklistingExponential) { GURL gurl("http://mytest.DoMain.com"); std::string domain(gurl.host()); sdch_manager()->ClearBlacklistings(); int exponential = 1; for (int i = 1; i < 100; ++i) { sdch_manager()->BlacklistDomain(gurl, SDCH_OK); EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), exponential); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), exponential); EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(gurl)); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), exponential - 1); // Simulate a large number of domain checks (which eventually remove the // blacklisting). sdch_manager()->ClearDomainBlacklisting(domain); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 0); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(gurl)); // Predict what exponential backoff will be. exponential = 1 + 2 * exponential; if (exponential < 0) exponential = INT_MAX; // We don't wrap. } } TEST_F(SdchManagerTest, CanSetExactMatchDictionary) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Perfect match should work. EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); } TEST_F(SdchManagerTest, CanAdvertiseDictionaryOverHTTP) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); // HTTP target URL can advertise dictionary. EXPECT_TRUE(sdch_manager()->GetDictionarySet( GURL("http://" + dictionary_domain + "/test"))); } TEST_F(SdchManagerTest, CanNotAdvertiseDictionaryOverHTTPS) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); // HTTPS target URL should NOT advertise dictionary. EXPECT_FALSE(sdch_manager()->GetDictionarySet( GURL("https://" + dictionary_domain + "/test"))); } TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); SdchManager::EnableSecureSchemeSupport(false); EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("https://" + dictionary_domain))); SdchManager::EnableSecureSchemeSupport(true); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("https://" + dictionary_domain))); GURL target_url("https://" + dictionary_domain + "/test"); // HTTPS target URL should advertise dictionary if secure scheme support is // enabled. EXPECT_TRUE(sdch_manager()->GetDictionarySet(target_url)); // Dictionary should be available. std::string client_hash; std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); SdchProblemCode problem_code; scoped_ptr dict_set( sdch_manager()->GetDictionarySetByHash( target_url, server_hash, &problem_code)); EXPECT_EQ(SDCH_OK, problem_code); EXPECT_TRUE(dict_set.get()); EXPECT_TRUE(dict_set->GetDictionary(server_hash)); } TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); GURL target_url("https://" + dictionary_domain + "/test"); // HTTPS target URL should not advertise dictionary acquired over HTTP even if // secure scheme support is enabled. SdchManager::EnableSecureSchemeSupport(true); EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_url)); std::string client_hash; std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); SdchProblemCode problem_code; scoped_ptr dict_set( sdch_manager()->GetDictionarySetByHash( target_url, server_hash, &problem_code)); EXPECT_FALSE(dict_set.get()); EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME, problem_code); } TEST_F(SdchManagerTest, CanNotUseHTTPSDictionaryOverHTTP) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); SdchManager::EnableSecureSchemeSupport(true); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("https://" + dictionary_domain))); GURL target_url("http://" + dictionary_domain + "/test"); // HTTP target URL should not advertise dictionary acquired over HTTPS even if // secure scheme support is enabled. EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_url)); std::string client_hash; std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); SdchProblemCode problem_code; scoped_ptr dict_set( sdch_manager()->GetDictionarySetByHash( target_url, server_hash, &problem_code)); EXPECT_FALSE(dict_set.get()); EXPECT_EQ(SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME, problem_code); } TEST_F(SdchManagerTest, FailToSetDomainMismatchDictionary) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the "domain match" requirement. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://y.z.google.com"))); } TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionary) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the HD with D being the domain and H having a dot requirement. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://w.x.y.z.google.com"))); } TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionaryTrailingDot) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the HD with D being the domain and H having a dot requirement. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://w.x.y.z.google.com."))); } TEST_F(SdchManagerTest, FailToSetRepeatPrefixWithDotDictionary) { // Make sure that a prefix that matches the domain postfix won't confuse // the validation checks. std::string dictionary_domain("www.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the HD with D being the domain and H having a dot requirement. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://www.google.com.www.google.com"))); } TEST_F(SdchManagerTest, CanSetLeadingDotDomainDictionary) { // Make sure that a prefix that matches the domain postfix won't confuse // the validation checks. std::string dictionary_domain(".google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Verify that a leading dot in the domain is acceptable, as long as the host // name does not contain any dots preceding the matched domain name. EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://www.google.com"))); } TEST_F(SdchManagerTest, CanSetLeadingDotDomainDictionaryFromURLWithTrailingDot) { // Make sure that a prefix that matches the domain postfix won't confuse // the validation checks. std::string dictionary_domain(".google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Verify that a leading dot in the domain is acceptable, as long as the host // name does not contain any dots preceding the matched domain name. EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://www.google.com."))); } TEST_F(SdchManagerTest, CannotSetLeadingDotDomainDictionary) { // Make sure that a prefix that matches the domain postfix won't confuse // the validation checks. std::string dictionary_domain(".google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Verify that a leading dot in the domain does not affect the name containing // dots failure. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://www.subdomain.google.com"))); } TEST_F(SdchManagerTest, CannotSetLeadingDotDomainDictionaryTrailingDot) { // Make sure that a prefix that matches the domain postfix won't confuse // the validation checks. std::string dictionary_domain(".google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Verify that a trailing period in the URL doesn't affect the check. EXPECT_FALSE(AddSdchDictionary(dictionary_text, GURL("http://www.subdomain.google.com."))); } // Make sure the order of the tests is not helping us or confusing things. // See test CanSetExactMatchDictionary above for first try. TEST_F(SdchManagerTest, CanStillSetExactMatchDictionary) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Perfect match should *STILL* work. EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); } TEST_F(SdchManagerTest, PathMatch) { bool (*PathMatch)(const std::string& path, const std::string& restriction) = SdchManager::Dictionary::PathMatch; // Perfect match is supported. EXPECT_TRUE(PathMatch("/search", "/search")); EXPECT_TRUE(PathMatch("/search/", "/search/")); // Prefix only works if last character of restriction is a slash, or first // character in path after a match is a slash. Validate each case separately. // Rely on the slash in the path (not at the end of the restriction). EXPECT_TRUE(PathMatch("/search/something", "/search")); EXPECT_TRUE(PathMatch("/search/s", "/search")); EXPECT_TRUE(PathMatch("/search/other", "/search")); EXPECT_TRUE(PathMatch("/search/something", "/search")); // Rely on the slash at the end of the restriction. EXPECT_TRUE(PathMatch("/search/something", "/search/")); EXPECT_TRUE(PathMatch("/search/s", "/search/")); EXPECT_TRUE(PathMatch("/search/other", "/search/")); EXPECT_TRUE(PathMatch("/search/something", "/search/")); // Make sure less that sufficient prefix match is false. EXPECT_FALSE(PathMatch("/sear", "/search")); EXPECT_FALSE(PathMatch("/", "/search")); EXPECT_FALSE(PathMatch(std::string(), "/search")); // Add examples with several levels of direcories in the restriction. EXPECT_FALSE(PathMatch("/search/something", "search/s")); EXPECT_FALSE(PathMatch("/search/", "/search/s")); // Make sure adding characters to path will also fail. EXPECT_FALSE(PathMatch("/searching", "/search/")); EXPECT_FALSE(PathMatch("/searching", "/search")); // Make sure we're case sensitive. EXPECT_FALSE(PathMatch("/ABC", "/abc")); EXPECT_FALSE(PathMatch("/abc", "/ABC")); } // The following are only applicable while we have a latency test in the code, // and can be removed when that functionality is stripped. TEST_F(SdchManagerTest, LatencyTestControls) { GURL url("http://www.google.com"); GURL url2("http://www.google2.com"); // First make sure we default to false. EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); // That we can set each to true. sdch_manager()->SetAllowLatencyExperiment(url, true); EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url)); EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); sdch_manager()->SetAllowLatencyExperiment(url2, true); EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url)); EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2)); // And can reset them to false. sdch_manager()->SetAllowLatencyExperiment(url, false); EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2)); sdch_manager()->SetAllowLatencyExperiment(url2, false); EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url)); EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2)); } TEST_F(SdchManagerTest, CanUseMultipleManagers) { SdchManager second_manager; std::string dictionary_domain_1("x.y.z.google.com"); std::string dictionary_domain_2("x.y.z.chromium.org"); std::string dictionary_text_1(NewSdchDictionary(dictionary_domain_1)); std::string dictionary_text_2(NewSdchDictionary(dictionary_domain_2)); std::string tmp_hash; std::string server_hash_1; std::string server_hash_2; SdchManager::GenerateHash(dictionary_text_1, &tmp_hash, &server_hash_1); SdchManager::GenerateHash(dictionary_text_2, &tmp_hash, &server_hash_2); // Confirm that if you add directories to one manager, you // can't get them from the other. EXPECT_TRUE(AddSdchDictionary(dictionary_text_1, GURL("http://" + dictionary_domain_1))); scoped_ptr dict_set; SdchProblemCode problem_code; dict_set = sdch_manager()->GetDictionarySetByHash( GURL("http://" + dictionary_domain_1 + "/random_url"), server_hash_1, &problem_code); EXPECT_TRUE(dict_set); EXPECT_TRUE(dict_set->GetDictionary(server_hash_1)); EXPECT_EQ(SDCH_OK, problem_code); second_manager.AddSdchDictionary( dictionary_text_2, GURL("http://" + dictionary_domain_2), nullptr); dict_set = second_manager.GetDictionarySetByHash( GURL("http://" + dictionary_domain_2 + "/random_url"), server_hash_2, &problem_code); EXPECT_TRUE(dict_set); EXPECT_TRUE(dict_set->GetDictionary(server_hash_2)); EXPECT_EQ(SDCH_OK, problem_code); dict_set = sdch_manager()->GetDictionarySetByHash( GURL("http://" + dictionary_domain_2 + "/random_url"), server_hash_2, &problem_code); EXPECT_FALSE(dict_set); EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code); dict_set = second_manager.GetDictionarySetByHash( GURL("http://" + dictionary_domain_1 + "/random_url"), server_hash_1, &problem_code); EXPECT_FALSE(dict_set); EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code); } TEST_F(SdchManagerTest, HttpsCorrectlySupported) { GURL url("http://www.google.com"); GURL secure_url("https://www.google.com"); bool expect_https_support = true; SdchProblemCode expected_code = expect_https_support ? SDCH_OK : SDCH_SECURE_SCHEME_NOT_SUPPORTED; EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(url)); EXPECT_EQ(expected_code, sdch_manager()->IsInSupportedDomain(secure_url)); SdchManager::EnableSecureSchemeSupport(!expect_https_support); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(url)); EXPECT_NE(expected_code, sdch_manager()->IsInSupportedDomain(secure_url)); } TEST_F(SdchManagerTest, ClearDictionaryData) { std::string dictionary_domain("x.y.z.google.com"); GURL blacklist_url("http://bad.chromium.org"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); std::string tmp_hash; std::string server_hash; SdchManager::GenerateHash(dictionary_text, &tmp_hash, &server_hash); EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://" + dictionary_domain))); scoped_ptr dict_set; SdchProblemCode problem_code; dict_set = sdch_manager()->GetDictionarySetByHash( GURL("http://" + dictionary_domain + "/random_url"), server_hash, &problem_code); EXPECT_TRUE(dict_set); EXPECT_TRUE(dict_set->GetDictionary(server_hash)); EXPECT_EQ(SDCH_OK, problem_code); sdch_manager()->BlacklistDomain(GURL(blacklist_url), SDCH_OK); EXPECT_EQ(SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET, sdch_manager()->IsInSupportedDomain(blacklist_url)); sdch_manager()->ClearData(); dict_set = sdch_manager()->GetDictionarySetByHash( GURL("http://" + dictionary_domain + "/random_url"), server_hash, &problem_code); EXPECT_FALSE(dict_set); EXPECT_EQ(SDCH_DICTIONARY_HASH_NOT_FOUND, problem_code); EXPECT_EQ(SDCH_OK, sdch_manager()->IsInSupportedDomain(blacklist_url)); } TEST_F(SdchManagerTest, GetDictionaryNotification) { GURL test_request_gurl(GURL("http://www.example.com/data")); GURL test_dictionary_gurl(GURL("http://www.example.com/dict")); MockSdchObserver observer; sdch_manager()->AddObserver(&observer); EXPECT_EQ(0, observer.get_dictionary_notifications()); sdch_manager()->OnGetDictionary(test_request_gurl, test_dictionary_gurl); EXPECT_EQ(1, observer.get_dictionary_notifications()); EXPECT_EQ(test_request_gurl, observer.last_dictionary_request_url()); EXPECT_EQ(test_dictionary_gurl, observer.last_dictionary_url()); sdch_manager()->RemoveObserver(&observer); sdch_manager()->OnGetDictionary(test_request_gurl, test_dictionary_gurl); EXPECT_EQ(1, observer.get_dictionary_notifications()); EXPECT_EQ(test_request_gurl, observer.last_dictionary_request_url()); EXPECT_EQ(test_dictionary_gurl, observer.last_dictionary_url()); } TEST_F(SdchManagerTest, ExpirationCheckedProperly) { // Create an SDCH dictionary with an expiration time in the past. std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(base::StringPrintf( "Domain: %s\nMax-age: 0\n\n", dictionary_domain.c_str())); dictionary_text.append( kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1); std::string client_hash; std::string server_hash; SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash); GURL target_gurl("http://" + dictionary_domain); AddSdchDictionary(dictionary_text, target_gurl); // It should be visible if looked up by hash whether expired or not. scoped_ptr clock(new base::SimpleTestClock); clock->SetNow(base::Time::Now()); clock->Advance(base::TimeDelta::FromMinutes(5)); SdchProblemCode problem_code; scoped_ptr hash_set( sdch_manager()->GetDictionarySetByHash( target_gurl, server_hash, &problem_code).Pass()); ASSERT_TRUE(hash_set); ASSERT_EQ(SDCH_OK, problem_code); const_cast( hash_set->GetDictionary(server_hash))->SetClockForTesting( clock.Pass()); // Make sure it's not visible for advertisement, but is visible // if looked up by hash. EXPECT_FALSE(sdch_manager()->GetDictionarySet(target_gurl)); EXPECT_TRUE(sdch_manager()->GetDictionarySetByHash( target_gurl, server_hash, &problem_code)); EXPECT_EQ(SDCH_OK, problem_code); } TEST_F(SdchManagerTest, SdchOnByDefault) { GURL google_url("http://www.google.com"); scoped_ptr sdch_manager(new SdchManager); EXPECT_EQ(SDCH_OK, sdch_manager->IsInSupportedDomain(google_url)); SdchManager::EnableSdchSupport(false); EXPECT_EQ(SDCH_DISABLED, sdch_manager->IsInSupportedDomain(google_url)); } // Confirm dispatch of notification. TEST_F(SdchManagerTest, SdchDictionaryUsed) { MockSdchObserver observer; sdch_manager()->AddObserver(&observer); EXPECT_EQ(0, observer.dictionary_used_notifications()); sdch_manager()->OnDictionaryUsed("xyzzy"); EXPECT_EQ(1, observer.dictionary_used_notifications()); EXPECT_EQ("xyzzy", observer.last_server_hash()); std::string dictionary_domain("x.y.z.google.com"); GURL target_gurl("http://" + dictionary_domain); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); std::string client_hash; std::string server_hash; SdchManager::GenerateHash(dictionary_text, &client_hash, &server_hash); EXPECT_TRUE(AddSdchDictionary(dictionary_text, target_gurl)); EXPECT_EQ("xyzzy", observer.last_server_hash()); EXPECT_EQ(1, observer.dictionary_used_notifications()); EXPECT_TRUE(sdch_manager()->GetDictionarySet(target_gurl)); EXPECT_EQ("xyzzy", observer.last_server_hash()); EXPECT_EQ(1, observer.dictionary_used_notifications()); sdch_manager()->RemoveObserver(&observer); EXPECT_EQ(1, observer.dictionary_used_notifications()); EXPECT_EQ("xyzzy", observer.last_server_hash()); sdch_manager()->OnDictionaryUsed("plugh"); EXPECT_EQ(1, observer.dictionary_used_notifications()); EXPECT_EQ("xyzzy", observer.last_server_hash()); } #else TEST(SdchManagerTest, SdchOffByDefault) { GURL google_url("http://www.google.com"); scoped_ptr sdch_manager(new SdchManager); EXPECT_EQ(SDCH_DISABLED, sdch_manager->IsInSupportedDomain(google_url)); SdchManager::EnableSdchSupport(true); EXPECT_EQ(SDCH_OK, sdch_manager->IsInSupportedDomain(google_url)); } #endif // !defined(OS_IOS) } // namespace net