Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / sync_file_system / sync_process_runner_unittest.cc
bloba1bd4b7f62288ab8839e172a57a586895256d4ca
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 "chrome/browser/sync_file_system/sync_process_runner.h"
7 #include <queue>
9 #include "base/memory/scoped_ptr.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace sync_file_system {
14 namespace {
16 class FakeClient : public SyncProcessRunner::Client {
17 public:
18 FakeClient() : service_state_(SYNC_SERVICE_RUNNING) {}
19 ~FakeClient() override {}
21 SyncServiceState GetSyncServiceState() override { return service_state_; }
23 SyncFileSystemService* GetSyncService() override { return nullptr; }
25 void set_service_state(SyncServiceState service_state) {
26 service_state_ = service_state;
29 private:
30 SyncServiceState service_state_;
32 DISALLOW_COPY_AND_ASSIGN(FakeClient);
35 class FakeTimerHelper : public SyncProcessRunner::TimerHelper {
36 public:
37 FakeTimerHelper() {}
38 ~FakeTimerHelper() override {}
40 bool IsRunning() override { return !timer_task_.is_null(); }
42 void Start(const tracked_objects::Location& from_here,
43 const base::TimeDelta& delay,
44 const base::Closure& closure) override {
45 scheduled_time_ = current_time_ + delay;
46 timer_task_ = closure;
49 base::TimeTicks Now() const override { return current_time_; }
51 void SetCurrentTime(const base::TimeTicks& current_time) {
52 current_time_ = current_time;
53 if (current_time_ < scheduled_time_ || timer_task_.is_null())
54 return;
56 base::Closure task = timer_task_;
57 timer_task_.Reset();
58 task.Run();
61 void AdvanceToScheduledTime() {
62 SetCurrentTime(scheduled_time_);
65 int64 GetCurrentDelay() {
66 EXPECT_FALSE(timer_task_.is_null());
67 return (scheduled_time_ - current_time_).InMilliseconds();
70 private:
71 base::TimeTicks current_time_;
72 base::TimeTicks scheduled_time_;
73 base::Closure timer_task_;
75 DISALLOW_COPY_AND_ASSIGN(FakeTimerHelper);
78 class FakeSyncProcessRunner : public SyncProcessRunner {
79 public:
80 FakeSyncProcessRunner(SyncProcessRunner::Client* client,
81 scoped_ptr<TimerHelper> timer_helper,
82 size_t max_parallel_task)
83 : SyncProcessRunner("FakeSyncProcess",
84 client, timer_helper.Pass(),
85 max_parallel_task),
86 max_parallel_task_(max_parallel_task) {
89 void StartSync(const SyncStatusCallback& callback) override {
90 EXPECT_LT(running_tasks_.size(), max_parallel_task_);
91 running_tasks_.push(callback);
94 ~FakeSyncProcessRunner() override {}
96 void UpdateChanges(int num_changes) {
97 OnChangesUpdated(num_changes);
100 void CompleteTask(SyncStatusCode status) {
101 ASSERT_FALSE(running_tasks_.empty());
102 SyncStatusCallback task = running_tasks_.front();
103 running_tasks_.pop();
104 task.Run(status);
107 bool HasRunningTask() const {
108 return !running_tasks_.empty();
111 private:
112 size_t max_parallel_task_;
113 std::queue<SyncStatusCallback> running_tasks_;
115 DISALLOW_COPY_AND_ASSIGN(FakeSyncProcessRunner);
118 } // namespace
120 TEST(SyncProcessRunnerTest, SingleTaskBasicTest) {
121 FakeClient fake_client;
122 FakeTimerHelper* fake_timer = new FakeTimerHelper();
123 FakeSyncProcessRunner fake_runner(
124 &fake_client,
125 scoped_ptr<SyncProcessRunner::TimerHelper>(fake_timer),
126 1 /* max_parallel_task */);
128 base::TimeTicks base_time = base::TimeTicks::Now();
129 fake_timer->SetCurrentTime(base_time);
131 // SyncProcessRunner is expected not to run a task initially.
132 EXPECT_FALSE(fake_timer->IsRunning());
134 // As soon as SyncProcessRunner gets a new update, it should start running
135 // the timer to run a synchronization task.
136 fake_runner.UpdateChanges(100);
137 EXPECT_TRUE(fake_timer->IsRunning());
138 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
139 fake_timer->GetCurrentDelay());
141 // When the time has come, the timer should fire the scheduled task.
142 fake_timer->AdvanceToScheduledTime();
143 EXPECT_FALSE(fake_timer->IsRunning());
144 EXPECT_TRUE(fake_runner.HasRunningTask());
146 // Successful completion of the task fires next synchronization task.
147 fake_runner.CompleteTask(SYNC_STATUS_OK);
148 EXPECT_TRUE(fake_timer->IsRunning());
149 EXPECT_FALSE(fake_runner.HasRunningTask());
150 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
151 fake_timer->GetCurrentDelay());
153 // Turn |service_state| to TEMPORARY_UNAVAILABLE and let the task fail.
154 // |fake_runner| should schedule following tasks with longer delay.
155 fake_timer->AdvanceToScheduledTime();
156 fake_client.set_service_state(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
157 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
158 EXPECT_EQ(SyncProcessRunner::kSyncDelaySlowInMilliseconds,
159 fake_timer->GetCurrentDelay());
161 // Repeated failure makes the task delay back off.
162 fake_timer->AdvanceToScheduledTime();
163 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
164 EXPECT_EQ(2 * SyncProcessRunner::kSyncDelaySlowInMilliseconds,
165 fake_timer->GetCurrentDelay());
167 // After |service_state| gets back to normal state, SyncProcessRunner should
168 // restart rapid task invocation.
169 fake_client.set_service_state(SYNC_SERVICE_RUNNING);
170 fake_timer->AdvanceToScheduledTime();
171 fake_runner.CompleteTask(SYNC_STATUS_OK);
172 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
173 fake_timer->GetCurrentDelay());
175 // There's no item to sync anymore, SyncProcessRunner should schedules the
176 // next with the longest delay.
177 fake_runner.UpdateChanges(0);
178 fake_timer->AdvanceToScheduledTime();
179 fake_runner.CompleteTask(SYNC_STATUS_OK);
180 EXPECT_EQ(SyncProcessRunner::kSyncDelayMaxInMilliseconds,
181 fake_timer->GetCurrentDelay());
183 // Schedule the next with the longest delay if the client is persistently
184 // unavailable.
185 fake_client.set_service_state(SYNC_SERVICE_AUTHENTICATION_REQUIRED);
186 fake_runner.UpdateChanges(100);
187 EXPECT_EQ(SyncProcessRunner::kSyncDelayMaxInMilliseconds,
188 fake_timer->GetCurrentDelay());
191 TEST(SyncProcessRunnerTest, MultiTaskBasicTest) {
192 FakeClient fake_client;
193 FakeTimerHelper* fake_timer = new FakeTimerHelper();
194 FakeSyncProcessRunner fake_runner(
195 &fake_client,
196 scoped_ptr<SyncProcessRunner::TimerHelper>(fake_timer),
197 2 /* max_parallel_task */);
199 base::TimeTicks base_time = base::TimeTicks::Now();
200 fake_timer->SetCurrentTime(base_time);
202 EXPECT_FALSE(fake_timer->IsRunning());
204 fake_runner.UpdateChanges(100);
205 EXPECT_TRUE(fake_timer->IsRunning());
206 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
207 fake_timer->GetCurrentDelay());
209 // Even after a task starts running, SyncProcessRunner should schedule next
210 // task until the number of running task reachs the limit.
211 fake_timer->AdvanceToScheduledTime();
212 EXPECT_TRUE(fake_timer->IsRunning());
213 EXPECT_TRUE(fake_runner.HasRunningTask());
214 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
215 fake_timer->GetCurrentDelay());
217 // After the second task starts running, SyncProcessRunner should stop
218 // scheduling a task.
219 fake_timer->AdvanceToScheduledTime();
220 EXPECT_FALSE(fake_timer->IsRunning());
221 EXPECT_TRUE(fake_runner.HasRunningTask());
223 fake_runner.CompleteTask(SYNC_STATUS_OK);
224 EXPECT_TRUE(fake_timer->IsRunning());
225 EXPECT_TRUE(fake_runner.HasRunningTask());
226 fake_runner.CompleteTask(SYNC_STATUS_OK);
227 EXPECT_TRUE(fake_timer->IsRunning());
228 EXPECT_FALSE(fake_runner.HasRunningTask());
230 // Turn |service_state| to TEMPORARY_UNAVAILABLE and let the task fail.
231 // |fake_runner| should schedule following tasks with longer delay.
232 fake_timer->AdvanceToScheduledTime();
233 fake_timer->AdvanceToScheduledTime();
234 fake_client.set_service_state(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
235 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
236 EXPECT_EQ(SyncProcessRunner::kSyncDelaySlowInMilliseconds,
237 fake_timer->GetCurrentDelay());
239 // Consecutive error reports shouldn't extend delay immediately.
240 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
241 EXPECT_EQ(SyncProcessRunner::kSyncDelaySlowInMilliseconds,
242 fake_timer->GetCurrentDelay());
244 // The next task will run after throttle period is over.
245 // And its failure should extend the throttle period by twice.
246 fake_timer->AdvanceToScheduledTime();
247 EXPECT_EQ(SyncProcessRunner::kSyncDelaySlowInMilliseconds,
248 fake_timer->GetCurrentDelay());
249 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
250 EXPECT_EQ(2 * SyncProcessRunner::kSyncDelaySlowInMilliseconds,
251 fake_timer->GetCurrentDelay());
253 // Next successful task should clear the throttling.
254 fake_timer->AdvanceToScheduledTime();
255 fake_client.set_service_state(SYNC_SERVICE_RUNNING);
256 fake_runner.CompleteTask(SYNC_STATUS_OK);
257 EXPECT_EQ(SyncProcessRunner::kSyncDelayFastInMilliseconds,
258 fake_timer->GetCurrentDelay());
260 // Then, following failing task should not extend throttling period.
261 fake_timer->AdvanceToScheduledTime();
262 fake_client.set_service_state(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
263 fake_runner.CompleteTask(SYNC_STATUS_FAILED);
264 EXPECT_EQ(SyncProcessRunner::kSyncDelaySlowInMilliseconds,
265 fake_timer->GetCurrentDelay());
268 } // namespace sync_file_system