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