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       : network_task_runner_(new base::TestSimpleTaskRunner()),
     52         url_request_context_getter_(
     53             new net::TestURLRequestContextGetter(network_task_runner_)),
     54         time_(new MockTime()),
     55         monitor_("test-reporter", scoped_ptr<MockableTime>(time_)),
     56         context_(NULL) {
     57     monitor_.Init(url_request_context_getter_);
     58     context_ = monitor_.AddContextForTesting(MakeTestConfig());
     59   }
     60 
     61   static RequestInfo MakeRequestInfo() {
     62     RequestInfo request;
     63     request.status = net::URLRequestStatus();
     64     request.status.set_status(net::URLRequestStatus::SUCCESS);
     65     request.status.set_error(net::OK);
     66     request.response_info.socket_address =
     67         net::HostPortPair::FromString("12.34.56.78:80");
     68     request.response_info.headers = MakeHttpResponseHeaders(
     69         "HTTP/1.1 200 OK\n\n");
     70     request.response_info.network_accessed = true;
     71     request.response_info.was_fetched_via_proxy = false;
     72     request.load_flags = 0;
     73     request.is_upload = false;
     74     return request;
     75   }
     76 
     77   void OnRequestLegComplete(const RequestInfo& info) {
     78     monitor_.OnRequestLegComplete(info);
     79   }
     80 
     81   size_t CountPendingBeacons(size_t index) {
     82     BeaconVector beacons;
     83     context_->GetQueuedDataForTesting(index, &beacons, NULL, NULL);
     84     return beacons.size();
     85   }
     86 
     87   bool CheckRequestCounts(size_t index,
     88                           uint32 expected_successful,
     89                           uint32 expected_failed) {
     90     uint32 successful, failed;
     91     context_->GetQueuedDataForTesting(index, NULL, &successful, &failed);
     92     EXPECT_EQ(expected_successful, successful);
     93     EXPECT_EQ(expected_failed, failed);
     94     return expected_successful == successful && expected_failed == failed;
     95   }
     96 
     97   scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_;
     98   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
     99   MockTime* time_;
    100   DomainReliabilityMonitor monitor_;
    101   DomainReliabilityContext* context_;
    102   DomainReliabilityMonitor::RequestInfo request_;
    103 };
    104 
    105 namespace {
    106 
    107 TEST_F(DomainReliabilityMonitorTest, Create) {
    108   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    109   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    110   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    111   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    112 }
    113 
    114 TEST_F(DomainReliabilityMonitorTest, NoContext) {
    115   RequestInfo request = MakeRequestInfo();
    116   request.url = GURL("http://no-context/");
    117   OnRequestLegComplete(request);
    118 
    119   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    120   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    121   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    122   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    123 }
    124 
    125 TEST_F(DomainReliabilityMonitorTest, NotReported) {
    126   RequestInfo request = MakeRequestInfo();
    127   request.url = GURL("http://example/never_report");
    128   OnRequestLegComplete(request);
    129 
    130   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    131   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 1u, 0u));
    132 }
    133 
    134 TEST_F(DomainReliabilityMonitorTest, NetworkFailure) {
    135   RequestInfo request = MakeRequestInfo();
    136   request.url = GURL("http://example/always_report");
    137   request.status.set_status(net::URLRequestStatus::FAILED);
    138   request.status.set_error(net::ERR_CONNECTION_RESET);
    139   request.response_info.headers = NULL;
    140   OnRequestLegComplete(request);
    141 
    142   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    143   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u));
    144 }
    145 
    146 TEST_F(DomainReliabilityMonitorTest, ServerFailure) {
    147   RequestInfo request = MakeRequestInfo();
    148   request.url = GURL("http://example/always_report");
    149   request.response_info.headers =
    150       MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n");
    151   OnRequestLegComplete(request);
    152 
    153   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    154   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 1u));
    155 }
    156 
    157 TEST_F(DomainReliabilityMonitorTest, NotReportedFailure) {
    158   RequestInfo request = MakeRequestInfo();
    159   request.url = GURL("http://example/never_report");
    160   request.status.set_status(net::URLRequestStatus::FAILED);
    161   request.status.set_error(net::ERR_CONNECTION_RESET);
    162   OnRequestLegComplete(request);
    163 
    164   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    165   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 1u));
    166 }
    167 
    168 TEST_F(DomainReliabilityMonitorTest, Request) {
    169   RequestInfo request = MakeRequestInfo();
    170   request.url = GURL("http://example/always_report");
    171   OnRequestLegComplete(request);
    172 
    173   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    174   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    175 }
    176 
    177 // Make sure the monitor does not log requests that did not access the network.
    178 TEST_F(DomainReliabilityMonitorTest, DidNotAccessNetwork) {
    179   RequestInfo request = MakeRequestInfo();
    180   request.url = GURL("http://example/always_report");
    181   request.response_info.network_accessed = false;
    182   OnRequestLegComplete(request);
    183 
    184   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    185   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    186 }
    187 
    188 // Make sure the monitor does not log requests that don't send cookies.
    189 TEST_F(DomainReliabilityMonitorTest, DoNotSendCookies) {
    190   RequestInfo request = MakeRequestInfo();
    191   request.url = GURL("http://example/always_report");
    192   request.load_flags = net::LOAD_DO_NOT_SEND_COOKIES;
    193   OnRequestLegComplete(request);
    194 
    195   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    196   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    197 }
    198 
    199 // Make sure the monitor does not log upload requests.
    200 TEST_F(DomainReliabilityMonitorTest, IsUpload) {
    201   RequestInfo request = MakeRequestInfo();
    202   request.url = GURL("http://example/always_report");
    203   request.is_upload = true;
    204   OnRequestLegComplete(request);
    205 
    206   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    207   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    208 }
    209 
    210 // Make sure the monitor does not log a network-local error.
    211 TEST_F(DomainReliabilityMonitorTest, LocalError) {
    212   RequestInfo request = MakeRequestInfo();
    213   request.url = GURL("http://example/always_report");
    214   request.status.set_status(net::URLRequestStatus::FAILED);
    215   request.status.set_error(net::ERR_PROXY_CONNECTION_FAILED);
    216   OnRequestLegComplete(request);
    217 
    218   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    219   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    220 }
    221 
    222 // Make sure the monitor does not log the proxy's IP if one was used.
    223 TEST_F(DomainReliabilityMonitorTest, WasFetchedViaProxy) {
    224   RequestInfo request = MakeRequestInfo();
    225   request.url = GURL("http://example/always_report");
    226   request.response_info.socket_address =
    227       net::HostPortPair::FromString("127.0.0.1:3128");
    228   request.response_info.was_fetched_via_proxy = true;
    229   OnRequestLegComplete(request);
    230 
    231   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    232   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    233 
    234   BeaconVector beacons;
    235   context_->GetQueuedDataForTesting(kAlwaysReportIndex, &beacons, NULL, NULL);
    236   EXPECT_TRUE(beacons[0].server_ip.empty());
    237 }
    238 
    239 TEST_F(DomainReliabilityMonitorTest, AddBakedInConfigs) {
    240   // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
    241   // this unittest will fail if someone tries to add an invalid config to the
    242   // source tree.
    243   monitor_.AddBakedInConfigs();
    244 
    245   // Count the number of baked-in configs.
    246   size_t num_baked_in_configs = 0;
    247   for (const char* const* p = kBakedInJsonConfigs; *p; ++p)
    248     ++num_baked_in_configs;
    249 
    250   // The monitor should have contexts for all of the baked-in configs, plus the
    251   // test one added in the test constructor.
    252   EXPECT_EQ(num_baked_in_configs + 1, monitor_.contexts_size_for_testing());
    253 }
    254 
    255 TEST_F(DomainReliabilityMonitorTest, ClearBeacons) {
    256   // Initially the monitor should have just the test context, with no beacons.
    257   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    258   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    259   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    260   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    261   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    262 
    263   // Add a beacon.
    264   RequestInfo request = MakeRequestInfo();
    265   request.url = GURL("http://example/always_report");
    266   OnRequestLegComplete(request);
    267 
    268   // Make sure it was added.
    269   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    270   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    271 
    272   monitor_.ClearBrowsingData(CLEAR_BEACONS);
    273 
    274   // Make sure the beacon was cleared, but not the contexts.
    275   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    276   EXPECT_EQ(0u, CountPendingBeacons(kAlwaysReportIndex));
    277   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 0u, 0u));
    278   EXPECT_EQ(0u, CountPendingBeacons(kNeverReportIndex));
    279   EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex, 0u, 0u));
    280 }
    281 
    282 TEST_F(DomainReliabilityMonitorTest, ClearContexts) {
    283   // Initially the monitor should have just the test context.
    284   EXPECT_EQ(1u, monitor_.contexts_size_for_testing());
    285 
    286   monitor_.ClearBrowsingData(CLEAR_CONTEXTS);
    287 
    288   // Clearing contexts should leave the monitor with none.
    289   EXPECT_EQ(0u, monitor_.contexts_size_for_testing());
    290 }
    291 
    292 TEST_F(DomainReliabilityMonitorTest, IgnoreSuccessError) {
    293   RequestInfo request = MakeRequestInfo();
    294   request.url = GURL("http://example/always_report");
    295   request.status.set_error(net::ERR_QUIC_PROTOCOL_ERROR);
    296   OnRequestLegComplete(request);
    297 
    298   EXPECT_EQ(1u, CountPendingBeacons(kAlwaysReportIndex));
    299   EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex, 1u, 0u));
    300 
    301   BeaconVector beacons;
    302   context_->GetQueuedDataForTesting(kAlwaysReportIndex, &beacons, NULL, NULL);
    303   EXPECT_EQ(net::OK, beacons[0].chrome_error);
    304 }
    305 
    306 }  // namespace
    307 
    308 }  // namespace domain_reliability
    309