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/context.h"
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "components/domain_reliability/beacon.h"
14 #include "components/domain_reliability/dispatcher.h"
15 #include "components/domain_reliability/scheduler.h"
16 #include "components/domain_reliability/test_util.h"
17 #include "net/base/net_errors.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 namespace domain_reliability {
24 typedef std::vector<DomainReliabilityBeacon> BeaconVector;
26 DomainReliabilityBeacon MakeBeacon(MockableTime* time) {
27 DomainReliabilityBeacon beacon;
28 beacon.domain = "localhost";
30 beacon.chrome_error = net::OK;
31 beacon.server_ip = "127.0.0.1";
32 beacon.protocol = "HTTP";
33 beacon.http_response_code = 200;
34 beacon.elapsed = base::TimeDelta::FromMilliseconds(250);
35 beacon.start_time = time->NowTicks() - beacon.elapsed;
39 class DomainReliabilityContextTest : public testing::Test {
41 DomainReliabilityContextTest()
42 : last_network_change_time_(time_.NowTicks()),
44 params_(MakeTestSchedulerParams()),
45 uploader_(base::Bind(&DomainReliabilityContextTest::OnUploadRequest,
46 base::Unretained(this))),
47 upload_reporter_string_("test-reporter"),
50 upload_reporter_string_,
51 &last_network_change_time_,
54 MakeTestConfig().Pass()),
55 upload_pending_(false) {
56 // Make sure that the last network change does not overlap requests
57 // made in test cases, which start 250ms in the past (see |MakeBeacon|).
58 last_network_change_time_ = time_.NowTicks();
59 time_.Advance(base::TimeDelta::FromSeconds(1));
62 TimeDelta min_delay() const { return params_.minimum_upload_delay; }
63 TimeDelta max_delay() const { return params_.maximum_upload_delay; }
64 TimeDelta retry_interval() const { return params_.upload_retry_interval; }
65 TimeDelta zero_delta() const { return TimeDelta::FromMicroseconds(0); }
67 bool upload_pending() { return upload_pending_; }
69 const std::string& upload_report() {
70 DCHECK(upload_pending_);
71 return upload_report_;
74 const GURL& upload_url() {
75 DCHECK(upload_pending_);
79 void CallUploadCallback(bool success) {
80 DCHECK(upload_pending_);
81 upload_callback_.Run(success);
82 upload_pending_ = false;
85 bool CheckNoBeacons() {
87 context_.GetQueuedBeaconsForTesting(&beacons);
88 return beacons.empty();
91 bool CheckCounts(size_t index,
92 unsigned expected_successful,
93 unsigned expected_failed) {
94 unsigned successful, failed;
95 context_.GetRequestCountsForTesting(index, &successful, &failed);
96 return successful == expected_successful && failed == expected_failed;
100 base::TimeTicks last_network_change_time_;
101 DomainReliabilityDispatcher dispatcher_;
102 DomainReliabilityScheduler::Params params_;
103 MockUploader uploader_;
104 std::string upload_reporter_string_;
105 DomainReliabilityContext context_;
108 void OnUploadRequest(
109 const std::string& report_json,
110 const GURL& upload_url,
111 const DomainReliabilityUploader::UploadCallback& callback) {
112 DCHECK(!upload_pending_);
113 upload_report_ = report_json;
114 upload_url_ = upload_url;
115 upload_callback_ = callback;
116 upload_pending_ = true;
119 bool upload_pending_;
120 std::string upload_report_;
122 DomainReliabilityUploader::UploadCallback upload_callback_;
125 TEST_F(DomainReliabilityContextTest, Create) {
126 EXPECT_TRUE(CheckNoBeacons());
127 EXPECT_TRUE(CheckCounts(0, 0, 0));
128 EXPECT_TRUE(CheckCounts(1, 0, 0));
131 TEST_F(DomainReliabilityContextTest, NoResource) {
132 GURL url("http://example/no_resource");
133 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
134 context_.OnBeacon(url, beacon);
136 EXPECT_TRUE(CheckNoBeacons());
137 EXPECT_TRUE(CheckCounts(0, 0, 0));
138 EXPECT_TRUE(CheckCounts(1, 0, 0));
141 TEST_F(DomainReliabilityContextTest, NeverReport) {
142 GURL url("http://example/never_report");
143 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
144 context_.OnBeacon(url, beacon);
146 EXPECT_TRUE(CheckNoBeacons());
147 EXPECT_TRUE(CheckCounts(0, 0, 0));
148 EXPECT_TRUE(CheckCounts(1, 1, 0));
151 TEST_F(DomainReliabilityContextTest, AlwaysReport) {
152 GURL url("http://example/always_report");
153 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
154 context_.OnBeacon(url, beacon);
156 BeaconVector beacons;
157 context_.GetQueuedBeaconsForTesting(&beacons);
158 EXPECT_EQ(1u, beacons.size());
159 EXPECT_TRUE(CheckCounts(0, 1, 0));
160 EXPECT_TRUE(CheckCounts(1, 0, 0));
163 TEST_F(DomainReliabilityContextTest, ReportUpload) {
164 GURL url("http://example/always_report");
165 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
166 context_.OnBeacon(url, beacon);
168 BeaconVector beacons;
169 context_.GetQueuedBeaconsForTesting(&beacons);
170 EXPECT_EQ(1u, beacons.size());
171 EXPECT_TRUE(CheckCounts(0, 1, 0));
172 EXPECT_TRUE(CheckCounts(1, 0, 0));
174 // N.B.: Assumes max_delay is 5 minutes.
175 const char* kExpectedReport = "{"
176 "\"config_version\":\"1\","
177 "\"entries\":[{\"domain\":\"localhost\","
178 "\"http_response_code\":200,\"network_changed\":false,"
179 "\"protocol\":\"HTTP\",\"request_age_ms\":300250,"
180 "\"request_elapsed_ms\":250,\"resource\":\"always_report\","
181 "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"}],"
182 "\"reporter\":\"test-reporter\","
183 "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\","
184 "\"successful_requests\":1}]}";
186 time_.Advance(max_delay());
187 EXPECT_TRUE(upload_pending());
188 EXPECT_EQ(kExpectedReport, upload_report());
189 EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
190 CallUploadCallback(true);
192 EXPECT_TRUE(CheckNoBeacons());
193 EXPECT_TRUE(CheckCounts(0, 0, 0));
194 EXPECT_TRUE(CheckCounts(1, 0, 0));
197 TEST_F(DomainReliabilityContextTest, ReportUpload_NetworkChanged) {
198 GURL url("http://example/always_report");
199 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
200 context_.OnBeacon(url, beacon);
202 BeaconVector beacons;
203 context_.GetQueuedBeaconsForTesting(&beacons);
204 EXPECT_EQ(1u, beacons.size());
205 EXPECT_TRUE(CheckCounts(0, 1, 0));
206 EXPECT_TRUE(CheckCounts(1, 0, 0));
208 // N.B.: Assumes max_delay is 5 minutes.
209 const char* kExpectedReport = "{"
210 "\"config_version\":\"1\","
211 "\"entries\":[{\"domain\":\"localhost\","
212 "\"http_response_code\":200,\"network_changed\":true,"
213 "\"protocol\":\"HTTP\",\"request_age_ms\":300250,"
214 "\"request_elapsed_ms\":250,\"resource\":\"always_report\","
215 "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"}],"
216 "\"reporter\":\"test-reporter\","
217 "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\","
218 "\"successful_requests\":1}]}";
220 // Simulate a network change after the request but before the upload.
221 last_network_change_time_ = time_.NowTicks();
222 time_.Advance(max_delay());
224 EXPECT_TRUE(upload_pending());
225 EXPECT_EQ(kExpectedReport, upload_report());
226 EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
227 CallUploadCallback(true);
229 EXPECT_TRUE(CheckNoBeacons());
230 EXPECT_TRUE(CheckCounts(0, 0, 0));
231 EXPECT_TRUE(CheckCounts(1, 0, 0));
235 } // namespace domain_reliability