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/test/test_simple_task_runner.h"
14 #include "components/domain_reliability/baked_in_configs.h"
15 #include "components/domain_reliability/beacon.h"
16 #include "components/domain_reliability/config.h"
17 #include "components/domain_reliability/test_util.h"
18 #include "net/base/host_port_pair.h"
19 #include "net/base/load_flags.h"
20 #include "net/http/http_response_headers.h"
21 #include "net/http/http_util.h"
22 #include "net/url_request/url_request_context_getter.h"
23 #include "net/url_request/url_request_status.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace domain_reliability
{
31 typedef std::vector
<DomainReliabilityBeacon
> BeaconVector
;
33 static const size_t kAlwaysReportIndex
= 0u;
34 static const size_t kNeverReportIndex
= 1u;
36 scoped_refptr
<net::HttpResponseHeaders
> MakeHttpResponseHeaders(
37 const std::string
& headers
) {
38 return scoped_refptr
<net::HttpResponseHeaders
>(
39 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
40 headers
.c_str(), headers
.length())));
45 class DomainReliabilityMonitorTest
: public testing::Test
{
47 typedef DomainReliabilityMonitor::RequestInfo RequestInfo
;
49 DomainReliabilityMonitorTest()
50 : pref_task_runner_(new base::TestSimpleTaskRunner()),
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",
58 scoped_ptr
<MockableTime
>(time_
)),
60 monitor_
.MoveToNetworkThread();
61 monitor_
.InitURLRequestContext(url_request_context_getter_
);
62 monitor_
.SetDiscardUploads(false);
63 context_
= monitor_
.AddContextForTesting(MakeTestConfig());
66 static RequestInfo
MakeRequestInfo() {
68 request
.status
= net::URLRequestStatus();
69 request
.response_info
.socket_address
=
70 net::HostPortPair::FromString("12.34.56.78:80");
71 request
.response_info
.headers
= MakeHttpResponseHeaders(
72 "HTTP/1.1 200 OK\n\n");
73 request
.response_info
.was_cached
= false;
74 request
.response_info
.network_accessed
= true;
75 request
.response_info
.was_fetched_via_proxy
= false;
76 request
.load_flags
= 0;
77 request
.is_upload
= false;
81 void OnRequestLegComplete(const RequestInfo
& info
) {
82 monitor_
.OnRequestLegComplete(info
);
85 size_t CountPendingBeacons() {
87 context_
->GetQueuedBeaconsForTesting(&beacons
);
88 return beacons
.size();
91 bool CheckRequestCounts(size_t index
,
92 uint32 expected_successful
,
93 uint32 expected_failed
) {
94 return CheckRequestCounts(context_
,
100 bool CheckRequestCounts(DomainReliabilityContext
* context
,
102 uint32 expected_successful
,
103 uint32 expected_failed
) {
104 uint32 successful
, failed
;
105 context
->GetRequestCountsForTesting(index
, &successful
, &failed
);
106 EXPECT_EQ(expected_successful
, successful
);
107 EXPECT_EQ(expected_failed
, failed
);
108 return expected_successful
== successful
&& expected_failed
== failed
;
111 DomainReliabilityContext
* CreateAndAddContext(const std::string
& domain
) {
112 return monitor_
.AddContextForTesting(MakeTestConfigWithDomain(domain
));
115 scoped_refptr
<base::TestSimpleTaskRunner
> pref_task_runner_
;
116 scoped_refptr
<base::TestSimpleTaskRunner
> network_task_runner_
;
117 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
119 DomainReliabilityMonitor monitor_
;
120 DomainReliabilityContext
* context_
;
121 DomainReliabilityMonitor::RequestInfo request_
;
126 TEST_F(DomainReliabilityMonitorTest
, Create
) {
127 EXPECT_EQ(0u, CountPendingBeacons());
128 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
129 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
132 TEST_F(DomainReliabilityMonitorTest
, NoContext
) {
133 RequestInfo request
= MakeRequestInfo();
134 request
.url
= GURL("http://no-context/");
135 OnRequestLegComplete(request
);
137 EXPECT_EQ(0u, CountPendingBeacons());
138 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
139 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
142 TEST_F(DomainReliabilityMonitorTest
, NotReported
) {
143 RequestInfo request
= MakeRequestInfo();
144 request
.url
= GURL("http://example/never_report");
145 OnRequestLegComplete(request
);
147 EXPECT_EQ(0u, CountPendingBeacons());
148 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 1u, 0u));
151 TEST_F(DomainReliabilityMonitorTest
, NetworkFailure
) {
152 RequestInfo request
= MakeRequestInfo();
153 request
.url
= GURL("http://example/always_report");
154 request
.status
= net::URLRequestStatus::FromError(net::ERR_CONNECTION_RESET
);
155 request
.response_info
.headers
= nullptr;
156 OnRequestLegComplete(request
);
158 EXPECT_EQ(1u, CountPendingBeacons());
159 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
162 TEST_F(DomainReliabilityMonitorTest
, ServerFailure
) {
163 RequestInfo request
= MakeRequestInfo();
164 request
.url
= GURL("http://example/always_report");
165 request
.response_info
.headers
=
166 MakeHttpResponseHeaders("HTTP/1.1 500 :(\n\n");
167 OnRequestLegComplete(request
);
169 EXPECT_EQ(1u, CountPendingBeacons());
170 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 1u));
173 TEST_F(DomainReliabilityMonitorTest
, NotReportedFailure
) {
174 RequestInfo request
= MakeRequestInfo();
175 request
.url
= GURL("http://example/never_report");
176 request
.status
= net::URLRequestStatus::FromError(net::ERR_CONNECTION_RESET
);
177 OnRequestLegComplete(request
);
179 EXPECT_EQ(0u, CountPendingBeacons());
180 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 1u));
183 TEST_F(DomainReliabilityMonitorTest
, Request
) {
184 RequestInfo request
= MakeRequestInfo();
185 request
.url
= GURL("http://example/always_report");
186 OnRequestLegComplete(request
);
188 EXPECT_EQ(1u, CountPendingBeacons());
189 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
192 // Make sure the monitor does not log requests that did not access the network.
193 TEST_F(DomainReliabilityMonitorTest
, DidNotAccessNetwork
) {
194 RequestInfo request
= MakeRequestInfo();
195 request
.url
= GURL("http://example/always_report");
196 request
.response_info
.network_accessed
= false;
197 OnRequestLegComplete(request
);
199 EXPECT_EQ(0u, CountPendingBeacons());
200 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
203 // Make sure the monitor does not log requests that don't send cookies.
204 TEST_F(DomainReliabilityMonitorTest
, DoNotSendCookies
) {
205 RequestInfo request
= MakeRequestInfo();
206 request
.url
= GURL("http://example/always_report");
207 request
.load_flags
= net::LOAD_DO_NOT_SEND_COOKIES
;
208 OnRequestLegComplete(request
);
210 EXPECT_EQ(0u, CountPendingBeacons());
211 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
214 // Make sure the monitor does not log upload requests.
215 TEST_F(DomainReliabilityMonitorTest
, IsUpload
) {
216 RequestInfo request
= MakeRequestInfo();
217 request
.url
= GURL("http://example/always_report");
218 request
.is_upload
= true;
219 OnRequestLegComplete(request
);
221 EXPECT_EQ(0u, CountPendingBeacons());
222 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
225 // Make sure the monitor does not log a network-local error.
226 TEST_F(DomainReliabilityMonitorTest
, LocalError
) {
227 RequestInfo request
= MakeRequestInfo();
228 request
.url
= GURL("http://example/always_report");
230 net::URLRequestStatus::FromError(net::ERR_PROXY_CONNECTION_FAILED
);
231 OnRequestLegComplete(request
);
233 EXPECT_EQ(0u, CountPendingBeacons());
234 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
237 // Make sure the monitor does not log the proxy's IP if one was used.
238 TEST_F(DomainReliabilityMonitorTest
, WasFetchedViaProxy
) {
239 RequestInfo request
= MakeRequestInfo();
240 request
.url
= GURL("http://example/always_report");
241 request
.response_info
.socket_address
=
242 net::HostPortPair::FromString("127.0.0.1:3128");
243 request
.response_info
.was_fetched_via_proxy
= true;
244 OnRequestLegComplete(request
);
246 BeaconVector beacons
;
247 context_
->GetQueuedBeaconsForTesting(&beacons
);
248 EXPECT_EQ(1u, beacons
.size());
249 EXPECT_TRUE(beacons
[0].server_ip
.empty());
251 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
254 // Make sure the monitor does not log the cached IP returned after a successful
255 // cache revalidation request.
256 TEST_F(DomainReliabilityMonitorTest
,
257 NoCachedIPFromSuccessfulRevalidationRequest
) {
258 RequestInfo request
= MakeRequestInfo();
259 request
.url
= GURL("http://example/always_report");
260 request
.response_info
.was_cached
= true;
261 OnRequestLegComplete(request
);
263 BeaconVector beacons
;
264 context_
->GetQueuedBeaconsForTesting(&beacons
);
265 EXPECT_EQ(1u, beacons
.size());
266 EXPECT_TRUE(beacons
[0].server_ip
.empty());
269 // Make sure the monitor does not log the cached IP returned with a failed
270 // cache revalidation request.
271 TEST_F(DomainReliabilityMonitorTest
, NoCachedIPFromFailedRevalidationRequest
) {
272 RequestInfo request
= MakeRequestInfo();
273 request
.url
= GURL("http://example/always_report");
274 request
.response_info
.was_cached
= true;
276 net::URLRequestStatus::FromError(net::ERR_NAME_RESOLUTION_FAILED
);
277 OnRequestLegComplete(request
);
279 BeaconVector beacons
;
280 context_
->GetQueuedBeaconsForTesting(&beacons
);
281 EXPECT_EQ(1u, beacons
.size());
282 EXPECT_TRUE(beacons
[0].server_ip
.empty());
285 TEST_F(DomainReliabilityMonitorTest
, AtLeastOneBakedInConfig
) {
286 DCHECK(kBakedInJsonConfigs
[0] != nullptr);
289 // Will fail when baked-in configs expire, as a reminder to update them.
290 // (Contact ttuttle@chromium.org if this starts failing.)
291 TEST_F(DomainReliabilityMonitorTest
, AddBakedInConfigs
) {
292 // AddBakedInConfigs DCHECKs that the baked-in configs parse correctly, so
293 // this unittest will fail if someone tries to add an invalid config to the
295 monitor_
.AddBakedInConfigs();
297 // Count the number of baked-in configs.
298 size_t num_baked_in_configs
= 0;
299 for (const char* const* p
= kBakedInJsonConfigs
; *p
; ++p
)
300 ++num_baked_in_configs
;
302 // The monitor should have contexts for all of the baked-in configs, plus the
303 // test one added in the test constructor.
304 EXPECT_EQ(num_baked_in_configs
+ 1, monitor_
.contexts_size_for_testing());
307 TEST_F(DomainReliabilityMonitorTest
, ClearBeacons
) {
308 // Initially the monitor should have just the test context, with no beacons.
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 RequestInfo request
= MakeRequestInfo();
316 request
.url
= GURL("http://example/always_report");
317 OnRequestLegComplete(request
);
319 // Make sure it was added.
320 EXPECT_EQ(1u, CountPendingBeacons());
321 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
323 monitor_
.ClearBrowsingData(CLEAR_BEACONS
);
325 // Make sure the beacon was cleared, but not the contexts.
326 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
327 EXPECT_EQ(0u, CountPendingBeacons());
328 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 0u, 0u));
329 EXPECT_TRUE(CheckRequestCounts(kNeverReportIndex
, 0u, 0u));
332 TEST_F(DomainReliabilityMonitorTest
, ClearContexts
) {
333 // Initially the monitor should have just the test context.
334 EXPECT_EQ(1u, monitor_
.contexts_size_for_testing());
336 monitor_
.ClearBrowsingData(CLEAR_CONTEXTS
);
338 // Clearing contexts should leave the monitor with none.
339 EXPECT_EQ(0u, monitor_
.contexts_size_for_testing());
342 // TODO(davidben): When https://crbug.com/490311 is resolved, this test can be
344 TEST_F(DomainReliabilityMonitorTest
, IgnoreSuccessError
) {
345 RequestInfo request
= MakeRequestInfo();
346 request
.url
= GURL("http://example/always_report");
347 request
.status
= net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
348 net::ERR_QUIC_PROTOCOL_ERROR
);
349 OnRequestLegComplete(request
);
351 BeaconVector beacons
;
352 context_
->GetQueuedBeaconsForTesting(&beacons
);
353 EXPECT_EQ(1u, beacons
.size());
354 EXPECT_EQ(net::OK
, beacons
[0].chrome_error
);
356 EXPECT_TRUE(CheckRequestCounts(kAlwaysReportIndex
, 1u, 0u));
359 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSelf
) {
360 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
362 RequestInfo request
= MakeRequestInfo();
363 request
.url
= GURL("http://wildcard/always_report");
364 OnRequestLegComplete(request
);
365 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
368 TEST_F(DomainReliabilityMonitorTest
, WildcardMatchesSubdomain
) {
369 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
371 RequestInfo request
= MakeRequestInfo();
372 request
.url
= GURL("http://test.wildcard/always_report");
373 OnRequestLegComplete(request
);
374 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 1u, 0u));
377 TEST_F(DomainReliabilityMonitorTest
, WildcardDoesntMatchSubsubdomain
) {
378 DomainReliabilityContext
* context
= CreateAndAddContext("*.wildcard");
380 RequestInfo request
= MakeRequestInfo();
381 request
.url
= GURL("http://test.test.wildcard/always_report");
382 OnRequestLegComplete(request
);
383 EXPECT_TRUE(CheckRequestCounts(context
, kAlwaysReportIndex
, 0u, 0u));
386 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToSelfWildcard
) {
387 DomainReliabilityContext
* context1
= CreateAndAddContext("wildcard");
388 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
390 RequestInfo request
= MakeRequestInfo();
391 request
.url
= GURL("http://wildcard/always_report");
392 OnRequestLegComplete(request
);
394 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
395 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
398 TEST_F(DomainReliabilityMonitorTest
, WildcardPrefersSelfToParentWildcard
) {
399 DomainReliabilityContext
* context1
= CreateAndAddContext("test.wildcard");
400 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
402 RequestInfo request
= MakeRequestInfo();
403 request
.url
= GURL("http://test.wildcard/always_report");
404 OnRequestLegComplete(request
);
406 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
407 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
410 TEST_F(DomainReliabilityMonitorTest
,
411 WildcardPrefersSelfWildcardToParentWildcard
) {
412 DomainReliabilityContext
* context1
= CreateAndAddContext("*.test.wildcard");
413 DomainReliabilityContext
* context2
= CreateAndAddContext("*.wildcard");
415 RequestInfo request
= MakeRequestInfo();
416 request
.url
= GURL("http://test.wildcard/always_report");
417 OnRequestLegComplete(request
);
419 EXPECT_TRUE(CheckRequestCounts(context1
, kAlwaysReportIndex
, 1u, 0u));
420 EXPECT_TRUE(CheckRequestCounts(context2
, kAlwaysReportIndex
, 0u, 0u));
425 } // namespace domain_reliability