blob: e910f111622fbdbf082ceab6a459d2dc57d35911 [file] [log] [blame]
// 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 "net/base/sdch_manager.h"
#include <limits.h>
#include <memory>
#include <string>
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/test/simple_test_clock.h"
#include "net/base/sdch_observer.h"
#include "net/log/net_log.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace net {
//------------------------------------------------------------------------------
// 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_added_notifications_(0),
dictionary_removed_notifications_(0),
dictionary_used_notifications_(0),
get_dictionary_notifications_(0),
clear_dictionaries_notifications_(0) {}
int dictionary_added_notifications() const {
return dictionary_added_notifications_;
}
int dictionary_removed_notifications() const {
return dictionary_removed_notifications_;
}
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 OnDictionaryAdded(const GURL& dictionary_url,
const std::string& server_hash) override {
last_server_hash_ = server_hash;
last_dictionary_url_ = dictionary_url;
++dictionary_added_notifications_;
}
void OnDictionaryRemoved(const std::string& server_hash) override {
last_server_hash_ = server_hash;
++dictionary_removed_notifications_;
}
void OnDictionaryUsed(const std::string& server_hash) override {
last_server_hash_ = server_hash;
++dictionary_used_notifications_;
}
void OnGetDictionary(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() override {
++clear_dictionaries_notifications_;
}
private:
int dictionary_added_notifications_;
int dictionary_removed_notifications_;
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) {}
~SdchManagerTest() override {}
SdchManager* sdch_manager() { return sdch_manager_.get(); }
// 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:
std::unique_ptr<SdchManager> sdch_manager_;
};
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");
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));
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;
std::unique_ptr<SdchManager::DictionarySet> 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->GetDictionaryText(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.
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;
std::unique_ptr<SdchManager::DictionarySet> 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));
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;
std::unique_ptr<SdchManager::DictionarySet> 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)));
}
// 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)));
std::unique_ptr<SdchManager::DictionarySet> 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->GetDictionaryText(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->GetDictionaryText(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, 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)));
std::unique_ptr<SdchManager::DictionarySet> 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->GetDictionaryText(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");
// TODO(eroman): "max-age: -1" is invalid -- it is not a valid production of
// delta-seconds (1*DIGIT). This test works because currently an invalid
// max-age results in the dictionary being considered expired on loading
// (crbug.com/602691)
std::string dictionary_text(base::StringPrintf("Domain: %s\nMax-age: -1\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.
SdchProblemCode problem_code;
std::unique_ptr<SdchManager::DictionarySet> hash_set(
sdch_manager()->GetDictionarySetByHash(target_gurl, server_hash,
&problem_code));
ASSERT_TRUE(hash_set);
ASSERT_EQ(SDCH_OK, problem_code);
// 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);
}
// 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(1, observer.dictionary_used_notifications());
EXPECT_TRUE(sdch_manager()->GetDictionarySet(target_gurl));
EXPECT_EQ(1, observer.dictionary_used_notifications());
sdch_manager()->RemoveObserver(&observer);
EXPECT_EQ(1, observer.dictionary_used_notifications());
sdch_manager()->OnDictionaryUsed("plugh");
EXPECT_EQ(1, observer.dictionary_used_notifications());
}
TEST_F(SdchManagerTest, AddRemoveNotifications) {
MockSdchObserver observer;
sdch_manager()->AddObserver(&observer);
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(1, observer.dictionary_added_notifications());
EXPECT_EQ(target_gurl, observer.last_dictionary_url());
EXPECT_EQ(server_hash, observer.last_server_hash());
EXPECT_EQ(SDCH_OK, sdch_manager()->RemoveSdchDictionary(server_hash));
EXPECT_EQ(1, observer.dictionary_removed_notifications());
EXPECT_EQ(server_hash, observer.last_server_hash());
sdch_manager()->RemoveObserver(&observer);
}
} // namespace net