- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / sync_task_manager_unittest.cc
1 // Copyright 2013 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 "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/sync_file_system/sync_task_manager.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace sync_file_system {
13
14 namespace {
15
16 void DumbTask(SyncStatusCode status,
17               const SyncStatusCallback& callback) {
18   base::MessageLoop::current()->PostTask(
19       FROM_HERE, base::Bind(callback, status));
20 }
21
22 void IncrementAndAssign(int expected_before_counter,
23                         int* counter,
24                         SyncStatusCode* status_out,
25                         SyncStatusCode status) {
26   EXPECT_EQ(expected_before_counter, *counter);
27   ++(*counter);
28   *status_out = status;
29 }
30
31 template <typename T>
32 void IncrementAndAssignWithOwnedPointer(T* object,
33                                         int* counter,
34                                         SyncStatusCode* status_out,
35                                         SyncStatusCode status) {
36   ++(*counter);
37   *status_out = status;
38 }
39
40 class TaskManagerClient
41     : public SyncTaskManager::Client,
42       public base::SupportsWeakPtr<TaskManagerClient> {
43  public:
44   TaskManagerClient()
45       : maybe_schedule_next_task_count_(0),
46         task_scheduled_count_(0),
47         idle_task_scheduled_count_(0),
48         last_operation_status_(SYNC_STATUS_OK) {
49     task_manager_.reset(new SyncTaskManager(AsWeakPtr()));
50     task_manager_->Initialize(SYNC_STATUS_OK);
51     maybe_schedule_next_task_count_ = 0;
52   }
53   virtual ~TaskManagerClient() {}
54
55   // DriveFileSyncManager::Client overrides.
56   virtual void MaybeScheduleNextTask() OVERRIDE {
57     ++maybe_schedule_next_task_count_;
58   }
59   virtual void NotifyLastOperationStatus(
60       SyncStatusCode last_operation_status) OVERRIDE {
61     last_operation_status_ = last_operation_status;
62   }
63
64   void ScheduleTask(SyncStatusCode status_to_return,
65                     const SyncStatusCallback& callback) {
66     task_manager_->ScheduleTask(
67         base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(),
68                    status_to_return, false /* idle */),
69         callback);
70   }
71
72   void ScheduleTaskIfIdle(SyncStatusCode status_to_return) {
73     task_manager_->ScheduleTaskIfIdle(
74         base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(),
75                    status_to_return, true /* idle */));
76   }
77
78   int maybe_schedule_next_task_count() const {
79     return maybe_schedule_next_task_count_;
80   }
81   int task_scheduled_count() const { return task_scheduled_count_; }
82   int idle_task_scheduled_count() const { return idle_task_scheduled_count_; }
83   SyncStatusCode last_operation_status() const {
84     return last_operation_status_;
85   }
86
87  private:
88   void DoTask(SyncStatusCode status_to_return,
89               bool is_idle_task,
90               const SyncStatusCallback& callback) {
91     ++task_scheduled_count_;
92     if (is_idle_task)
93       ++idle_task_scheduled_count_;
94     base::MessageLoop::current()->PostTask(
95         FROM_HERE, base::Bind(callback, status_to_return));
96   }
97
98   scoped_ptr<SyncTaskManager> task_manager_;
99
100   int maybe_schedule_next_task_count_;
101   int task_scheduled_count_;
102   int idle_task_scheduled_count_;
103
104   SyncStatusCode last_operation_status_;
105
106   DISALLOW_COPY_AND_ASSIGN(TaskManagerClient);
107 };
108
109 class MultihopSyncTask : public SyncTask {
110  public:
111   MultihopSyncTask(bool* task_started,
112                    bool* task_completed)
113       : task_started_(task_started),
114         task_completed_(task_completed),
115         weak_ptr_factory_(this) {
116     DCHECK(task_started_);
117     DCHECK(task_completed_);
118   }
119
120   virtual ~MultihopSyncTask() {}
121
122   virtual void Run(const SyncStatusCallback& callback) OVERRIDE {
123     DCHECK(!*task_started_);
124     *task_started_ = true;
125     base::MessageLoop::current()->PostTask(
126         FROM_HERE, base::Bind(&MultihopSyncTask::CompleteTask,
127                               weak_ptr_factory_.GetWeakPtr(), callback));
128   }
129
130  private:
131   void CompleteTask(const SyncStatusCallback& callback) {
132     DCHECK(*task_started_);
133     DCHECK(!*task_completed_);
134     *task_completed_ = true;
135     callback.Run(SYNC_STATUS_OK);
136   }
137
138   bool* task_started_;
139   bool* task_completed_;
140   base::WeakPtrFactory<MultihopSyncTask> weak_ptr_factory_;
141
142   DISALLOW_COPY_AND_ASSIGN(MultihopSyncTask);
143 };
144
145 // Arbitrary non-default status values for testing.
146 const SyncStatusCode kStatus1 = static_cast<SyncStatusCode>(-1);
147 const SyncStatusCode kStatus2 = static_cast<SyncStatusCode>(-2);
148 const SyncStatusCode kStatus3 = static_cast<SyncStatusCode>(-3);
149 const SyncStatusCode kStatus4 = static_cast<SyncStatusCode>(-4);
150 const SyncStatusCode kStatus5 = static_cast<SyncStatusCode>(-5);
151
152 }  // namespace
153
154 TEST(SyncTaskManagerTest, ScheduleTask) {
155   base::MessageLoop message_loop;
156   TaskManagerClient client;
157   int callback_count = 0;
158   SyncStatusCode callback_status = SYNC_STATUS_OK;
159
160   client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
161                                            &callback_count,
162                                            &callback_status));
163   message_loop.RunUntilIdle();
164
165   EXPECT_EQ(kStatus1, callback_status);
166   EXPECT_EQ(kStatus1, client.last_operation_status());
167
168   EXPECT_EQ(1, callback_count);
169   EXPECT_EQ(1, client.maybe_schedule_next_task_count());
170   EXPECT_EQ(1, client.task_scheduled_count());
171   EXPECT_EQ(0, client.idle_task_scheduled_count());
172 }
173
174 TEST(SyncTaskManagerTest, ScheduleTwoTasks) {
175   base::MessageLoop message_loop;
176   TaskManagerClient client;
177   int callback_count = 0;
178   SyncStatusCode callback_status = SYNC_STATUS_OK;
179
180   client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
181                                            &callback_count,
182                                            &callback_status));
183   client.ScheduleTask(kStatus2, base::Bind(&IncrementAndAssign, 1,
184                                            &callback_count,
185                                            &callback_status));
186   message_loop.RunUntilIdle();
187
188   EXPECT_EQ(kStatus2, callback_status);
189   EXPECT_EQ(kStatus2, client.last_operation_status());
190
191   EXPECT_EQ(2, callback_count);
192   EXPECT_EQ(1, client.maybe_schedule_next_task_count());
193   EXPECT_EQ(2, client.task_scheduled_count());
194   EXPECT_EQ(0, client.idle_task_scheduled_count());
195 }
196
197 TEST(SyncTaskManagerTest, ScheduleIdleTask) {
198   base::MessageLoop message_loop;
199   TaskManagerClient client;
200
201   client.ScheduleTaskIfIdle(kStatus1);
202   message_loop.RunUntilIdle();
203
204   EXPECT_EQ(kStatus1, client.last_operation_status());
205
206   EXPECT_EQ(1, client.maybe_schedule_next_task_count());
207   EXPECT_EQ(1, client.task_scheduled_count());
208   EXPECT_EQ(1, client.idle_task_scheduled_count());
209 }
210
211 TEST(SyncTaskManagerTest, ScheduleIdleTaskWhileNotIdle) {
212   base::MessageLoop message_loop;
213   TaskManagerClient client;
214   int callback_count = 0;
215   SyncStatusCode callback_status = SYNC_STATUS_OK;
216
217   client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
218                                            &callback_count,
219                                            &callback_status));
220   client.ScheduleTaskIfIdle(kStatus2);
221   message_loop.RunUntilIdle();
222
223   // Idle task must not have run.
224   EXPECT_EQ(kStatus1, callback_status);
225   EXPECT_EQ(kStatus1, client.last_operation_status());
226
227   EXPECT_EQ(1, callback_count);
228   EXPECT_EQ(1, client.maybe_schedule_next_task_count());
229   EXPECT_EQ(1, client.task_scheduled_count());
230   EXPECT_EQ(0, client.idle_task_scheduled_count());
231 }
232
233 TEST(SyncTaskManagerTest, ScheduleAndCancelSyncTask) {
234   base::MessageLoop message_loop;
235
236   int callback_count = 0;
237   SyncStatusCode status = SYNC_STATUS_UNKNOWN;
238
239   bool task_started = false;
240   bool task_completed = false;
241
242   {
243     SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
244     task_manager.Initialize(SYNC_STATUS_OK);
245     task_manager.ScheduleSyncTask(
246         scoped_ptr<SyncTask>(new MultihopSyncTask(
247             &task_started, &task_completed)),
248         base::Bind(&IncrementAndAssign, 0, &callback_count, &status));
249   }
250
251   message_loop.RunUntilIdle();
252   EXPECT_EQ(0, callback_count);
253   EXPECT_EQ(SYNC_STATUS_UNKNOWN, status);
254   EXPECT_TRUE(task_started);
255   EXPECT_FALSE(task_completed);
256 }
257
258 TEST(SyncTaskManagerTest, ScheduleAndCancelTask) {
259   base::MessageLoop message_loop;
260
261   int callback_count = 0;
262   SyncStatusCode status = SYNC_STATUS_UNKNOWN;
263
264   bool task_started = false;
265   bool task_completed = false;
266
267   {
268     SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
269     task_manager.Initialize(SYNC_STATUS_OK);
270     MultihopSyncTask* task = new MultihopSyncTask(
271         &task_started, &task_completed);
272     task_manager.ScheduleTask(
273         base::Bind(&MultihopSyncTask::Run, base::Unretained(task)),
274         base::Bind(&IncrementAndAssignWithOwnedPointer<MultihopSyncTask>,
275                    base::Owned(task), &callback_count, &status));
276   }
277
278   message_loop.RunUntilIdle();
279   EXPECT_EQ(0, callback_count);
280   EXPECT_EQ(SYNC_STATUS_UNKNOWN, status);
281   EXPECT_TRUE(task_started);
282   EXPECT_FALSE(task_completed);
283 }
284
285 TEST(SyncTaskManagerTest, ScheduleTaskAtPriority) {
286   base::MessageLoop message_loop;
287   SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
288   task_manager.Initialize(SYNC_STATUS_OK);
289
290   int callback_count = 0;
291   SyncStatusCode callback_status1 = SYNC_STATUS_OK;
292   SyncStatusCode callback_status2 = SYNC_STATUS_OK;
293   SyncStatusCode callback_status3 = SYNC_STATUS_OK;
294   SyncStatusCode callback_status4 = SYNC_STATUS_OK;
295   SyncStatusCode callback_status5 = SYNC_STATUS_OK;
296
297   // This will run first even if its priority is low, since there're no
298   // pending tasks.
299   task_manager.ScheduleTaskAtPriority(
300       base::Bind(&DumbTask, kStatus1),
301       SyncTaskManager::PRIORITY_LOW,
302       base::Bind(&IncrementAndAssign, 0, &callback_count, &callback_status1));
303
304   // This runs last (expected counter == 4).
305   task_manager.ScheduleTaskAtPriority(
306       base::Bind(&DumbTask, kStatus2),
307       SyncTaskManager::PRIORITY_LOW,
308       base::Bind(&IncrementAndAssign, 4, &callback_count, &callback_status2));
309
310   // This runs second (expected counter == 1).
311   task_manager.ScheduleTaskAtPriority(
312       base::Bind(&DumbTask, kStatus3),
313       SyncTaskManager::PRIORITY_HIGH,
314       base::Bind(&IncrementAndAssign, 1, &callback_count, &callback_status3));
315
316   // This runs fourth (expected counter == 3).
317   task_manager.ScheduleTaskAtPriority(
318       base::Bind(&DumbTask, kStatus4),
319       SyncTaskManager::PRIORITY_MED,
320       base::Bind(&IncrementAndAssign, 3, &callback_count, &callback_status4));
321
322   // This runs third (expected counter == 2).
323   task_manager.ScheduleTaskAtPriority(
324       base::Bind(&DumbTask, kStatus5),
325       SyncTaskManager::PRIORITY_HIGH,
326       base::Bind(&IncrementAndAssign, 2, &callback_count, &callback_status5));
327
328   message_loop.RunUntilIdle();
329
330   EXPECT_EQ(kStatus1, callback_status1);
331   EXPECT_EQ(kStatus2, callback_status2);
332   EXPECT_EQ(kStatus3, callback_status3);
333   EXPECT_EQ(kStatus4, callback_status4);
334   EXPECT_EQ(kStatus5, callback_status5);
335   EXPECT_EQ(5, callback_count);
336 }
337
338 }  // namespace sync_file_system