Home | History | Annotate | Download | only in domain_reliability
      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 "components/domain_reliability/monitor.h"
      6 
      7 #include <map>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/bind.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/message_loop/message_loop_proxy.h"
     14 #include "base/test/test_simple_task_runner.h"
     15 #include "components/domain_reliability/baked_in_configs.h"
     16 #include "components/domain_reliability/beacon.h"
     17 #include "components/domain_reliability/config.h"
     18 #include "components/domain_reliability/test_util.h"
     19 #include "net/base/host_port_pair.h"
     20 #include "net/base/load_flags.h"
     21 #include "net/http/http_response_headers.h"
     22 #include "net/http/http_util.h"
     23 #include "net/url_request/url_request_context_getter.h"
     24 #include "net/url_request/url_request_status.h"
     25 #include "net/url_request/url_request_test_util.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 
     28 namespace domain_reliability {
     29 
     30 namespace {
     31 
     32 typedef std::vector<DomainReliabilityBeacon> BeaconVector;
     33 
     34 static const size_t kAlwaysReportIndex = 0u;
     35 static const size_t kNeverReportIndex = 1u;
     36 
     37 scoped_refptr<net::HttpResponseHeaders> MakeHttpResponseHeaders(
     38     const std::string& headers) {
     39   return scoped_refptr<net::HttpResponseHeaders>(
     40       new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
     41           headers.c_str(), headers.length())));
     42 }
     43 
     44 }  // namespace
     45 
     46 class DomainReliabilityMonitorTest : public testing::Test {
     47  protected:
     48   typedef DomainReliabilityMonitor::RequestInfo RequestInfo;
     49 
     50   DomainReliabilityMonitorTest()
     51       : pref_task_runner_(new base::TestSimpleTaskRunner()),
     52         network_task_runner_(new base::TestSimpleTaskRunner()),
     53         url_request_context_getter_(
     54             new net::TestURLRequestContextGetter(network_task_runner_)),
     55         time_(new MockTime()),
     56         monitor_("test-reporter",
     57                  pref_task_runner_,
     58                  network_task_runner_,
     59                  scoped_ptr<MockableTime>(time_)),
     60         context_(NULL) {
     61     monitor_.MoveToNetworkThread();
     62     monitor_.InitURLRequestContext(url_request_context_getter_);
     63     monitor_.SetDiscardUploads(false);
     64     context_ = monitor_.AddContextForTesting(MakeTestConfig());
     65   }
     66 
     67   static RequestInfo MakeRequestInfo() {
     68     RequestInfo request;
     69     request.status = net::URLRequestStatus();
     70     request.status.set_status(net::URLRequestStatus::SUCCESS);
     71     request.status.set_error(net::OK);
     72     request.response_info.socket_address =
     73         net::HostPortPair::FromString("12.34.56.78:80");
     74     request.response_info.headers = MakeHttpResponseHeaders(
     75         "HTTP/1.1 200 OK\n\n");
     76     request.response_info.network_accessed = true;
     77     request.response_info.was_fetched_via_proxy = false;
     78     request.load_flags = 0;
     79     request.is_upload = false;
     80     return request;
     81   }
     82 
     83   void OnRequestLegComplete(const RequestInfo& info) {
     84     monitor_.OnRequestLegComplete(info);
     85   }
     86 
     87   size_t CountPendingBeacons() {
     88     BeaconVector beacons;
     89     context_->GetQueuedBeaconsForTesting(&beacons);
     90     return beacons.size();
     91   }
     92 
     93   bool CheckRequestCounts(size_t index,
     94                           uint32 expected_successful,
     95                           uint32 expected_failed) {
     96     return CheckRequestCounts(context_,
     97                               index,
     98                               expected_successful,
     99                               expected_failed);
    100   }
    101 
    102   bool CheckRequestCounts(DomainReliabilityContext* context,
    103                           size_t index,
    104                           uint32 expected_successful,
    105                           uint32 expected_failed) {
    106     uint32 successful, failed;
    107     context->GetRequestCountsForTesting(index, &successful, &failed);
    108     EXPECT_EQ(expected_successful, successful);
    109     EXPECT_EQ(expected_failed, failed);
    110     return expected_successful == successful && expected_failed == failed;
    111   }
    112 
    113   DomainReliabilityContext* CreateAndAddContext(const std::string& domain) {
    114     return monitor_.AddContextForTesting(MakeTestConfigWithDomain(domain));
    115   }
    116 
    117   scoped_refptr<base::TestSimpleTaskRunner> pref_task_runner_;
    118   scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_;
    119   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
    120   MockTime* time_;
    121   DomainReliabilityMonitor monitor_;
    122   DomainReliabilityContext* context_;
    123   DomainReliabilityMonitor::RequestInfo request_;
    124 };
    125 
    126 namespace {
    127 
    128 TEST_F(DomainReliabilityMonitorTest, Create) {
    129   EXPECT_EQ(0u, CountPendingBeacons());
    130   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    131   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    132 }
    133 
    134 TEST_F(DomainReliabilityMonitorTest, NoContext) {
    135   RequestInfo request = MakeRequestInfo();
    136   request.url = GURL("http://no-context/");
    137   OnRequestLegComplete(request);
    138 
    139   EXPECT_EQ(0u, CountPendingBeacons());
    140   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    141   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    142 }
    143 
    144 TEST_F(DomainReliabilityMonitorTest, NotReported) {
    145   RequestInfo request = MakeRequestInfo();
    146   request.url = GURL("http://example/never_report");
    147   OnRequestLegComplete(request);
    148 
    149   EXPECT_EQ(0u, CountPendingBeacons());
    150   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 1u, 0u));
    151 }
    152 
    153 TEST_F(DomainReliabilityMonitorTest, NetworkFailure) {
    154   RequestInfo request = MakeRequestInfo();
    155   request.url = GURL("http://example/always_report");
    156   request.status.set_status(net::URLRequestStatus::FAILED);
    157   request.status.set_error(net::ERR_CONNECTION_RESET);
    158   request.response_info.headers = NULL;
    159   OnRequestLegComplete(request);
    160 
    161   EXPECT_EQ(1u, CountPendingBeacons());
    162   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u));
    163 }
    164 
    165 TEST_F(DomainReliabilityMonitorTest, ServerFailure) {
    166   RequestInfo request = MakeRequestInfo();
    167   request.url = GURL("http://example/always_report");
    168   request.response_info.headers =
    169       MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n");
    170   OnRequestLegComplete(request);
    171 
    172   EXPECT_EQ(1u, CountPendingBeacons());
    173   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u));
    174 }
    175 
    176 TEST_F(DomainReliabilityMonitorTest, NotReportedFailure) {
    177   RequestInfo request = MakeRequestInfo();
    178   request.url = GURL("http://example/never_report");
    179   request.status.set_status(net::URLRequestStatus::FAILED);
    180   request.status.set_error(net::ERR_CONNECTION_RESET);
    181   OnRequestLegComplete(request);
    182 
    183   EXPECT_EQ(0u, CountPendingBeacons());
    184   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 1u));
    185 }
    186 
    187 TEST_F(DomainReliabilityMonitorTest, Request) {
    188   RequestInfo request = MakeRequestInfo();
    189   request.url = GURL("http://example/always_report");
    190   OnRequestLegComplete(request);
    191 
    192   EXPECT_EQ(1u, CountPendingBeacons());
    193   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    194 }
    195 
    196 // Make sure the monitor does not log requests that did not access the network.
    197 TEST_F(DomainReliabilityMonitorTest, DidNotAccessNetwork) {
    198   RequestInfo request = MakeRequestInfo();
    199   request.url = GURL("http://example/always_report");
    200   request.response_info.network_accessed = false;
    201   OnRequestLegComplete(request);
    202 
    203   EXPECT_EQ(0u, CountPendingBeacons());
    204   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    205 }
    206 
    207 // Make sure the monitor does not log requests that don't send cookies.
    208 TEST_F(DomainReliabilityMonitorTest, DoNotSendCookies) {
    209   RequestInfo request = MakeRequestInfo();
    210   request.url = GURL("http://example/always_report");
    211   request.load_flags = net::LOAD_DO_NOT_SEND_COOKIES;
    212   OnRequestLegComplete(request);
    213 
    214   EXPECT_EQ(0u, CountPendingBeacons());
    215   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    216 }
    217 
    218 // Make sure the monitor does not log upload requests.
    219 TEST_F(DomainReliabilityMonitorTest, IsUpload) {
    220   RequestInfo request = MakeRequestInfo();
    221   request.url = GURL("http://example/always_report");
    222   request.is_upload = true;
    223   OnRequestLegComplete(request);
    224 
    225   EXPECT_EQ(0u, CountPendingBeacons());
    226   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    227 }
    228 
    229 // Make sure the monitor does not log a network-local error.
    230 TEST_F(DomainReliabilityMonitorTest, LocalError) {
    231   RequestInfo request = MakeRequestInfo();
    232   request.url = GURL("http://example/always_report");
    233   request.status.set_status(net::URLRequestStatus::FAILED);
    234   request.status.set_error(net::ERR_PROXY_CONNECTION_FAILED);
    235   OnRequestLegComplete(request);
    236 
    237   EXPECT_EQ(0u, CountPendingBeacons());
    238   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    239 }
    240 
    241 // Make sure the monitor does not log the proxy's IP if one was used.
    242 TEST_F(DomainReliabilityMonitorTest, WasFetchedViaProxy) {
    243   RequestInfo request = MakeRequestInfo();
    244   request.url = GURL("http://example/always_report");
    245   request.response_info.socket_address =
    246       net::HostPortPair::FromString("127.0.0.1:3128");
    247   request.response_info.was_fetched_via_proxy = true;
    248   OnRequestLegComplete(request);
    249 
    250   BeaconVector beacons;
    251   context_->GetQueuedBeaconsForTesting(&beacons);
    252   EXPECT_EQ(1u, beacons.size());
    253   EXPECT_TRUE(beacons[0].server_ip.empty());
    254 
    255   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    256 }
    257 
    258 // Will fail when baked-in configs expire, as a reminder to update them.
    259 // (Contact ttuttle (at) chromium.org if this starts failing.)
    260 TEST_F(DomainReliabilityMonitorTest, AddBakedInConfigs) {
    261   // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
    262   // this unittest will fail if someone tries to add an invalid config to the
    263   // source tree.
    264   monitor_.AddBakedInConfigs();
    265 
    266   // Count the number of baked-in configs.
    267   size_t num_baked_in_configs = 0;
    268   for (const char* const* p = kBakedInJsonConfigs; *p; ++p)
    269     ++num_baked_in_configs;
    270 
    271   // The monitor should have contexts for all of the baked-in configs, plus the
    272   // test one added in the test constructor.
    273   EXPECT_EQ(num_baked_in_configs + 1, monitor_.contexts_size_for_testing());
    274 }
    275 
    276 TEST_F(DomainReliabilityMonitorTest, ClearBeacons) {
    277   // Initially the monitor should have just the test context, with no beacons.
    278   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    279   EXPECT_EQ(0u, CountPendingBeacons());
    280   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    281   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    282 
    283   // Add a beacon.
    284   RequestInfo request = MakeRequestInfo();
    285   request.url = GURL("http://example/always_report");
    286   OnRequestLegComplete(request);
    287 
    288   // Make sure it was added.
    289   EXPECT_EQ(1u, CountPendingBeacons());
    290   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    291 
    292   monitor_.ClearBrowsingData(CLEAR_BEACONS);
    293 
    294   // Make sure the beacon was cleared, but not the contexts.
    295   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    296   EXPECT_EQ(0u, CountPendingBeacons());
    297   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    298   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    299 }
    300 
    301 TEST_F(DomainReliabilityMonitorTest, ClearContexts) {
    302   // Initially the monitor should have just the test context.
    303   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    304 
    305   monitor_.ClearBrowsingData(CLEAR_CONTEXTS);
    306 
    307   // Clearing contexts should leave the monitor with none.
    308   EXPECT_EQ(0u, monitor_.contexts_size_for_testing());
    309 }
    310 
    311 TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) {
    312   RequestInfo request = MakeRequestInfo();
    313   request.url = GURL("http://example/always_report");
    314   request.status.set_error(net::ERR_QUIC_PROTOCOL_ERROR);
    315   OnRequestLegComplete(request);
    316 
    317   BeaconVector beacons;
    318   context_->GetQueuedBeaconsForTesting(&beacons);
    319   EXPECT_EQ(1u, beacons.size());
    320   EXPECT_EQ(net::OK, beacons[0].chrome_error);
    321 
    322   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    323 }
    324 
    325 TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSelf) {
    326   DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
    327 
    328   RequestInfo request = MakeRequestInfo();
    329   request.url = GURL("http://wildcard/always_report");
    330   OnRequestLegComplete(request);
    331   EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u));
    332 }
    333 
    334 TEST_F(DomainReliabilityMonitorTest, WildcardMatchesSubdomain) {
    335   DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
    336 
    337   RequestInfo request = MakeRequestInfo();
    338   request.url = GURL("http://test.wildcard/always_report");
    339   OnRequestLegComplete(request);
    340   EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 1u, 0u));
    341 }
    342 
    343 TEST_F(DomainReliabilityMonitorTest, WildcardDoesntMatchSubsubdomain) {
    344   DomainReliabilityContext* context = CreateAndAddContext("*.wildcard");
    345 
    346   RequestInfo request = MakeRequestInfo();
    347   request.url = GURL("http://test.test.wildcard/always_report");
    348   OnRequestLegComplete(request);
    349   EXPECT_TRUE(CheckRequestCounts(context, kAlwaysReportIndex, 0u, 0u));
    350 }
    351 
    352 TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToSelfWildcard) {
    353   DomainReliabilityContext* context1 = CreateAndAddContext("wildcard");
    354   DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
    355 
    356   RequestInfo request = MakeRequestInfo();
    357   request.url = GURL("http://wildcard/always_report");
    358   OnRequestLegComplete(request);
    359 
    360   EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
    361   EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
    362 }
    363 
    364 TEST_F(DomainReliabilityMonitorTest, WildcardPrefersSelfToParentWildcard) {
    365   DomainReliabilityContext* context1 = CreateAndAddContext("test.wildcard");
    366   DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
    367 
    368   RequestInfo request = MakeRequestInfo();
    369   request.url = GURL("http://test.wildcard/always_report");
    370   OnRequestLegComplete(request);
    371 
    372   EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
    373   EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
    374 }
    375 
    376 TEST_F(DomainReliabilityMonitorTest,
    377     WildcardPrefersSelfWildcardToParentWildcard) {
    378   DomainReliabilityContext* context1 = CreateAndAddContext("*.test.wildcard");
    379   DomainReliabilityContext* context2 = CreateAndAddContext("*.wildcard");
    380 
    381   RequestInfo request = MakeRequestInfo();
    382   request.url = GURL("http://test.wildcard/always_report");
    383   OnRequestLegComplete(request);
    384 
    385   EXPECT_TRUE(CheckRequestCounts(context1, kAlwaysReportIndex, 1u, 0u));
    386   EXPECT_TRUE(CheckRequestCounts(context2, kAlwaysReportIndex, 0u, 0u));
    387 }
    388 
    389 }  // namespace
    390 
    391 }  // namespace domain_reliability
    392