monitor_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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
28namespace domain_reliability {
29
30namespace {
31
32typedef std::vector<DomainReliabilityBeacon> BeaconVector;
33
34static const size_t kAlwaysReportIndex = 0u;
35static const size_t kNeverReportIndex = 1u;
36
37scoped_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
46class DomainReliabilityMonitorTest : public testing::Test {
47 protected:
48  typedef DomainReliabilityMonitor::RequestInfo RequestInfo;
49
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
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
77  void OnRequestLegComplete(const RequestInfo& info) {
78    monitor_.OnRequestLegComplete(info);
79  }
80
81  size_t CountPendingBeacons(size_t index) {
82    BeaconVector beacons;
83    context_->GetQueuedDataForTesting(index, &beacons, NULL, NULL);
84    return beacons.size();
85  }
86
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
105namespace {
106
107TEST_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
114TEST_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
125TEST_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
134TEST_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
146TEST_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
157TEST_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
168TEST_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.
178TEST_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.
189TEST_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.
200TEST_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.
211TEST_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.
223TEST_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
239TEST_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
255TEST_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
282TEST_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
292TEST_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