Update mojo sdk to rev c02a28868825edfa57ab77947b8cb15e741c5598
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / sync_scheduler_impl_unittest.cc
bloba88eb56d8c609c2433e1ce8d02b8cdabd8526c72
1 // Copyright 2015 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/proximity_auth/cryptauth/sync_scheduler_impl.h"
7 #include "base/timer/mock_timer.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 namespace proximity_auth {
12 using Strategy = SyncScheduler::Strategy;
13 using SyncState = SyncScheduler::SyncState;
15 namespace {
17 // Constants configuring the the scheduler.
18 const int kElapsedTimeDays = 40;
19 const int kRefreshPeriodDays = 30;
20 const int kRecoveryPeriodSeconds = 10;
21 const double kMaxJitterPercentage = 0.1;
22 const char kTestSchedulerName[] = "TestSyncSchedulerImpl";
24 // Returns true if |jittered_time_delta| is within the range of a jittered
25 // |base_time_delta| with a maximum of |max_jitter_ratio|.
26 bool IsTimeDeltaWithinJitter(const base::TimeDelta& base_time_delta,
27 const base::TimeDelta& jittered_time_delta,
28 double max_jitter_ratio) {
29 if (base_time_delta.is_zero())
30 return jittered_time_delta.is_zero();
32 base::TimeDelta difference =
33 (jittered_time_delta - base_time_delta).magnitude();
34 double percentage_of_base =
35 difference.InMillisecondsF() / base_time_delta.InMillisecondsF();
36 return percentage_of_base < max_jitter_ratio;
39 // Test harness for the SyncSchedulerImpl to create MockTimers.
40 class TestSyncSchedulerImpl : public SyncSchedulerImpl {
41 public:
42 TestSyncSchedulerImpl(Delegate* delegate,
43 base::TimeDelta refresh_period,
44 base::TimeDelta recovery_period,
45 double max_jitter_ratio)
46 : SyncSchedulerImpl(delegate,
47 refresh_period,
48 recovery_period,
49 max_jitter_ratio,
50 kTestSchedulerName) {}
52 ~TestSyncSchedulerImpl() override {}
54 base::MockTimer* timer() { return mock_timer_; }
56 private:
57 scoped_ptr<base::Timer> CreateTimer() override {
58 bool retain_user_task = false;
59 bool is_repeating = false;
60 mock_timer_ = new base::MockTimer(retain_user_task, is_repeating);
61 return make_scoped_ptr(mock_timer_);
64 // A timer instance for testing. Owned by the parent scheduler.
65 base::MockTimer* mock_timer_;
67 DISALLOW_COPY_AND_ASSIGN(TestSyncSchedulerImpl);
70 } // namespace
72 class ProximityAuthSyncSchedulerImplTest : public testing::Test,
73 public SyncSchedulerImpl::Delegate {
74 protected:
75 ProximityAuthSyncSchedulerImplTest()
76 : refresh_period_(base::TimeDelta::FromDays(kRefreshPeriodDays)),
77 base_recovery_period_(
78 base::TimeDelta::FromSeconds(kRecoveryPeriodSeconds)),
79 zero_elapsed_time_(base::TimeDelta::FromSeconds(0)),
80 scheduler_(new TestSyncSchedulerImpl(this,
81 refresh_period_,
82 base_recovery_period_,
83 0)) {}
85 ~ProximityAuthSyncSchedulerImplTest() override {}
87 void OnSyncRequested(
88 scoped_ptr<SyncScheduler::SyncRequest> sync_request) override {
89 sync_request_ = sync_request.Pass();
92 base::MockTimer* timer() { return scheduler_->timer(); }
94 // The time deltas used to configure |scheduler_|.
95 base::TimeDelta refresh_period_;
96 base::TimeDelta base_recovery_period_;
97 base::TimeDelta zero_elapsed_time_;
99 // The scheduler instance under test.
100 scoped_ptr<TestSyncSchedulerImpl> scheduler_;
102 scoped_ptr<SyncScheduler::SyncRequest> sync_request_;
104 DISALLOW_COPY_AND_ASSIGN(ProximityAuthSyncSchedulerImplTest);
107 TEST_F(ProximityAuthSyncSchedulerImplTest, ForceSyncSuccess) {
108 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
109 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
110 EXPECT_EQ(SyncState::WAITING_FOR_REFRESH, scheduler_->GetSyncState());
112 scheduler_->ForceSync();
113 EXPECT_EQ(SyncState::SYNC_IN_PROGRESS, scheduler_->GetSyncState());
114 EXPECT_TRUE(sync_request_);
115 sync_request_->OnDidComplete(true);
116 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
117 EXPECT_EQ(SyncState::WAITING_FOR_REFRESH, scheduler_->GetSyncState());
120 TEST_F(ProximityAuthSyncSchedulerImplTest, ForceSyncFailure) {
121 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
122 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
124 scheduler_->ForceSync();
125 EXPECT_TRUE(sync_request_);
126 sync_request_->OnDidComplete(false);
127 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
130 TEST_F(ProximityAuthSyncSchedulerImplTest, PeriodicRefreshSuccess) {
131 EXPECT_EQ(SyncState::NOT_STARTED, scheduler_->GetSyncState());
132 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
133 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
135 EXPECT_EQ(refresh_period_, timer()->GetCurrentDelay());
136 timer()->Fire();
137 EXPECT_EQ(SyncState::SYNC_IN_PROGRESS, scheduler_->GetSyncState());
138 ASSERT_TRUE(sync_request_.get());
140 sync_request_->OnDidComplete(true);
141 EXPECT_EQ(SyncState::WAITING_FOR_REFRESH, scheduler_->GetSyncState());
142 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
145 TEST_F(ProximityAuthSyncSchedulerImplTest, PeriodicRefreshFailure) {
146 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
147 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
148 timer()->Fire();
149 sync_request_->OnDidComplete(false);
150 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
153 TEST_F(ProximityAuthSyncSchedulerImplTest, AggressiveRecoverySuccess) {
154 scheduler_->Start(zero_elapsed_time_, Strategy::AGGRESSIVE_RECOVERY);
155 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
157 EXPECT_EQ(base_recovery_period_, timer()->GetCurrentDelay());
158 timer()->Fire();
159 EXPECT_EQ(SyncState::SYNC_IN_PROGRESS, scheduler_->GetSyncState());
160 ASSERT_TRUE(sync_request_.get());
162 sync_request_->OnDidComplete(true);
163 EXPECT_EQ(SyncState::WAITING_FOR_REFRESH, scheduler_->GetSyncState());
164 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
167 TEST_F(ProximityAuthSyncSchedulerImplTest, AggressiveRecoveryFailure) {
168 scheduler_->Start(zero_elapsed_time_, Strategy::AGGRESSIVE_RECOVERY);
170 timer()->Fire();
171 sync_request_->OnDidComplete(false);
172 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
175 TEST_F(ProximityAuthSyncSchedulerImplTest, AggressiveRecoveryBackOff) {
176 scheduler_->Start(zero_elapsed_time_, Strategy::AGGRESSIVE_RECOVERY);
177 base::TimeDelta last_recovery_period = base::TimeDelta::FromSeconds(0);
179 for (int i = 0; i < 20; ++i) {
180 timer()->Fire();
181 EXPECT_EQ(SyncState::SYNC_IN_PROGRESS, scheduler_->GetSyncState());
182 sync_request_->OnDidComplete(false);
183 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
184 EXPECT_EQ(SyncState::WAITING_FOR_REFRESH, scheduler_->GetSyncState());
186 base::TimeDelta recovery_period = scheduler_->GetTimeToNextSync();
187 EXPECT_LE(last_recovery_period, recovery_period);
188 last_recovery_period = recovery_period;
191 // Backoffs should rapidly converge to the normal refresh period.
192 EXPECT_EQ(refresh_period_, last_recovery_period);
195 TEST_F(ProximityAuthSyncSchedulerImplTest, RefreshFailureRecoverySuccess) {
196 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
197 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
199 timer()->Fire();
200 sync_request_->OnDidComplete(false);
201 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
203 timer()->Fire();
204 sync_request_->OnDidComplete(true);
205 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
208 TEST_F(ProximityAuthSyncSchedulerImplTest, SyncImmediatelyForPeriodicRefresh) {
209 scheduler_->Start(base::TimeDelta::FromDays(kElapsedTimeDays),
210 Strategy::PERIODIC_REFRESH);
211 EXPECT_TRUE(scheduler_->GetTimeToNextSync().is_zero());
212 EXPECT_TRUE(timer()->GetCurrentDelay().is_zero());
213 timer()->Fire();
214 EXPECT_TRUE(sync_request_);
216 EXPECT_EQ(Strategy::PERIODIC_REFRESH, scheduler_->GetStrategy());
219 TEST_F(ProximityAuthSyncSchedulerImplTest,
220 SyncImmediatelyForAggressiveRecovery) {
221 scheduler_->Start(base::TimeDelta::FromDays(kElapsedTimeDays),
222 Strategy::AGGRESSIVE_RECOVERY);
223 EXPECT_TRUE(scheduler_->GetTimeToNextSync().is_zero());
224 EXPECT_TRUE(timer()->GetCurrentDelay().is_zero());
225 timer()->Fire();
226 EXPECT_TRUE(sync_request_);
228 EXPECT_EQ(Strategy::AGGRESSIVE_RECOVERY, scheduler_->GetStrategy());
231 TEST_F(ProximityAuthSyncSchedulerImplTest, InitialSyncShorterByElapsedTime) {
232 base::TimeDelta elapsed_time = base::TimeDelta::FromDays(2);
233 scheduler_->Start(elapsed_time, Strategy::PERIODIC_REFRESH);
234 EXPECT_EQ(refresh_period_ - elapsed_time, scheduler_->GetTimeToNextSync());
235 timer()->Fire();
236 EXPECT_TRUE(sync_request_);
239 TEST_F(ProximityAuthSyncSchedulerImplTest, PeriodicRefreshJitter) {
240 scheduler_.reset(new TestSyncSchedulerImpl(
241 this, refresh_period_, base_recovery_period_, kMaxJitterPercentage));
243 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
245 base::TimeDelta cumulative_jitter = base::TimeDelta::FromSeconds(0);
246 for (int i = 0; i < 10; ++i) {
247 base::TimeDelta next_sync_delta = scheduler_->GetTimeToNextSync();
248 cumulative_jitter += (next_sync_delta - refresh_period_).magnitude();
249 EXPECT_TRUE(IsTimeDeltaWithinJitter(refresh_period_, next_sync_delta,
250 kMaxJitterPercentage));
251 timer()->Fire();
252 sync_request_->OnDidComplete(true);
255 // The probablility that all periods are randomly equal to |refresh_period_|
256 // is so low that we would expect the heat death of the universe before this
257 // test flakes.
258 EXPECT_FALSE(cumulative_jitter.is_zero());
261 TEST_F(ProximityAuthSyncSchedulerImplTest, JitteredTimeDeltaIsNonNegative) {
262 base::TimeDelta zero_delta = base::TimeDelta::FromSeconds(0);
263 double max_jitter_ratio = 1;
264 scheduler_.reset(new TestSyncSchedulerImpl(this, zero_delta, zero_delta,
265 max_jitter_ratio));
266 scheduler_->Start(zero_elapsed_time_, Strategy::PERIODIC_REFRESH);
268 for (int i = 0; i < 10; ++i) {
269 base::TimeDelta next_sync_delta = scheduler_->GetTimeToNextSync();
270 EXPECT_GE(zero_delta, next_sync_delta);
271 EXPECT_TRUE(
272 IsTimeDeltaWithinJitter(zero_delta, next_sync_delta, max_jitter_ratio));
273 timer()->Fire();
274 sync_request_->OnDidComplete(true);
278 TEST_F(ProximityAuthSyncSchedulerImplTest, StartWithNegativeElapsedTime) {
279 // This could happen in rare cases where the system clock changes.
280 scheduler_->Start(base::TimeDelta::FromDays(-1000),
281 Strategy::PERIODIC_REFRESH);
283 base::TimeDelta zero_delta = base::TimeDelta::FromSeconds(0);
284 EXPECT_EQ(zero_delta, scheduler_->GetTimeToNextSync());
285 EXPECT_EQ(zero_delta, timer()->GetCurrentDelay());
288 } // namespace proximity_auth