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/scheduler.h"
8 #include "base/time/time.h"
9 #include "components/domain_reliability/config.h"
10 #include "components/domain_reliability/test_util.h"
11 #include "components/domain_reliability/uploader.h"
12 #include "components/domain_reliability/util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace domain_reliability
{
18 using base::TimeDelta
;
19 using base::TimeTicks
;
21 class DomainReliabilitySchedulerTest
: public testing::Test
{
23 DomainReliabilitySchedulerTest()
25 params_(MakeTestSchedulerParams()),
26 callback_called_(false) {}
28 void CreateScheduler(int num_collectors
) {
29 DCHECK_LT(0, num_collectors
);
32 num_collectors_
= num_collectors
;
33 scheduler_
.reset(new DomainReliabilityScheduler(
37 base::Bind(&DomainReliabilitySchedulerTest::ScheduleUploadCallback
,
38 base::Unretained(this))));
39 scheduler_
->MakeDeterministicForTesting();
42 void NotifySuccessfulUpload() {
43 DomainReliabilityUploader::UploadResult result
;
44 result
.status
= DomainReliabilityUploader::UploadResult::SUCCESS
;
45 scheduler_
->OnUploadComplete(result
);
48 void NotifyFailedUpload() {
49 DomainReliabilityUploader::UploadResult result
;
50 result
.status
= DomainReliabilityUploader::UploadResult::FAILURE
;
51 scheduler_
->OnUploadComplete(result
);
54 void NotifyRetryAfterUpload(base::TimeDelta retry_after
) {
55 DomainReliabilityUploader::UploadResult result
;
56 result
.status
= DomainReliabilityUploader::UploadResult::RETRY_AFTER
;
57 result
.retry_after
= retry_after
;
58 scheduler_
->OnUploadComplete(result
);
61 ::testing::AssertionResult
CheckNoPendingUpload() {
64 if (!callback_called_
)
65 return ::testing::AssertionSuccess();
67 return ::testing::AssertionFailure()
68 << "expected no upload, got upload between "
69 << callback_min_
.InSeconds() << " and "
70 << callback_max_
.InSeconds() << " seconds from now";
73 ::testing::AssertionResult
CheckPendingUpload(TimeDelta expected_min
,
74 TimeDelta expected_max
) {
76 DCHECK_LE(expected_min
.InMicroseconds(), expected_max
.InMicroseconds());
78 if (callback_called_
&& expected_min
== callback_min_
79 && expected_max
== callback_max_
) {
80 callback_called_
= false;
81 return ::testing::AssertionSuccess();
84 if (callback_called_
) {
85 return ::testing::AssertionFailure()
86 << "expected upload between " << expected_min
.InSeconds()
87 << " and " << expected_max
.InSeconds() << " seconds from now, "
88 << "got upload between " << callback_min_
.InSeconds()
89 << " and " << callback_max_
.InSeconds() << " seconds from now";
91 return ::testing::AssertionFailure()
92 << "expected upload between " << expected_min
.InSeconds()
93 << " and " << expected_max
.InSeconds() << " seconds from now, "
98 ::testing::AssertionResult
CheckStartingUpload(size_t expected_collector
) {
100 DCHECK_GT(num_collectors_
, expected_collector
);
102 size_t collector
= scheduler_
->OnUploadStart();
103 if (collector
== expected_collector
)
104 return ::testing::AssertionSuccess();
106 return ::testing::AssertionFailure()
107 << "expected upload to collector " << expected_collector
108 << ", got upload to collector " << collector
;
111 TimeDelta
min_delay() const { return params_
.minimum_upload_delay
; }
112 TimeDelta
max_delay() const { return params_
.maximum_upload_delay
; }
113 TimeDelta
retry_interval() const { return params_
.upload_retry_interval
; }
114 TimeDelta
zero_delta() const { return base::TimeDelta::FromMicroseconds(0); }
117 void ScheduleUploadCallback(TimeDelta min
, TimeDelta max
) {
118 callback_called_
= true;
124 size_t num_collectors_
;
125 DomainReliabilityScheduler::Params params_
;
126 scoped_ptr
<DomainReliabilityScheduler
> scheduler_
;
128 bool callback_called_
;
129 TimeDelta callback_min_
;
130 TimeDelta callback_max_
;
133 TEST_F(DomainReliabilitySchedulerTest
, Create
) {
137 TEST_F(DomainReliabilitySchedulerTest
, UploadNotPendingWithoutBeacon
) {
140 ASSERT_TRUE(CheckNoPendingUpload());
143 TEST_F(DomainReliabilitySchedulerTest
, SuccessfulUploads
) {
146 scheduler_
->OnBeaconAdded();
147 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
148 time_
.Advance(min_delay());
149 ASSERT_TRUE(CheckStartingUpload(0));
150 NotifySuccessfulUpload();
152 scheduler_
->OnBeaconAdded();
153 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
154 time_
.Advance(min_delay());
155 ASSERT_TRUE(CheckStartingUpload(0));
156 NotifySuccessfulUpload();
159 TEST_F(DomainReliabilitySchedulerTest
, RetryAfter
) {
162 base::TimeDelta retry_after_interval
= base::TimeDelta::FromMinutes(30);
164 scheduler_
->OnBeaconAdded();
165 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
166 time_
.Advance(min_delay());
167 ASSERT_TRUE(CheckStartingUpload(0));
168 NotifyRetryAfterUpload(retry_after_interval
);
170 scheduler_
->OnBeaconAdded();
171 ASSERT_TRUE(CheckPendingUpload(retry_after_interval
, retry_after_interval
));
172 time_
.Advance(retry_after_interval
);
173 ASSERT_TRUE(CheckStartingUpload(0));
174 NotifySuccessfulUpload();
177 TEST_F(DomainReliabilitySchedulerTest
, Failover
) {
180 scheduler_
->OnBeaconAdded();
181 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
182 time_
.Advance(min_delay());
183 ASSERT_TRUE(CheckStartingUpload(0));
184 NotifyFailedUpload();
186 scheduler_
->OnBeaconAdded();
187 ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
188 // Don't need to advance; should retry immediately.
189 ASSERT_TRUE(CheckStartingUpload(1));
190 NotifySuccessfulUpload();
193 TEST_F(DomainReliabilitySchedulerTest
, FailedAllCollectors
) {
197 scheduler_
->OnBeaconAdded();
198 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
199 time_
.Advance(min_delay());
202 ASSERT_TRUE(CheckStartingUpload(0));
203 NotifyFailedUpload();
205 ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
206 // Don't need to advance; should retry immediately.
207 ASSERT_TRUE(CheckStartingUpload(1));
208 NotifyFailedUpload();
210 ASSERT_TRUE(CheckPendingUpload(retry_interval(), max_delay() - min_delay()));
211 time_
.Advance(retry_interval());
213 // T = min_delay + retry_interval
214 ASSERT_TRUE(CheckStartingUpload(0));
215 NotifyFailedUpload();
217 ASSERT_TRUE(CheckPendingUpload(
219 max_delay() - min_delay() - retry_interval()));
220 ASSERT_TRUE(CheckStartingUpload(1));
221 NotifyFailedUpload();
224 // Make sure that the scheduler uses the first available collector at upload
225 // time, even if it wasn't available at scheduling time.
226 TEST_F(DomainReliabilitySchedulerTest
, DetermineCollectorAtUpload
) {
230 scheduler_
->OnBeaconAdded();
231 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
232 time_
.Advance(min_delay());
235 ASSERT_TRUE(CheckStartingUpload(0));
236 NotifyFailedUpload();
238 ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
239 time_
.Advance(retry_interval());
241 // T = min_delay + retry_interval; collector 0 should be active again.
242 ASSERT_TRUE(CheckStartingUpload(0));
243 NotifySuccessfulUpload();
246 TEST_F(DomainReliabilitySchedulerTest
, BeaconWhilePending
) {
249 scheduler_
->OnBeaconAdded();
250 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
252 // Second beacon should not call callback again.
253 scheduler_
->OnBeaconAdded();
254 ASSERT_TRUE(CheckNoPendingUpload());
255 time_
.Advance(min_delay());
257 // No pending upload after beacon.
258 ASSERT_TRUE(CheckStartingUpload(0));
259 NotifySuccessfulUpload();
260 ASSERT_TRUE(CheckNoPendingUpload());
263 TEST_F(DomainReliabilitySchedulerTest
, BeaconWhileUploading
) {
266 scheduler_
->OnBeaconAdded();
267 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
268 time_
.Advance(min_delay());
270 // If a beacon arrives during the upload, a new upload should be pending.
271 ASSERT_TRUE(CheckStartingUpload(0));
272 scheduler_
->OnBeaconAdded();
273 NotifySuccessfulUpload();
274 ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
276 time_
.Advance(min_delay());
277 ASSERT_TRUE(CheckStartingUpload(0));
278 NotifySuccessfulUpload();
279 ASSERT_TRUE(CheckNoPendingUpload());
283 } // namespace domain_reliability