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