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
.was_cached
= false;
77 request
.response_info
.network_accessed
= true;
78 request
.response_info
.was_fetched_via_proxy
= false;
79 request
.load_flags
= 0;
80 request
.is_upload
= false;
84 void OnRequestLegComplete(const RequestInfo
& info
) {
85 monitor_
.OnRequestLegComplete(info
);
88 size_t CountPendingBeacons() {
90 context_
->GetQueuedBeaconsForTesting(&beacons
);
91 return beacons
.size();
94 bool CheckRequestCounts(size_t index
,
95 uint32 expected_successful
,
96 uint32 expected_failed
) {
97 return CheckRequestCounts(context_
,
103 bool CheckRequestCounts(DomainReliabilityContext
* context
,
105 uint32 expected_successful
,
106 uint32 expected_failed
) {
107 uint32 successful
, failed
;
108 context
->GetRequestCountsForTesting(index
, &successful
, &failed
);
109 EXPECT_EQ(expected_successful
, successful
);
110 EXPECT_EQ(expected_failed
, failed
);
111 return expected_successful
== successful
&& expected_failed
== failed
;
114 DomainReliabilityContext
* CreateAndAddContext(const std::string
& domain
) {
115 return monitor_
.AddContextForTesting(MakeTestConfigWithDomain(domain
));
118 scoped_refptr
<base::TestSimpleTaskRunner
> pref_task_runner_
;
119 scoped_refptr
<base::TestSimpleTaskRunner
> network_task_runner_
;
120 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
122 DomainReliabilityMonitor monitor_
;
123 DomainReliabilityContext
* context_
;
124 DomainReliabilityMonitor::RequestInfo request_
;
129 TEST_F(DomainReliabilityMonitorTest
, Create
) {
130 EXPECT_EQ(0u, CountPendingBeacons());
131 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
132 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
135 TEST_F(DomainReliabilityMonitorTest
, NoContext
) {
136 RequestInfo request
= MakeRequestInfo();
137 request
.url
= GURL("http://no-context/");
138 OnRequestLegComplete(request
);
140 EXPECT_EQ(0u, CountPendingBeacons());
141 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
142 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
145 TEST_F(DomainReliabilityMonitorTest
, NotReported
) {
146 RequestInfo request
= MakeRequestInfo();
147 request
.url
= GURL("http://example/never_report");
148 OnRequestLegComplete(request
);
150 EXPECT_EQ(0u, CountPendingBeacons());
151 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 1u, 0u));
154 TEST_F(DomainReliabilityMonitorTest
, NetworkFailure
) {
155 RequestInfo request
= MakeRequestInfo();
156 request
.url
= GURL("http://example/always_report");
157 request
.status
.set_status(net::URLRequestStatus::FAILED
);
158 request
.status
.set_error(net::ERR_CONNECTION_RESET
);
159 request
.response_info
.headers
= NULL
;
160 OnRequestLegComplete(request
);
162 EXPECT_EQ(1u, CountPendingBeacons());
163 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
166 TEST_F(DomainReliabilityMonitorTest
, ServerFailure
) {
167 RequestInfo request
= MakeRequestInfo();
168 request
.url
= GURL("http://example/always_report");
169 request
.response_info
.headers
=
170 MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n");
171 OnRequestLegComplete(request
);
173 EXPECT_EQ(1u, CountPendingBeacons());
174 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
177 TEST_F(DomainReliabilityMonitorTest
, NotReportedFailure
) {
178 RequestInfo request
= MakeRequestInfo();
179 request
.url
= GURL("http://example/never_report");
180 request
.status
.set_status(net::URLRequestStatus::FAILED
);
181 request
.status
.set_error(net::ERR_CONNECTION_RESET
);
182 OnRequestLegComplete(request
);
184 EXPECT_EQ(0u, CountPendingBeacons());
185 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 1u));
188 TEST_F(DomainReliabilityMonitorTest
, Request
) {
189 RequestInfo request
= MakeRequestInfo();
190 request
.url
= GURL("http://example/always_report");
191 OnRequestLegComplete(request
);
193 EXPECT_EQ(1u, CountPendingBeacons());
194 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
197 // Make sure the monitor does not log requests that did not access the network.
198 TEST_F(DomainReliabilityMonitorTest
, DidNotAccessNetwork
) {
199 RequestInfo request
= MakeRequestInfo();
200 request
.url
= GURL("http://example/always_report");
201 request
.response_info
.network_accessed
= false;
202 OnRequestLegComplete(request
);
204 EXPECT_EQ(0u, CountPendingBeacons());
205 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
208 // Make sure the monitor does not log requests that don't send cookies.
209 TEST_F(DomainReliabilityMonitorTest
, DoNotSendCookies
) {
210 RequestInfo request
= MakeRequestInfo();
211 request
.url
= GURL("http://example/always_report");
212 request
.load_flags
= net::LOAD_DO_NOT_SEND_COOKIES
;
213 OnRequestLegComplete(request
);
215 EXPECT_EQ(0u, CountPendingBeacons());
216 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
219 // Make sure the monitor does not log upload requests.
220 TEST_F(DomainReliabilityMonitorTest
, IsUpload
) {
221 RequestInfo request
= MakeRequestInfo();
222 request
.url
= GURL("http://example/always_report");
223 request
.is_upload
= true;
224 OnRequestLegComplete(request
);
226 EXPECT_EQ(0u, CountPendingBeacons());
227 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
230 // Make sure the monitor does not log a network-local error.
231 TEST_F(DomainReliabilityMonitorTest
, LocalError
) {
232 RequestInfo request
= MakeRequestInfo();
233 request
.url
= GURL("http://example/always_report");
234 request
.status
.set_status(net::URLRequestStatus::FAILED
);
235 request
.status
.set_error(net::ERR_PROXY_CONNECTION_FAILED
);
236 OnRequestLegComplete(request
);
238 EXPECT_EQ(0u, CountPendingBeacons());
239 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
242 // Make sure the monitor does not log the proxy's IP if one was used.
243 TEST_F(DomainReliabilityMonitorTest
, WasFetchedViaProxy
) {
244 RequestInfo request
= MakeRequestInfo();
245 request
.url
= GURL("http://example/always_report");
246 request
.response_info
.socket_address
=
247 net::HostPortPair::FromString("127.0.0.1:3128");
248 request
.response_info
.was_fetched_via_proxy
= true;
249 OnRequestLegComplete(request
);
251 BeaconVector beacons
;
252 context_
->GetQueuedBeaconsForTesting(&beacons
);
253 EXPECT_EQ(1u, beacons
.size());
254 EXPECT_TRUE(beacons
[0].server_ip
.empty());
256 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
259 // Make sure the monitor does not log the cached IP returned after a successful
260 // cache revalidation request.
261 TEST_F(DomainReliabilityMonitorTest
,
262 NoCachedIPFromSuccessfulRevalidationRequest
) {
263 RequestInfo request
= MakeRequestInfo();
264 request
.url
= GURL("http://example/always_report");
265 request
.response_info
.was_cached
= true;
266 OnRequestLegComplete(request
);
268 BeaconVector beacons
;
269 context_
->GetQueuedBeaconsForTesting(&beacons
);
270 EXPECT_EQ(1u, beacons
.size());
271 EXPECT_TRUE(beacons
[0].server_ip
.empty());
274 // Make sure the monitor does not log the cached IP returned with a failed
275 // cache revalidation request.
276 TEST_F(DomainReliabilityMonitorTest
, NoCachedIPFromFailedRevalidationRequest
) {
277 RequestInfo request
= MakeRequestInfo();
278 request
.url
= GURL("http://example/always_report");
279 request
.response_info
.was_cached
= true;
280 request
.status
.set_status(net::URLRequestStatus::FAILED
);
281 request
.status
.set_error(net::ERR_NAME_RESOLUTION_FAILED
);
282 OnRequestLegComplete(request
);
284 BeaconVector beacons
;
285 context_
->GetQueuedBeaconsForTesting(&beacons
);
286 EXPECT_EQ(1u, beacons
.size());
287 EXPECT_TRUE(beacons
[0].server_ip
.empty());
290 TEST_F(DomainReliabilityMonitorTest
, AtLeastOneBakedInConfig
) {
291 DCHECK(kBakedInJsonConfigs
[0] != NULL
);
294 // Will fail when baked-in configs expire, as a reminder to update them.
295 // (Contact ttuttle@chromium.org if this starts failing.)
296 TEST_F(DomainReliabilityMonitorTest
, AddBakedInConfigs
) {
297 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
298 // this unittest will fail if someone tries to add an invalid config to the
300 monitor_
.AddBakedInConfigs();
302 // Count the number of baked-in configs.
303 size_t num_baked_in_configs
= 0;
304 for (const char* const* p
= kBakedInJsonConfigs
; *p
; ++p
)
305 ++num_baked_in_configs
;
307 // The monitor should have contexts for all of the baked-in configs, plus the
308 // test one added in the test constructor.
309 EXPECT_EQ(num_baked_in_configs
+ 1, monitor_
.contexts_size_for_testing());
312 TEST_F(DomainReliabilityMonitorTest
, ClearBeacons
) {
313 // Initially the monitor should have just the test context, with no beacons.
314 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
315 EXPECT_EQ(0u, CountPendingBeacons());
316 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
317 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
320 RequestInfo request
= MakeRequestInfo();
321 request
.url
= GURL("http://example/always_report");
322 OnRequestLegComplete(request
);
324 // Make sure it was added.
325 EXPECT_EQ(1u, CountPendingBeacons());
326 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
328 monitor_
.ClearBrowsingData(CLEAR_BEACONS
);
330 // Make sure the beacon was cleared, but not the contexts.
331 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
332 EXPECT_EQ(0u, CountPendingBeacons());
333 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
334 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
337 TEST_F(DomainReliabilityMonitorTest
, ClearContexts
) {
338 // Initially the monitor should have just the test context.
339 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
341 monitor_
.ClearBrowsingData(CLEAR_CONTEXTS
);
343 // Clearing contexts should leave the monitor with none.
344 EXPECT_EQ(0u, monitor_
.contexts_size_for_testing());
347 TEST_F(DomainReliabilityMonitorTest
, IgnoreSuccessError
) {
348 RequestInfo request
= MakeRequestInfo();
349 request
.url
= GURL("http://example/always_report");
350 request
.status
.set_error(net::ERR_QUIC_PROTOCOL_ERROR
);
351 OnRequestLegComplete(request
);
353 BeaconVector beacons
;
354 context_
->GetQueuedBeaconsForTesting(&beacons
);
355 EXPECT_EQ(1u, beacons
.size());
356 EXPECT_EQ(net::OK
, beacons
[0].chrome_error
);
358 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
361 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSelf
) {
362 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
364 RequestInfo request
= MakeRequestInfo();
365 request
.url
= GURL("http://wildcard/always_report");
366 OnRequestLegComplete(request
);
367 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
370 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSubdomain
) {
371 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
373 RequestInfo request
= MakeRequestInfo();
374 request
.url
= GURL("http://test.wildcard/always_report");
375 OnRequestLegComplete(request
);
376 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
379 TEST_F(DomainReliabilityMonitorTest
, WildcardDoesntMatchSubsubdomain
) {
380 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
382 RequestInfo request
= MakeRequestInfo();
383 request
.url
= GURL("http://test.test.wildcard/always_report");
384 OnRequestLegComplete(request
);
385 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 0u, 0u));
388 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToSelfWildcard
) {
389 DomainReliabilityContext
* context1
= CreateAndAddContext("wildcard");
390 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
392 RequestInfo request
= MakeRequestInfo();
393 request
.url
= GURL("http://wildcard/always_report");
394 OnRequestLegComplete(request
);
396 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
397 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
400 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToParentWildcard
) {
401 DomainReliabilityContext
* context1
= CreateAndAddContext("test.wildcard");
402 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
404 RequestInfo request
= MakeRequestInfo();
405 request
.url
= GURL("http://test.wildcard/always_report");
406 OnRequestLegComplete(request
);
408 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
409 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
412 TEST_F(DomainReliabilityMonitorTest
,
413 WildcardPrefersSelfWildcardToParentWildcard
) {
414 DomainReliabilityContext
* context1
= CreateAndAddContext("*.test.wildcard");
415 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
417 RequestInfo request
= MakeRequestInfo();
418 request
.url
= GURL("http://test.wildcard/always_report");
419 OnRequestLegComplete(request
);
421 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
422 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
427 } // namespace domain_reliability