• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MakeHttpResponseHeaders(const std::string & headers)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 
DomainReliabilityMonitorTest()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 
MakeRequestInfo()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 
OnRequestLegComplete(const RequestInfo & info)77   void OnRequestLegComplete(const RequestInfo& info) {
78     monitor_.OnRequestLegComplete(info);
79   }
80 
CountPendingBeacons(size_t index)81   size_t CountPendingBeacons(size_t index) {
82     BeaconVector beacons;
83     context_->GetQueuedDataForTesting(index, &beacons, NULL, NULL);
84     return beacons.size();
85   }
86 
CheckRequestCounts(size_t index,uint32 expected_successful,uint32 expected_failed)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 
TEST_F(DomainReliabilityMonitorTest,Create)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 
TEST_F(DomainReliabilityMonitorTest,NoContext)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 
TEST_F(DomainReliabilityMonitorTest,NotReported)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 
TEST_F(DomainReliabilityMonitorTest,NetworkFailure)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 
TEST_F(DomainReliabilityMonitorTest,ServerFailure)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 
TEST_F(DomainReliabilityMonitorTest,NotReportedFailure)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 
TEST_F(DomainReliabilityMonitorTest,Request)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.
TEST_F(DomainReliabilityMonitorTest,DidNotAccessNetwork)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.
TEST_F(DomainReliabilityMonitorTest,DoNotSendCookies)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.
TEST_F(DomainReliabilityMonitorTest,IsUpload)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.
TEST_F(DomainReliabilityMonitorTest,LocalError)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.
TEST_F(DomainReliabilityMonitorTest,WasFetchedViaProxy)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 
TEST_F(DomainReliabilityMonitorTest,AddBakedInConfigs)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 
TEST_F(DomainReliabilityMonitorTest,ClearBeacons)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 
TEST_F(DomainReliabilityMonitorTest,ClearContexts)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 
TEST_F(DomainReliabilityMonitorTest,IgnoreSuccessError)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