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/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"
28 namespace domain_reliability
{
32 typedef std::vector
<DomainReliabilityBeacon
> BeaconVector
;
34 static const size_t kAlwaysReportIndex
= 0u;
35 static const size_t kNeverReportIndex
= 1u;
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())));
46 class DomainReliabilityMonitorTest
: public testing::Test
{
48 typedef DomainReliabilityMonitor::RequestInfo RequestInfo
;
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",
59 scoped_ptr
<MockableTime
>(time_
)),
61 monitor_
.MoveToNetworkThread();
62 monitor_
.InitURLRequestContext(url_request_context_getter_
);
63 monitor_
.SetDiscardUploads(false);
64 context_
= monitor_
.AddContextForTesting(MakeTestConfig());
67 static RequestInfo
MakeRequestInfo() {
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;
83 void OnRequestLegComplete(const RequestInfo
& info
) {
84 monitor_
.OnRequestLegComplete(info
);
87 size_t CountPendingBeacons() {
89 context_
->GetQueuedBeaconsForTesting(&beacons
);
90 return beacons
.size();
93 bool CheckRequestCounts(size_t index
,
94 uint32 expected_successful
,
95 uint32 expected_failed
) {
96 return CheckRequestCounts(context_
,
102 bool CheckRequestCounts(DomainReliabilityContext
* context
,
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
;
113 DomainReliabilityContext
* CreateAndAddContext(const std::string
& domain
) {
114 return monitor_
.AddContextForTesting(MakeTestConfigWithDomain(domain
));
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_
;
121 DomainReliabilityMonitor monitor_
;
122 DomainReliabilityContext
* context_
;
123 DomainReliabilityMonitor::RequestInfo request_
;
128 TEST_F(DomainReliabilityMonitorTest
, Create
) {
129 EXPECT_EQ(0u, CountPendingBeacons());
130 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
131 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
134 TEST_F(DomainReliabilityMonitorTest
, NoContext
) {
135 RequestInfo request
= MakeRequestInfo();
136 request
.url
= GURL("http://no-context/");
137 OnRequestLegComplete(request
);
139 EXPECT_EQ(0u, CountPendingBeacons());
140 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
141 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
144 TEST_F(DomainReliabilityMonitorTest
, NotReported
) {
145 RequestInfo request
= MakeRequestInfo();
146 request
.url
= GURL("http://example/never_report");
147 OnRequestLegComplete(request
);
149 EXPECT_EQ(0u, CountPendingBeacons());
150 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 1u, 0u));
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
);
161 EXPECT_EQ(1u, CountPendingBeacons());
162 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
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
);
172 EXPECT_EQ(1u, CountPendingBeacons());
173 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
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
);
183 EXPECT_EQ(0u, CountPendingBeacons());
184 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 1u));
187 TEST_F(DomainReliabilityMonitorTest
, Request
) {
188 RequestInfo request
= MakeRequestInfo();
189 request
.url
= GURL("http://example/always_report");
190 OnRequestLegComplete(request
);
192 EXPECT_EQ(1u, CountPendingBeacons());
193 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
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
);
203 EXPECT_EQ(0u, CountPendingBeacons());
204 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
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
);
214 EXPECT_EQ(0u, CountPendingBeacons());
215 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
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
);
225 EXPECT_EQ(0u, CountPendingBeacons());
226 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
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
);
237 EXPECT_EQ(0u, CountPendingBeacons());
238 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
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
);
250 BeaconVector beacons
;
251 context_
->GetQueuedBeaconsForTesting(&beacons
);
252 EXPECT_EQ(1u, beacons
.size());
253 EXPECT_TRUE(beacons
[0].server_ip
.empty());
255 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
258 TEST_F(DomainReliabilityMonitorTest
, AtLeastOneBakedInConfig
) {
259 DCHECK(kBakedInJsonConfigs
[0] != NULL
);
262 // Will fail when baked-in configs expire, as a reminder to update them.
263 // (Contact ttuttle@chromium.org if this starts failing.)
264 TEST_F(DomainReliabilityMonitorTest
, AddBakedInConfigs
) {
265 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
266 // this unittest will fail if someone tries to add an invalid config to the
268 monitor_
.AddBakedInConfigs();
270 // Count the number of baked-in configs.
271 size_t num_baked_in_configs
= 0;
272 for (const char* const* p
= kBakedInJsonConfigs
; *p
; ++p
)
273 ++num_baked_in_configs
;
275 // The monitor should have contexts for all of the baked-in configs, plus the
276 // test one added in the test constructor.
277 EXPECT_EQ(num_baked_in_configs
+ 1, monitor_
.contexts_size_for_testing());
280 TEST_F(DomainReliabilityMonitorTest
, ClearBeacons
) {
281 // Initially the monitor should have just the test context, with no beacons.
282 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
283 EXPECT_EQ(0u, CountPendingBeacons());
284 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
285 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
288 RequestInfo request
= MakeRequestInfo();
289 request
.url
= GURL("http://example/always_report");
290 OnRequestLegComplete(request
);
292 // Make sure it was added.
293 EXPECT_EQ(1u, CountPendingBeacons());
294 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
296 monitor_
.ClearBrowsingData(CLEAR_BEACONS
);
298 // Make sure the beacon was cleared, but not the contexts.
299 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
300 EXPECT_EQ(0u, CountPendingBeacons());
301 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
302 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
305 TEST_F(DomainReliabilityMonitorTest
, ClearContexts
) {
306 // Initially the monitor should have just the test context.
307 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
309 monitor_
.ClearBrowsingData(CLEAR_CONTEXTS
);
311 // Clearing contexts should leave the monitor with none.
312 EXPECT_EQ(0u, monitor_
.contexts_size_for_testing());
315 TEST_F(DomainReliabilityMonitorTest
, IgnoreSuccessError
) {
316 RequestInfo request
= MakeRequestInfo();
317 request
.url
= GURL("http://example/always_report");
318 request
.status
.set_error(net::ERR_QUIC_PROTOCOL_ERROR
);
319 OnRequestLegComplete(request
);
321 BeaconVector beacons
;
322 context_
->GetQueuedBeaconsForTesting(&beacons
);
323 EXPECT_EQ(1u, beacons
.size());
324 EXPECT_EQ(net::OK
, beacons
[0].chrome_error
);
326 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
329 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSelf
) {
330 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
332 RequestInfo request
= MakeRequestInfo();
333 request
.url
= GURL("http://wildcard/always_report");
334 OnRequestLegComplete(request
);
335 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
338 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSubdomain
) {
339 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
341 RequestInfo request
= MakeRequestInfo();
342 request
.url
= GURL("http://test.wildcard/always_report");
343 OnRequestLegComplete(request
);
344 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
347 TEST_F(DomainReliabilityMonitorTest
, WildcardDoesntMatchSubsubdomain
) {
348 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
350 RequestInfo request
= MakeRequestInfo();
351 request
.url
= GURL("http://test.test.wildcard/always_report");
352 OnRequestLegComplete(request
);
353 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 0u, 0u));
356 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToSelfWildcard
) {
357 DomainReliabilityContext
* context1
= CreateAndAddContext("wildcard");
358 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
360 RequestInfo request
= MakeRequestInfo();
361 request
.url
= GURL("http://wildcard/always_report");
362 OnRequestLegComplete(request
);
364 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
365 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
368 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToParentWildcard
) {
369 DomainReliabilityContext
* context1
= CreateAndAddContext("test.wildcard");
370 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
372 RequestInfo request
= MakeRequestInfo();
373 request
.url
= GURL("http://test.wildcard/always_report");
374 OnRequestLegComplete(request
);
376 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
377 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
380 TEST_F(DomainReliabilityMonitorTest
,
381 WildcardPrefersSelfWildcardToParentWildcard
) {
382 DomainReliabilityContext
* context1
= CreateAndAddContext("*.test.wildcard");
383 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
385 RequestInfo request
= MakeRequestInfo();
386 request
.url
= GURL("http://test.wildcard/always_report");
387 OnRequestLegComplete(request
);
389 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
390 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
395 } // namespace domain_reliability