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.
5 #include "components/domain_reliability/monitor.h"
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/prefs/pref_registry_simple.h"
15 #include "base/prefs/testing_pref_service.h"
16 #include "base/test/test_simple_task_runner.h"
17 #include "components/domain_reliability/baked_in_configs.h"
18 #include "components/domain_reliability/beacon.h"
19 #include "components/domain_reliability/config.h"
20 #include "components/domain_reliability/test_util.h"
21 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h"
23 #include "net/http/http_response_headers.h"
24 #include "net/http/http_util.h"
25 #include "net/url_request/url_request_context_getter.h"
26 #include "net/url_request/url_request_status.h"
27 #include "net/url_request/url_request_test_util.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 namespace domain_reliability
{
34 typedef std::vector
<DomainReliabilityBeacon
> BeaconVector
;
36 static const size_t kAlwaysReportIndex
= 0u;
37 static const size_t kNeverReportIndex
= 1u;
39 static const char* kPrefName
= "reporting_enabled";
41 scoped_refptr
<net::HttpResponseHeaders
> MakeHttpResponseHeaders(
42 const std::string
& headers
) {
43 return scoped_refptr
<net::HttpResponseHeaders
>(
44 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
45 headers
.c_str(), headers
.length())));
50 class DomainReliabilityMonitorTest
: public testing::Test
{
52 typedef DomainReliabilityMonitor::RequestInfo RequestInfo
;
54 DomainReliabilityMonitorTest()
55 : pref_task_runner_(new base::TestSimpleTaskRunner()),
56 network_task_runner_(new base::TestSimpleTaskRunner()),
57 url_request_context_getter_(
58 new net::TestURLRequestContextGetter(network_task_runner_
)),
59 time_(new MockTime()),
60 pref_service_(CreatePrefService()),
61 monitor_("test-reporter",
66 scoped_ptr
<MockableTime
>(time_
)),
68 monitor_
.MoveToNetworkThread();
69 monitor_
.InitURLRequestContext(url_request_context_getter_
);
70 context_
= monitor_
.AddContextForTesting(MakeTestConfig());
73 static PrefService
* CreatePrefService() {
74 TestingPrefServiceSimple
* prefs
= new TestingPrefServiceSimple();
75 prefs
->registry()->RegisterBooleanPref(kPrefName
, false);
76 prefs
->SetUserPref(kPrefName
, new base::FundamentalValue(true));
80 static RequestInfo
MakeRequestInfo() {
82 request
.status
= net::URLRequestStatus();
83 request
.status
.set_status(net::URLRequestStatus::SUCCESS
);
84 request
.status
.set_error(net::OK
);
85 request
.response_info
.socket_address
=
86 net::HostPortPair::FromString("12.34.56.78:80");
87 request
.response_info
.headers
= MakeHttpResponseHeaders(
88 "HTTP/1.1 200 OK\n\n");
89 request
.response_info
.network_accessed
= true;
90 request
.response_info
.was_fetched_via_proxy
= false;
91 request
.load_flags
= 0;
92 request
.is_upload
= false;
96 void OnRequestLegComplete(const RequestInfo
& info
) {
97 monitor_
.OnRequestLegComplete(info
);
100 size_t CountPendingBeacons() {
101 BeaconVector beacons
;
102 context_
->GetQueuedBeaconsForTesting(&beacons
);
103 return beacons
.size();
106 bool CheckRequestCounts(size_t index
,
107 uint32 expected_successful
,
108 uint32 expected_failed
) {
109 return CheckRequestCounts(context_
,
115 bool CheckRequestCounts(DomainReliabilityContext
* context
,
117 uint32 expected_successful
,
118 uint32 expected_failed
) {
119 uint32 successful
, failed
;
120 context
->GetRequestCountsForTesting(index
, &successful
, &failed
);
121 EXPECT_EQ(expected_successful
, successful
);
122 EXPECT_EQ(expected_failed
, failed
);
123 return expected_successful
== successful
&& expected_failed
== failed
;
126 DomainReliabilityContext
* CreateAndAddContext(const std::string
& domain
) {
127 return monitor_
.AddContextForTesting(MakeTestConfigWithDomain(domain
));
130 scoped_refptr
<base::TestSimpleTaskRunner
> pref_task_runner_
;
131 scoped_refptr
<base::TestSimpleTaskRunner
> network_task_runner_
;
132 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
134 scoped_ptr
<PrefService
> pref_service_
;
135 DomainReliabilityMonitor monitor_
;
136 DomainReliabilityContext
* context_
;
137 DomainReliabilityMonitor::RequestInfo request_
;
142 TEST_F(DomainReliabilityMonitorTest
, Create
) {
143 EXPECT_EQ(0u, CountPendingBeacons());
144 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
145 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
148 TEST_F(DomainReliabilityMonitorTest
, NoContext
) {
149 RequestInfo request
= MakeRequestInfo();
150 request
.url
= GURL("http://no-context/");
151 OnRequestLegComplete(request
);
153 EXPECT_EQ(0u, CountPendingBeacons());
154 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
155 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
158 TEST_F(DomainReliabilityMonitorTest
, NotReported
) {
159 RequestInfo request
= MakeRequestInfo();
160 request
.url
= GURL("http://example/never_report");
161 OnRequestLegComplete(request
);
163 EXPECT_EQ(0u, CountPendingBeacons());
164 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 1u, 0u));
167 TEST_F(DomainReliabilityMonitorTest
, NetworkFailure
) {
168 RequestInfo request
= MakeRequestInfo();
169 request
.url
= GURL("http://example/always_report");
170 request
.status
.set_status(net::URLRequestStatus::FAILED
);
171 request
.status
.set_error(net::ERR_CONNECTION_RESET
);
172 request
.response_info
.headers
= NULL
;
173 OnRequestLegComplete(request
);
175 EXPECT_EQ(1u, CountPendingBeacons());
176 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
179 TEST_F(DomainReliabilityMonitorTest
, ServerFailure
) {
180 RequestInfo request
= MakeRequestInfo();
181 request
.url
= GURL("http://example/always_report");
182 request
.response_info
.headers
=
183 MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n");
184 OnRequestLegComplete(request
);
186 EXPECT_EQ(1u, CountPendingBeacons());
187 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
190 TEST_F(DomainReliabilityMonitorTest
, NotReportedFailure
) {
191 RequestInfo request
= MakeRequestInfo();
192 request
.url
= GURL("http://example/never_report");
193 request
.status
.set_status(net::URLRequestStatus::FAILED
);
194 request
.status
.set_error(net::ERR_CONNECTION_RESET
);
195 OnRequestLegComplete(request
);
197 EXPECT_EQ(0u, CountPendingBeacons());
198 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 1u));
201 TEST_F(DomainReliabilityMonitorTest
, Request
) {
202 RequestInfo request
= MakeRequestInfo();
203 request
.url
= GURL("http://example/always_report");
204 OnRequestLegComplete(request
);
206 EXPECT_EQ(1u, CountPendingBeacons());
207 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
210 // Make sure the monitor does not log requests that did not access the network.
211 TEST_F(DomainReliabilityMonitorTest
, DidNotAccessNetwork
) {
212 RequestInfo request
= MakeRequestInfo();
213 request
.url
= GURL("http://example/always_report");
214 request
.response_info
.network_accessed
= false;
215 OnRequestLegComplete(request
);
217 EXPECT_EQ(0u, CountPendingBeacons());
218 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
221 // Make sure the monitor does not log requests that don't send cookies.
222 TEST_F(DomainReliabilityMonitorTest
, DoNotSendCookies
) {
223 RequestInfo request
= MakeRequestInfo();
224 request
.url
= GURL("http://example/always_report");
225 request
.load_flags
= net::LOAD_DO_NOT_SEND_COOKIES
;
226 OnRequestLegComplete(request
);
228 EXPECT_EQ(0u, CountPendingBeacons());
229 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
232 // Make sure the monitor does not log upload requests.
233 TEST_F(DomainReliabilityMonitorTest
, IsUpload
) {
234 RequestInfo request
= MakeRequestInfo();
235 request
.url
= GURL("http://example/always_report");
236 request
.is_upload
= true;
237 OnRequestLegComplete(request
);
239 EXPECT_EQ(0u, CountPendingBeacons());
240 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
243 // Make sure the monitor does not log a network-local error.
244 TEST_F(DomainReliabilityMonitorTest
, LocalError
) {
245 RequestInfo request
= MakeRequestInfo();
246 request
.url
= GURL("http://example/always_report");
247 request
.status
.set_status(net::URLRequestStatus::FAILED
);
248 request
.status
.set_error(net::ERR_PROXY_CONNECTION_FAILED
);
249 OnRequestLegComplete(request
);
251 EXPECT_EQ(0u, CountPendingBeacons());
252 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
255 // Make sure the monitor does not log the proxy's IP if one was used.
256 TEST_F(DomainReliabilityMonitorTest
, WasFetchedViaProxy
) {
257 RequestInfo request
= MakeRequestInfo();
258 request
.url
= GURL("http://example/always_report");
259 request
.response_info
.socket_address
=
260 net::HostPortPair::FromString("127.0.0.1:3128");
261 request
.response_info
.was_fetched_via_proxy
= true;
262 OnRequestLegComplete(request
);
264 BeaconVector beacons
;
265 context_
->GetQueuedBeaconsForTesting(&beacons
);
266 EXPECT_EQ(1u, beacons
.size());
267 EXPECT_TRUE(beacons
[0].server_ip
.empty());
269 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
272 // Will fail when baked-in configs expire, as a reminder to update them.
273 // (Contact ttuttle@chromium.org if this starts failing.)
274 TEST_F(DomainReliabilityMonitorTest
, AddBakedInConfigs
) {
275 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
276 // this unittest will fail if someone tries to add an invalid config to the
278 monitor_
.AddBakedInConfigs();
280 // Count the number of baked-in configs.
281 size_t num_baked_in_configs
= 0;
282 for (const char* const* p
= kBakedInJsonConfigs
; *p
; ++p
)
283 ++num_baked_in_configs
;
285 // The monitor should have contexts for all of the baked-in configs, plus the
286 // test one added in the test constructor.
287 EXPECT_EQ(num_baked_in_configs
+ 1, monitor_
.contexts_size_for_testing());
290 TEST_F(DomainReliabilityMonitorTest
, ClearBeacons
) {
291 // Initially the monitor should have just the test context, with no beacons.
292 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
293 EXPECT_EQ(0u, CountPendingBeacons());
294 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
295 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
298 RequestInfo request
= MakeRequestInfo();
299 request
.url
= GURL("http://example/always_report");
300 OnRequestLegComplete(request
);
302 // Make sure it was added.
303 EXPECT_EQ(1u, CountPendingBeacons());
304 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
306 monitor_
.ClearBrowsingData(CLEAR_BEACONS
);
308 // Make sure the beacon was cleared, but not the contexts.
309 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
310 EXPECT_EQ(0u, CountPendingBeacons());
311 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
312 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
315 TEST_F(DomainReliabilityMonitorTest
, ClearContexts
) {
316 // Initially the monitor should have just the test context.
317 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
319 monitor_
.ClearBrowsingData(CLEAR_CONTEXTS
);
321 // Clearing contexts should leave the monitor with none.
322 EXPECT_EQ(0u, monitor_
.contexts_size_for_testing());
325 TEST_F(DomainReliabilityMonitorTest
, IgnoreSuccessError
) {
326 RequestInfo request
= MakeRequestInfo();
327 request
.url
= GURL("http://example/always_report");
328 request
.status
.set_error(net::ERR_QUIC_PROTOCOL_ERROR
);
329 OnRequestLegComplete(request
);
331 BeaconVector beacons
;
332 context_
->GetQueuedBeaconsForTesting(&beacons
);
333 EXPECT_EQ(1u, beacons
.size());
334 EXPECT_EQ(net::OK
, beacons
[0].chrome_error
);
336 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
339 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSelf
) {
340 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
342 RequestInfo request
= MakeRequestInfo();
343 request
.url
= GURL("http://wildcard/always_report");
344 OnRequestLegComplete(request
);
345 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
348 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSubdomain
) {
349 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
351 RequestInfo request
= MakeRequestInfo();
352 request
.url
= GURL("http://test.wildcard/always_report");
353 OnRequestLegComplete(request
);
354 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
357 TEST_F(DomainReliabilityMonitorTest
, WildcardDoesntMatchSubsubdomain
) {
358 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
360 RequestInfo request
= MakeRequestInfo();
361 request
.url
= GURL("http://test.test.wildcard/always_report");
362 OnRequestLegComplete(request
);
363 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 0u, 0u));
366 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToSelfWildcard
) {
367 DomainReliabilityContext
* context1
= CreateAndAddContext("wildcard");
368 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
370 RequestInfo request
= MakeRequestInfo();
371 request
.url
= GURL("http://wildcard/always_report");
372 OnRequestLegComplete(request
);
374 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
375 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
378 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToParentWildcard
) {
379 DomainReliabilityContext
* context1
= CreateAndAddContext("test.wildcard");
380 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
382 RequestInfo request
= MakeRequestInfo();
383 request
.url
= GURL("http://test.wildcard/always_report");
384 OnRequestLegComplete(request
);
386 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
387 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
390 TEST_F(DomainReliabilityMonitorTest
,
391 WildcardPrefersSelfWildcardToParentWildcard
) {
392 DomainReliabilityContext
* context1
= CreateAndAddContext("*.test.wildcard");
393 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
395 RequestInfo request
= MakeRequestInfo();
396 request
.url
= GURL("http://test.wildcard/always_report");
397 OnRequestLegComplete(request
);
399 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
400 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
405 } // namespace domain_reliability