Home | History | Annotate | Download | only in spdyproxy
      1 // Copyright 2013 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 "chrome/browser/net/spdyproxy/data_reduction_proxy_settings_unittest.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/md5.h"
      9 #include "base/metrics/field_trial.h"
     10 #include "base/prefs/pref_registry_simple.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/prefs/scoped_user_pref_update.h"
     13 #include "base/prefs/testing_pref_service.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h"
     17 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h"
     18 #include "chrome/browser/prefs/proxy_prefs.h"
     19 #include "chrome/common/chrome_switches.h"
     20 #include "chrome/common/metrics/variations/variations_util.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "components/variations/entropy_provider.h"
     23 #include "net/base/auth.h"
     24 #include "net/base/host_port_pair.h"
     25 #include "net/http/http_auth.h"
     26 #include "net/http/http_auth_cache.h"
     27 #include "net/http/http_response_headers.h"
     28 #include "net/http/http_status_code.h"
     29 #include "net/url_request/test_url_fetcher_factory.h"
     30 #include "testing/gmock/include/gmock/gmock.h"
     31 #include "testing/gtest/include/gtest/gtest.h"
     32 #include "url/gurl.h"
     33 
     34 using testing::_;
     35 using testing::AnyNumber;
     36 using testing::Return;
     37 
     38 const char kDataReductionProxyOrigin[] = "https://foo.com:443/";
     39 const char kDataReductionProxyFallback[] = "http://bar.com:80";
     40 const char kDataReductionProxyAuth[] = "12345";
     41 
     42 const char kProbeURLWithOKResponse[] = "http://ok.org/";
     43 const char kProbeURLWithBadResponse[] = "http://bad.org/";
     44 const char kProbeURLWithNoResponse[] = "http://no.org/";
     45 
     46 // Transform "normal"-looking headers (\n-separated) to the appropriate
     47 // input format for ParseRawHeaders (\0-separated).
     48 void HeadersToRaw(std::string* headers) {
     49   std::replace(headers->begin(), headers->end(), '\n', '\0');
     50   if (!headers->empty())
     51     *headers += '\0';
     52 }
     53 
     54 DataReductionProxySettingsTestBase::DataReductionProxySettingsTestBase()
     55     : testing::Test() {
     56 }
     57 
     58 DataReductionProxySettingsTestBase::~DataReductionProxySettingsTestBase() {}
     59 
     60 void DataReductionProxySettingsTestBase::AddProxyToCommandLine() {
     61   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     62       switches::kSpdyProxyAuthOrigin, kDataReductionProxyOrigin);
     63   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     64       switches::kSpdyProxyAuthFallback, kDataReductionProxyFallback);
     65   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     66       switches::kSpdyProxyAuthValue, kDataReductionProxyAuth);
     67 }
     68 
     69 // testing::Test implementation:
     70 void DataReductionProxySettingsTestBase::SetUp() {
     71   PrefRegistrySimple* registry = pref_service_.registry();
     72   registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
     73   registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
     74   registry->RegisterInt64Pref(
     75       prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
     76   registry->RegisterDictionaryPref(prefs::kProxy);
     77   registry->RegisterBooleanPref(prefs::kSpdyProxyAuthEnabled, false);
     78   registry->RegisterBooleanPref(prefs::kSpdyProxyAuthWasEnabledBefore, false);
     79   ResetSettings();
     80 
     81   ListPrefUpdate original_update(&pref_service_,
     82                                  prefs::kDailyHttpOriginalContentLength);
     83   ListPrefUpdate received_update(&pref_service_,
     84                                  prefs::kDailyHttpReceivedContentLength);
     85   for (int64 i = 0; i < spdyproxy::kNumDaysInHistory; i++) {
     86     original_update->Insert(0, new StringValue(base::Int64ToString(2 * i)));
     87     received_update->Insert(0, new StringValue(base::Int64ToString(i)));
     88   }
     89   last_update_time_ = base::Time::Now().LocalMidnight();
     90   pref_service_.SetInt64(
     91       prefs::kDailyHttpContentLengthLastUpdateDate,
     92       last_update_time_.ToInternalValue());
     93 }
     94 
     95 template <class C>
     96 void DataReductionProxySettingsTestBase::ResetSettings() {
     97   MockDataReductionProxySettings<C>* settings =
     98       new MockDataReductionProxySettings<C>;
     99   EXPECT_CALL(*settings, GetOriginalProfilePrefs())
    100       .Times(AnyNumber())
    101       .WillRepeatedly(Return(&pref_service_));
    102   EXPECT_CALL(*settings, GetLocalStatePrefs())
    103       .Times(AnyNumber())
    104       .WillRepeatedly(Return(&pref_service_));
    105   EXPECT_CALL(*settings, GetURLFetcher()).Times(0);
    106   EXPECT_CALL(*settings, LogProxyState(_, _, _)).Times(0);
    107   settings_.reset(settings);
    108 }
    109 
    110 // Explicitly generate required instantiations.
    111 template void
    112 DataReductionProxySettingsTestBase::ResetSettings<DataReductionProxySettings>();
    113 template void
    114 DataReductionProxySettingsTestBase::ResetSettings<
    115     DataReductionProxySettingsAndroid>();
    116 
    117 template <class C>
    118 void DataReductionProxySettingsTestBase::SetProbeResult(
    119     const std::string& test_url,
    120     const std::string& response,
    121     bool success,
    122     int expected_calls)  {
    123   MockDataReductionProxySettings<C>* settings =
    124       static_cast<MockDataReductionProxySettings<C>*>(settings_.get());
    125   if (0 == expected_calls) {
    126     EXPECT_CALL(*settings, GetURLFetcher()).Times(0);
    127   } else {
    128     EXPECT_CALL(*settings, GetURLFetcher())
    129         .Times(expected_calls)
    130         .WillRepeatedly(Return(new net::FakeURLFetcher(
    131             GURL(test_url),
    132             settings,
    133             response,
    134             success ? net::HTTP_OK : net::HTTP_INTERNAL_SERVER_ERROR,
    135             success ? net::URLRequestStatus::SUCCESS :
    136                       net::URLRequestStatus::FAILED)));
    137   }
    138 }
    139 
    140 // Explicitly generate required instantiations.
    141 template void
    142 DataReductionProxySettingsTestBase::SetProbeResult<DataReductionProxySettings>(
    143     const std::string& test_url,
    144     const std::string& response,
    145     bool success,
    146     int expected_calls);
    147 template void
    148 DataReductionProxySettingsTestBase::SetProbeResult<
    149     DataReductionProxySettingsAndroid>(const std::string& test_url,
    150                                        const std::string& response,
    151                                        bool success,
    152                                        int expected_calls);
    153 
    154 void DataReductionProxySettingsTestBase::CheckProxyPref(
    155     const std::string& expected_servers,
    156     const std::string& expected_mode) {
    157   const DictionaryValue* dict = pref_service_.GetDictionary(prefs::kProxy);
    158   std::string mode;
    159   std::string server;
    160   dict->GetString("mode", &mode);
    161   ASSERT_EQ(expected_mode, mode);
    162   dict->GetString("server", &server);
    163   ASSERT_EQ(expected_servers, server);
    164 }
    165 
    166 void DataReductionProxySettingsTestBase::CheckProxyConfigs(
    167     bool expected_enabled, bool expected_restricted) {
    168   if (expected_enabled) {
    169     std::string main_proxy = kDataReductionProxyOrigin;
    170     std::string fallback_proxy = kDataReductionProxyFallback;
    171     std::string servers = expected_restricted ?
    172         "http=" + fallback_proxy + ",direct://;" :
    173         "http=" + main_proxy + "," + fallback_proxy + ",direct://;";
    174     CheckProxyPref(servers,
    175                    ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
    176   } else {
    177     CheckProxyPref(std::string(), ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
    178   }
    179 }
    180 
    181 void DataReductionProxySettingsTestBase::CheckProbe(
    182     bool initially_enabled,
    183     const std::string& probe_url,
    184     const std::string& response,
    185     bool request_success,
    186     bool expected_enabled,
    187     bool expected_restricted) {
    188   pref_service_.SetBoolean(prefs::kSpdyProxyAuthEnabled, initially_enabled);
    189   settings_->restricted_by_carrier_ = false;
    190   SetProbeResult(
    191       probe_url, response, request_success, initially_enabled ? 1 : 0);
    192   settings_->MaybeActivateDataReductionProxy(false);
    193   base::MessageLoop::current()->RunUntilIdle();
    194   CheckProxyConfigs(expected_enabled, expected_restricted);
    195 }
    196 
    197 void DataReductionProxySettingsTestBase::CheckProbeOnIPChange(
    198     const std::string& probe_url,
    199     const std::string& response,
    200     bool request_success,
    201     bool expected_restricted) {
    202   SetProbeResult(probe_url, response, request_success, 1);
    203   settings_->OnIPAddressChanged();
    204   base::MessageLoop::current()->RunUntilIdle();
    205   CheckProxyConfigs(true, expected_restricted);
    206 }
    207 
    208 void DataReductionProxySettingsTestBase::CheckOnPrefChange(
    209     bool enabled,
    210     bool expected_enabled) {
    211   // Always have a sucessful probe for pref change tests.
    212   SetProbeResult(
    213       kProbeURLWithOKResponse, "OK", true, expected_enabled ? 1 : 0);
    214   pref_service_.SetBoolean(prefs::kSpdyProxyAuthEnabled, enabled);
    215   base::MessageLoop::current()->RunUntilIdle();
    216   // Never expect the proxy to be restricted for pref change tests.
    217   CheckProxyConfigs(expected_enabled, false);
    218 }
    219 
    220 void DataReductionProxySettingsTestBase::CheckInitDataReductionProxy(
    221     bool enabled_at_startup) {
    222   AddProxyToCommandLine();
    223   base::MessageLoop loop(base::MessageLoop::TYPE_UI);
    224   pref_service_.SetBoolean(prefs::kSpdyProxyAuthEnabled, enabled_at_startup);
    225   SetProbeResult(
    226       kProbeURLWithOKResponse, "OK", true, enabled_at_startup ? 1 : 0);
    227   settings_->InitDataReductionProxySettings();
    228   base::MessageLoop::current()->RunUntilIdle();
    229   if (enabled_at_startup) {
    230     CheckProxyConfigs(enabled_at_startup, false);
    231   } else {
    232     // This presumes the proxy preference hadn't been set up by Chrome.
    233     CheckProxyPref(std::string(), std::string());
    234   }
    235 }
    236 
    237 
    238 class DataReductionProxySettingsTest
    239     : public ConcreteDataReductionProxySettingsTest<
    240         DataReductionProxySettings> {
    241 };
    242 
    243 
    244 TEST_F(DataReductionProxySettingsTest, TestAuthenticationInit) {
    245   AddProxyToCommandLine();
    246   net::HttpAuthCache cache;
    247   DataReductionProxySettings::InitDataReductionAuthentication(&cache);
    248   DataReductionProxySettings::DataReductionProxyList proxies =
    249       DataReductionProxySettings::GetDataReductionProxies();
    250   for (DataReductionProxySettings::DataReductionProxyList::iterator it =
    251            proxies.begin();  it != proxies.end(); ++it) {
    252     net::HttpAuthCache::Entry* entry = cache.LookupByPath(*it,
    253                                                           std::string("/"));
    254     EXPECT_TRUE(entry != NULL);
    255     EXPECT_EQ(net::HttpAuth::AUTH_SCHEME_SPDYPROXY, entry->scheme());
    256     EXPECT_EQ("SpdyProxy", entry->auth_challenge().substr(0,9));
    257   }
    258   GURL bad_server = GURL("https://bad.proxy.com/");
    259   net::HttpAuthCache::Entry* entry =
    260       cache.LookupByPath(bad_server, std::string());
    261   EXPECT_TRUE(entry == NULL);
    262 }
    263 
    264 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxyOrigin) {
    265   AddProxyToCommandLine();
    266   // SetUp() adds the origin to the command line, which should be returned here.
    267   std::string result =
    268       DataReductionProxySettings::GetDataReductionProxyOrigin();
    269   EXPECT_EQ(kDataReductionProxyOrigin, result);
    270 }
    271 
    272 TEST_F(DataReductionProxySettingsTest, TestGetDataReductionProxies) {
    273   DataReductionProxySettings::DataReductionProxyList proxies =
    274       DataReductionProxySettings::GetDataReductionProxies();
    275 
    276   unsigned int expected_proxy_size = 0u;
    277 #if defined(SPDY_PROXY_AUTH_ORIGIN)
    278   ++expected_proxy_size;
    279 #endif
    280 #if defined(DATA_REDUCTION_FALLBACK_HOST)
    281   ++expected_proxy_size;
    282 #endif
    283 
    284   EXPECT_EQ(expected_proxy_size, proxies.size());
    285 
    286   // Adding just the fallback on the command line shouldn't add a proxy unless
    287   // there was already one compiled in.
    288   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    289       switches::kSpdyProxyAuthFallback, kDataReductionProxyFallback);
    290   proxies = DataReductionProxySettings::GetDataReductionProxies();
    291 
    292   // So: if there weren't any proxies before, there still won't be.
    293   // If there were one or two, there will be two now.
    294   expected_proxy_size = expected_proxy_size == 0u ? 0u : 2u;
    295 
    296   EXPECT_EQ(expected_proxy_size, proxies.size());
    297 
    298   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    299     switches::kSpdyProxyAuthOrigin, kDataReductionProxyOrigin);
    300   proxies = DataReductionProxySettings::GetDataReductionProxies();
    301   EXPECT_EQ(2u, proxies.size());
    302 
    303   // Command line proxies have precedence, so even if there were other values
    304   // compiled in, these should be the ones in the list.
    305   EXPECT_EQ("foo.com", proxies[0].host());
    306   EXPECT_EQ(443 ,proxies[0].EffectiveIntPort());
    307   EXPECT_EQ("bar.com", proxies[1].host());
    308   EXPECT_EQ(80, proxies[1].EffectiveIntPort());
    309 }
    310 
    311 TEST_F(DataReductionProxySettingsTest, TestAuthHashGeneration) {
    312   AddProxyToCommandLine();
    313   std::string salt = "8675309";  // Jenny's number to test the hash generator.
    314   std::string salted_key = salt + kDataReductionProxyAuth + salt;
    315   base::string16 expected_hash = UTF8ToUTF16(base::MD5String(salted_key));
    316   EXPECT_EQ(expected_hash,
    317             DataReductionProxySettings::AuthHashForSalt(8675309));
    318 }
    319 
    320 // Test that the auth key set by preprocessor directive is not used
    321 // when an origin is set via a switch. This test only does anything useful in
    322 // Chrome builds.
    323 TEST_F(DataReductionProxySettingsTest,
    324        TestAuthHashGenerationWithOriginSetViaSwitch) {
    325   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    326       switches::kSpdyProxyAuthOrigin, kDataReductionProxyOrigin);
    327   EXPECT_EQ(base::string16(),
    328             DataReductionProxySettings::AuthHashForSalt(8675309));
    329 }
    330 
    331 
    332 TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
    333   settings_->InitPrefMembers();
    334   EXPECT_FALSE(settings_->IsDataReductionProxyEnabled());
    335   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
    336 
    337   pref_service_.SetBoolean(prefs::kSpdyProxyAuthEnabled, true);
    338   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
    339   EXPECT_FALSE(settings_->IsDataReductionProxyManaged());
    340 
    341   pref_service_.SetManagedPref(prefs::kSpdyProxyAuthEnabled,
    342                                base::Value::CreateBooleanValue(true));
    343   EXPECT_TRUE(settings_->IsDataReductionProxyEnabled());
    344   EXPECT_TRUE(settings_->IsDataReductionProxyManaged());
    345 }
    346 
    347 
    348 TEST_F(DataReductionProxySettingsTest, TestAcceptableChallenges) {
    349   AddProxyToCommandLine();
    350   typedef struct {
    351     std::string host;
    352     std::string realm;
    353     bool expected_to_succeed;
    354   } challenge_test;
    355 
    356   challenge_test tests[] = {
    357     {"foo.com:443", "", false},                 // 0. No realm.
    358     {"foo.com:443", "xxx", false},              // 1. Wrong realm.
    359     {"foo.com:443", "spdyproxy", false},        // 2. Case matters.
    360     {"foo.com:443", "SpdyProxy", true},         // 3. OK.
    361     {"foo.com:443", "SpdyProxy1234567", true},  // 4. OK
    362     {"bar.com:80", "SpdyProxy1234567", true},   // 5. OK.
    363     {"foo.com:443", "SpdyProxyxxx", true},      // 6. OK
    364     {"", "SpdyProxy1234567", false},            // 7. No challenger.
    365     {"xxx.net:443", "SpdyProxy1234567", false}, // 8. Wrong host.
    366     {"foo.com", "SpdyProxy1234567", false},     // 9. No port.
    367     {"foo.com:80", "SpdyProxy1234567", false},  // 10.Wrong port.
    368     {"bar.com:81", "SpdyProxy1234567", false},  // 11.Wrong port.
    369   };
    370 
    371   for (int i = 0; i <= 11; ++i) {
    372     scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
    373     auth_info->challenger = net::HostPortPair::FromString(tests[i].host);
    374     auth_info->realm = tests[i].realm;
    375     EXPECT_EQ(tests[i].expected_to_succeed,
    376               settings_->IsAcceptableAuthChallenge(auth_info.get()));
    377   }
    378 }
    379 
    380 TEST_F(DataReductionProxySettingsTest, TestChallengeTokens) {
    381   AddProxyToCommandLine();
    382   typedef struct {
    383     std::string realm;
    384     bool expected_empty_token;
    385   } token_test;
    386 
    387   token_test tests[] = {
    388     {"", true},                  // 0. No realm.
    389     {"xxx", true},               // 1. realm too short.
    390     {"spdyproxy", true},         // 2. no salt.
    391     {"SpdyProxyxxx", true},      // 3. Salt not an int.
    392     {"SpdyProxy1234567", false}, // 4. OK
    393   };
    394 
    395   for (int i = 0; i <= 4; ++i) {
    396     scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
    397     auth_info->challenger =
    398         net::HostPortPair::FromString(kDataReductionProxyOrigin);
    399     auth_info->realm = tests[i].realm;
    400     base::string16 token = settings_->GetTokenForAuthChallenge(auth_info.get());
    401     EXPECT_EQ(tests[i].expected_empty_token, token.empty());
    402   }
    403 }
    404 
    405 TEST_F(DataReductionProxySettingsTest, TestResetDataReductionStatistics) {
    406   int64 original_content_length;
    407   int64 received_content_length;
    408   int64 last_update_time;
    409   settings_->ResetDataReductionStatistics();
    410   settings_->GetContentLengths(spdyproxy::kNumDaysInHistory,
    411                                &original_content_length,
    412                                &received_content_length,
    413                                &last_update_time);
    414   EXPECT_EQ(0L, original_content_length);
    415   EXPECT_EQ(0L, received_content_length);
    416   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
    417 }
    418 
    419 TEST_F(DataReductionProxySettingsTest, TestContentLengths) {
    420   int64 original_content_length;
    421   int64 received_content_length;
    422   int64 last_update_time;
    423 
    424   // Request |kNumDaysInHistory| days.
    425   settings_->GetContentLengths(spdyproxy::kNumDaysInHistory,
    426                                &original_content_length,
    427                                &received_content_length,
    428                                &last_update_time);
    429   const unsigned int days = spdyproxy::kNumDaysInHistory;
    430   // Received content length history values are 0 to |kNumDaysInHistory - 1|.
    431   int64 expected_total_received_content_length = (days - 1L) * days / 2;
    432   // Original content length history values are 0 to
    433   // |2 * (kNumDaysInHistory - 1)|.
    434   long expected_total_original_content_length = (days - 1L) * days;
    435   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    436   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    437   EXPECT_EQ(last_update_time_.ToInternalValue(), last_update_time);
    438 
    439   // Request |kNumDaysInHistory - 1| days.
    440   settings_->GetContentLengths(spdyproxy::kNumDaysInHistory - 1,
    441                                &original_content_length,
    442                                &received_content_length,
    443                                &last_update_time);
    444   expected_total_received_content_length -= (days - 1);
    445   expected_total_original_content_length -= 2 * (days - 1);
    446   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    447   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    448 
    449   // Request 0 days.
    450   settings_->GetContentLengths(0,
    451                                &original_content_length,
    452                                &received_content_length,
    453                                &last_update_time);
    454   expected_total_received_content_length = 0;
    455   expected_total_original_content_length = 0;
    456   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    457   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    458 
    459   // Request 1 day. First day had 0 bytes so should be same as 0 days.
    460   settings_->GetContentLengths(1,
    461                                &original_content_length,
    462                                &received_content_length,
    463                                &last_update_time);
    464   EXPECT_EQ(expected_total_original_content_length, original_content_length);
    465   EXPECT_EQ(expected_total_received_content_length, received_content_length);
    466 }
    467 
    468 // TODO(marq): Add a test to verify that MaybeActivateDataReductionProxy
    469 // is called when the pref in |settings_| is enabled.
    470 TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
    471   AddProxyToCommandLine();
    472 
    473   // Initialize the pref member in |settings_| without the usual callback
    474   // so it won't trigger MaybeActivateDataReductionProxy when the pref value
    475   // is set.
    476   settings_->spdy_proxy_auth_enabled_.Init(
    477       prefs::kSpdyProxyAuthEnabled,
    478       settings_->GetOriginalProfilePrefs());
    479 
    480   // TODO(bengr): Test enabling/disabling while a probe is outstanding.
    481   base::MessageLoop loop(base::MessageLoop::TYPE_UI);
    482   // The proxy is enabled and unrestructed initially.
    483   // Request succeeded but with bad response, expect proxy to be restricted.
    484   CheckProbe(true, kProbeURLWithBadResponse, "Bad", true, true, true);
    485   // Request succeeded with valid response, expect proxy to be unrestricted.
    486   CheckProbe(true, kProbeURLWithOKResponse, "OK", true, true, false);
    487   // Request failed, expect proxy to be enabled but restricted.
    488   CheckProbe(true, kProbeURLWithNoResponse, "", false, true, true);
    489   // The proxy is disabled initially. Probes should not be emitted to change
    490   // state.
    491   CheckProbe(false, kProbeURLWithOKResponse, "OK", true, false, false);
    492 }
    493 
    494 TEST_F(DataReductionProxySettingsTest, TestOnIPAddressChanged) {
    495   AddProxyToCommandLine();
    496   base::MessageLoop loop(base::MessageLoop::TYPE_UI);
    497   // The proxy is enabled initially.
    498   settings_->enabled_by_user_ = true;
    499   settings_->restricted_by_carrier_ = false;
    500   settings_->SetProxyConfigs(true, false, true);
    501   // IP address change triggers a probe that succeeds. Proxy remains
    502   // unrestricted.
    503   CheckProbeOnIPChange(kProbeURLWithOKResponse, "OK", true, false);
    504   // IP address change triggers a probe that fails. Proxy is restricted.
    505   CheckProbeOnIPChange(kProbeURLWithBadResponse, "Bad", true, true);
    506   // IP address change triggers a probe that fails. Proxy remains restricted.
    507   CheckProbeOnIPChange(kProbeURLWithBadResponse, "Bad", true, true);
    508   // IP address change triggers a probe that succeed. Proxy is unrestricted.
    509   CheckProbeOnIPChange(kProbeURLWithBadResponse, "OK", true, false);
    510 }
    511 
    512 TEST_F(DataReductionProxySettingsTest, TestOnProxyEnabledPrefChange) {
    513   AddProxyToCommandLine();
    514   settings_->InitPrefMembers();
    515   base::MessageLoop loop(base::MessageLoop::TYPE_UI);
    516   // The proxy is enabled initially.
    517   settings_->enabled_by_user_ = true;
    518   settings_->SetProxyConfigs(true, false, true);
    519   // The pref is disabled, so correspondingly should be the proxy.
    520   CheckOnPrefChange(false, false);
    521   // The pref is enabled, so correspondingly should be the proxy.
    522   CheckOnPrefChange(true, true);
    523 }
    524 
    525 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOn) {
    526   CheckInitDataReductionProxy(true);
    527 }
    528 
    529 TEST_F(DataReductionProxySettingsTest, TestInitDataReductionProxyOff) {
    530   // InitDataReductionProxySettings with the preference off will directly call
    531   // LogProxyState.
    532   MockSettings* settings = static_cast<MockSettings*>(settings_.get());
    533   EXPECT_CALL(*settings, LogProxyState(false, false, true)).Times(1);
    534   CheckInitDataReductionProxy(false);
    535 }
    536 
    537 TEST_F(DataReductionProxySettingsTest, TestGetDailyContentLengths) {
    538   DataReductionProxySettings::ContentLengthList result =
    539       settings_->GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
    540 
    541   ASSERT_FALSE(result.empty());
    542   ASSERT_EQ(spdyproxy::kNumDaysInHistory, result.size());
    543 
    544   for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) {
    545     long expected_length =
    546         static_cast<long>((spdyproxy::kNumDaysInHistory - 1 - i) * 2);
    547     ASSERT_EQ(expected_length, result[i]);
    548   }
    549 }
    550 
    551 TEST_F(DataReductionProxySettingsTest, TestBypassList) {
    552   settings_->AddHostPatternToBypass("http://www.google.com");
    553   settings_->AddHostPatternToBypass("fefe:13::abc/33");
    554   settings_->AddURLPatternToBypass("foo.org/images/*");
    555   settings_->AddURLPatternToBypass("http://foo.com/*");
    556   settings_->AddURLPatternToBypass("http://baz.com:22/bar/*");
    557   settings_->AddURLPatternToBypass("http://*bat.com/bar/*");
    558 
    559   std::string expected[] = {
    560     "http://www.google.com",
    561     "fefe:13::abc/33",
    562     "foo.org",
    563     "http://foo.com",
    564     "http://baz.com:22",
    565     "http://*bat.com"
    566   };
    567 
    568   ASSERT_EQ(settings_->bypass_rules_.size(), 6u);
    569   int i = 0;
    570   for (std::vector<std::string>::iterator it = settings_->bypass_rules_.begin();
    571        it != settings_->bypass_rules_.end(); ++it) {
    572     EXPECT_EQ(expected[i++], *it);
    573   }
    574 }
    575 
    576 TEST_F(DataReductionProxySettingsTest, WasFetchedViaProxy) {
    577   const struct {
    578      const char* headers;
    579      bool expected_result;
    580   } tests[] = {
    581     { "HTTP/1.1 200 OK\n"
    582       "Via: 1.1 Chrome Proxy\n",
    583       false,
    584     },
    585     { "HTTP/1.1 200 OK\n"
    586       "Via: 1.1 Chrome Compression Proxy\n",
    587       true,
    588     },
    589     { "HTTP/1.1 200 OK\n"
    590       "Via: 1.1 Foo Bar, 1.1 Chrome Compression Proxy\n",
    591       true,
    592     },
    593     { "HTTP/1.1 200 OK\n"
    594       "Via: 1.1 Chrome Compression Proxy, 1.1 Bar Foo\n",
    595       true,
    596     },
    597     { "HTTP/1.1 200 OK\n"
    598       "Via: 1.1 chrome compression proxy\n",
    599       false,
    600     },
    601     { "HTTP/1.1 200 OK\n"
    602       "Via: 1.1 Foo Bar\n"
    603       "Via: 1.1 Chrome Compression Proxy\n",
    604       true,
    605     },
    606   };
    607   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
    608     std::string headers(tests[i].headers);
    609     HeadersToRaw(&headers);
    610     scoped_refptr<net::HttpResponseHeaders> parsed(
    611         new net::HttpResponseHeaders(headers));
    612 
    613     EXPECT_EQ(tests[i].expected_result,
    614               DataReductionProxySettings::WasFetchedViaProxy(parsed));
    615   }
    616 }
    617