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/context.h"
6
7 #include <map>
8 #include <string>
9
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"
20
21 namespace domain_reliability {
22 namespace {
23
24 typedef std::vector<DomainReliabilityBeacon> BeaconVector;
25
MakeBeacon(MockableTime * time)26 DomainReliabilityBeacon MakeBeacon(MockableTime* time) {
27 DomainReliabilityBeacon beacon;
28 beacon.domain = "localhost";
29 beacon.status = "ok";
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;
36 return beacon;
37 }
38
39 class DomainReliabilityContextTest : public testing::Test {
40 protected:
DomainReliabilityContextTest()41 DomainReliabilityContextTest()
42 : dispatcher_(&time_),
43 params_(MakeTestSchedulerParams()),
44 uploader_(base::Bind(&DomainReliabilityContextTest::OnUploadRequest,
45 base::Unretained(this))),
46 upload_reporter_string_("test-reporter"),
47 context_(&time_,
48 params_,
49 upload_reporter_string_,
50 &dispatcher_,
51 &uploader_,
52 MakeTestConfig().Pass()),
53 upload_pending_(false) {}
54
min_delay() const55 TimeDelta min_delay() const { return params_.minimum_upload_delay; }
max_delay() const56 TimeDelta max_delay() const { return params_.maximum_upload_delay; }
retry_interval() const57 TimeDelta retry_interval() const { return params_.upload_retry_interval; }
zero_delta() const58 TimeDelta zero_delta() const { return TimeDelta::FromMicroseconds(0); }
59
upload_pending()60 bool upload_pending() { return upload_pending_; }
61
upload_report()62 const std::string& upload_report() {
63 DCHECK(upload_pending_);
64 return upload_report_;
65 }
66
upload_url()67 const GURL& upload_url() {
68 DCHECK(upload_pending_);
69 return upload_url_;
70 }
71
CallUploadCallback(bool success)72 void CallUploadCallback(bool success) {
73 DCHECK(upload_pending_);
74 upload_callback_.Run(success);
75 upload_pending_ = false;
76 }
77
CheckNoBeacons()78 bool CheckNoBeacons() {
79 BeaconVector beacons;
80 context_.GetQueuedBeaconsForTesting(&beacons);
81 return beacons.empty();
82 }
83
CheckCounts(size_t index,unsigned expected_successful,unsigned expected_failed)84 bool CheckCounts(size_t index,
85 unsigned expected_successful,
86 unsigned expected_failed) {
87 unsigned successful, failed;
88 context_.GetRequestCountsForTesting(index, &successful, &failed);
89 return successful == expected_successful && failed == expected_failed;
90 }
91
92 MockTime time_;
93 DomainReliabilityDispatcher dispatcher_;
94 DomainReliabilityScheduler::Params params_;
95 MockUploader uploader_;
96 std::string upload_reporter_string_;
97 DomainReliabilityContext context_;
98
99 private:
OnUploadRequest(const std::string & report_json,const GURL & upload_url,const DomainReliabilityUploader::UploadCallback & callback)100 void OnUploadRequest(
101 const std::string& report_json,
102 const GURL& upload_url,
103 const DomainReliabilityUploader::UploadCallback& callback) {
104 DCHECK(!upload_pending_);
105 upload_report_ = report_json;
106 upload_url_ = upload_url;
107 upload_callback_ = callback;
108 upload_pending_ = true;
109 }
110
111 bool upload_pending_;
112 std::string upload_report_;
113 GURL upload_url_;
114 DomainReliabilityUploader::UploadCallback upload_callback_;
115 };
116
TEST_F(DomainReliabilityContextTest,Create)117 TEST_F(DomainReliabilityContextTest, Create) {
118 EXPECT_TRUE(CheckNoBeacons());
119 EXPECT_TRUE(CheckCounts(0, 0, 0));
120 EXPECT_TRUE(CheckCounts(1, 0, 0));
121 }
122
TEST_F(DomainReliabilityContextTest,NoResource)123 TEST_F(DomainReliabilityContextTest, NoResource) {
124 GURL url("http://example/no_resource");
125 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
126 context_.OnBeacon(url, beacon);
127
128 EXPECT_TRUE(CheckNoBeacons());
129 EXPECT_TRUE(CheckCounts(0, 0, 0));
130 EXPECT_TRUE(CheckCounts(1, 0, 0));
131 }
132
TEST_F(DomainReliabilityContextTest,NeverReport)133 TEST_F(DomainReliabilityContextTest, NeverReport) {
134 GURL url("http://example/never_report");
135 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
136 context_.OnBeacon(url, beacon);
137
138 EXPECT_TRUE(CheckNoBeacons());
139 EXPECT_TRUE(CheckCounts(0, 0, 0));
140 EXPECT_TRUE(CheckCounts(1, 1, 0));
141 }
142
TEST_F(DomainReliabilityContextTest,AlwaysReport)143 TEST_F(DomainReliabilityContextTest, AlwaysReport) {
144 GURL url("http://example/always_report");
145 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
146 context_.OnBeacon(url, beacon);
147
148 BeaconVector beacons;
149 context_.GetQueuedBeaconsForTesting(&beacons);
150 EXPECT_EQ(1u, beacons.size());
151 EXPECT_TRUE(CheckCounts(0, 1, 0));
152 EXPECT_TRUE(CheckCounts(1, 0, 0));
153 }
154
TEST_F(DomainReliabilityContextTest,ReportUpload)155 TEST_F(DomainReliabilityContextTest, ReportUpload) {
156 GURL url("http://example/always_report");
157 DomainReliabilityBeacon beacon = MakeBeacon(&time_);
158 context_.OnBeacon(url, beacon);
159
160 BeaconVector beacons;
161 context_.GetQueuedBeaconsForTesting(&beacons);
162 EXPECT_EQ(1u, beacons.size());
163 EXPECT_TRUE(CheckCounts(0, 1, 0));
164 EXPECT_TRUE(CheckCounts(1, 0, 0));
165
166 // N.B.: Assumes max_delay is 5 minutes.
167 const char* kExpectedReport = "{"
168 "\"config_version\":\"1\","
169 "\"entries\":[{\"domain\":\"localhost\","
170 "\"http_response_code\":200,\"protocol\":\"HTTP\","
171 "\"request_age_ms\":300250,\"request_elapsed_ms\":250,"
172 "\"resource\":\"always_report\",\"server_ip\":\"127.0.0.1\","
173 "\"status\":\"ok\"}],"
174 "\"reporter\":\"test-reporter\","
175 "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\","
176 "\"successful_requests\":1}]}";
177
178 time_.Advance(max_delay());
179 EXPECT_TRUE(upload_pending());
180 EXPECT_EQ(kExpectedReport, upload_report());
181 EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
182 CallUploadCallback(true);
183
184 EXPECT_TRUE(CheckNoBeacons());
185 EXPECT_TRUE(CheckCounts(0, 0, 0));
186 EXPECT_TRUE(CheckCounts(1, 0, 0));
187 }
188
189 } // namespace
190 } // namespace domain_reliability
191