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.
5 #include "base/basictypes.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"
12 namespace sync_file_system {
16 void DumbTask(SyncStatusCode status,
17 const SyncStatusCallback& callback) {
18 base::MessageLoop::current()->PostTask(
19 FROM_HERE, base::Bind(callback, status));
22 void IncrementAndAssign(int expected_before_counter,
24 SyncStatusCode* status_out,
25 SyncStatusCode status) {
26 EXPECT_EQ(expected_before_counter, *counter);
32 void IncrementAndAssignWithOwnedPointer(T* object,
34 SyncStatusCode* status_out,
35 SyncStatusCode status) {
40 class TaskManagerClient
41 : public SyncTaskManager::Client,
42 public base::SupportsWeakPtr<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;
53 virtual ~TaskManagerClient() {}
55 // DriveFileSyncManager::Client overrides.
56 virtual void MaybeScheduleNextTask() OVERRIDE {
57 ++maybe_schedule_next_task_count_;
59 virtual void NotifyLastOperationStatus(
60 SyncStatusCode last_operation_status) OVERRIDE {
61 last_operation_status_ = last_operation_status;
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 */),
72 void ScheduleTaskIfIdle(SyncStatusCode status_to_return) {
73 task_manager_->ScheduleTaskIfIdle(
74 base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(),
75 status_to_return, true /* idle */));
78 int maybe_schedule_next_task_count() const {
79 return maybe_schedule_next_task_count_;
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_;
88 void DoTask(SyncStatusCode status_to_return,
90 const SyncStatusCallback& callback) {
91 ++task_scheduled_count_;
93 ++idle_task_scheduled_count_;
94 base::MessageLoop::current()->PostTask(
95 FROM_HERE, base::Bind(callback, status_to_return));
98 scoped_ptr<SyncTaskManager> task_manager_;
100 int maybe_schedule_next_task_count_;
101 int task_scheduled_count_;
102 int idle_task_scheduled_count_;
104 SyncStatusCode last_operation_status_;
106 DISALLOW_COPY_AND_ASSIGN(TaskManagerClient);
109 class MultihopSyncTask : public SyncTask {
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_);
120 virtual ~MultihopSyncTask() {}
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));
131 void CompleteTask(const SyncStatusCallback& callback) {
132 DCHECK(*task_started_);
133 DCHECK(!*task_completed_);
134 *task_completed_ = true;
135 callback.Run(SYNC_STATUS_OK);
139 bool* task_completed_;
140 base::WeakPtrFactory<MultihopSyncTask> weak_ptr_factory_;
142 DISALLOW_COPY_AND_ASSIGN(MultihopSyncTask);
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);
154 TEST(SyncTaskManagerTest, ScheduleTask) {
155 base::MessageLoop message_loop;
156 TaskManagerClient client;
157 int callback_count = 0;
158 SyncStatusCode callback_status = SYNC_STATUS_OK;
160 client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
163 message_loop.RunUntilIdle();
165 EXPECT_EQ(kStatus1, callback_status);
166 EXPECT_EQ(kStatus1, client.last_operation_status());
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());
174 TEST(SyncTaskManagerTest, ScheduleTwoTasks) {
175 base::MessageLoop message_loop;
176 TaskManagerClient client;
177 int callback_count = 0;
178 SyncStatusCode callback_status = SYNC_STATUS_OK;
180 client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
183 client.ScheduleTask(kStatus2, base::Bind(&IncrementAndAssign, 1,
186 message_loop.RunUntilIdle();
188 EXPECT_EQ(kStatus2, callback_status);
189 EXPECT_EQ(kStatus2, client.last_operation_status());
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());
197 TEST(SyncTaskManagerTest, ScheduleIdleTask) {
198 base::MessageLoop message_loop;
199 TaskManagerClient client;
201 client.ScheduleTaskIfIdle(kStatus1);
202 message_loop.RunUntilIdle();
204 EXPECT_EQ(kStatus1, client.last_operation_status());
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());
211 TEST(SyncTaskManagerTest, ScheduleIdleTaskWhileNotIdle) {
212 base::MessageLoop message_loop;
213 TaskManagerClient client;
214 int callback_count = 0;
215 SyncStatusCode callback_status = SYNC_STATUS_OK;
217 client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
220 client.ScheduleTaskIfIdle(kStatus2);
221 message_loop.RunUntilIdle();
223 // Idle task must not have run.
224 EXPECT_EQ(kStatus1, callback_status);
225 EXPECT_EQ(kStatus1, client.last_operation_status());
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());
233 TEST(SyncTaskManagerTest, ScheduleAndCancelSyncTask) {
234 base::MessageLoop message_loop;
236 int callback_count = 0;
237 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
239 bool task_started = false;
240 bool task_completed = false;
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));
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);
258 TEST(SyncTaskManagerTest, ScheduleAndCancelTask) {
259 base::MessageLoop message_loop;
261 int callback_count = 0;
262 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
264 bool task_started = false;
265 bool task_completed = false;
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));
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);
285 TEST(SyncTaskManagerTest, ScheduleTaskAtPriority) {
286 base::MessageLoop message_loop;
287 SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
288 task_manager.Initialize(SYNC_STATUS_OK);
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;
297 // This will run first even if its priority is low, since there're no
299 task_manager.ScheduleTaskAtPriority(
300 base::Bind(&DumbTask, kStatus1),
301 SyncTaskManager::PRIORITY_LOW,
302 base::Bind(&IncrementAndAssign, 0, &callback_count, &callback_status1));
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));
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));
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));
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));
328 message_loop.RunUntilIdle();
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);
338 } // namespace sync_file_system