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
,
61 bool last_operation_used_network
) OVERRIDE
{
62 last_operation_status_
= last_operation_status
;
65 void ScheduleTask(SyncStatusCode status_to_return
,
66 const SyncStatusCallback
& callback
) {
67 task_manager_
->ScheduleTask(
68 base::Bind(&TaskManagerClient::DoTask
, AsWeakPtr(),
69 status_to_return
, false /* idle */),
73 void ScheduleTaskIfIdle(SyncStatusCode status_to_return
) {
74 task_manager_
->ScheduleTaskIfIdle(
75 base::Bind(&TaskManagerClient::DoTask
, AsWeakPtr(),
76 status_to_return
, true /* idle */),
77 SyncStatusCallback());
80 int maybe_schedule_next_task_count() const {
81 return maybe_schedule_next_task_count_
;
83 int task_scheduled_count() const { return task_scheduled_count_
; }
84 int idle_task_scheduled_count() const { return idle_task_scheduled_count_
; }
85 SyncStatusCode
last_operation_status() const {
86 return last_operation_status_
;
90 void DoTask(SyncStatusCode status_to_return
,
92 const SyncStatusCallback
& callback
) {
93 ++task_scheduled_count_
;
95 ++idle_task_scheduled_count_
;
96 base::MessageLoop::current()->PostTask(
97 FROM_HERE
, base::Bind(callback
, status_to_return
));
100 scoped_ptr
<SyncTaskManager
> task_manager_
;
102 int maybe_schedule_next_task_count_
;
103 int task_scheduled_count_
;
104 int idle_task_scheduled_count_
;
106 SyncStatusCode last_operation_status_
;
108 DISALLOW_COPY_AND_ASSIGN(TaskManagerClient
);
111 class MultihopSyncTask
: public SyncTask
{
113 MultihopSyncTask(bool* task_started
,
114 bool* task_completed
)
115 : task_started_(task_started
),
116 task_completed_(task_completed
),
117 weak_ptr_factory_(this) {
118 DCHECK(task_started_
);
119 DCHECK(task_completed_
);
122 virtual ~MultihopSyncTask() {}
124 virtual void Run(const SyncStatusCallback
& callback
) OVERRIDE
{
125 DCHECK(!*task_started_
);
126 *task_started_
= true;
127 base::MessageLoop::current()->PostTask(
128 FROM_HERE
, base::Bind(&MultihopSyncTask::CompleteTask
,
129 weak_ptr_factory_
.GetWeakPtr(), callback
));
133 void CompleteTask(const SyncStatusCallback
& callback
) {
134 DCHECK(*task_started_
);
135 DCHECK(!*task_completed_
);
136 *task_completed_
= true;
137 callback
.Run(SYNC_STATUS_OK
);
141 bool* task_completed_
;
142 base::WeakPtrFactory
<MultihopSyncTask
> weak_ptr_factory_
;
144 DISALLOW_COPY_AND_ASSIGN(MultihopSyncTask
);
147 // Arbitrary non-default status values for testing.
148 const SyncStatusCode kStatus1
= static_cast<SyncStatusCode
>(-1);
149 const SyncStatusCode kStatus2
= static_cast<SyncStatusCode
>(-2);
150 const SyncStatusCode kStatus3
= static_cast<SyncStatusCode
>(-3);
151 const SyncStatusCode kStatus4
= static_cast<SyncStatusCode
>(-4);
152 const SyncStatusCode kStatus5
= static_cast<SyncStatusCode
>(-5);
156 TEST(SyncTaskManagerTest
, ScheduleTask
) {
157 base::MessageLoop message_loop
;
158 TaskManagerClient client
;
159 int callback_count
= 0;
160 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
162 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
165 message_loop
.RunUntilIdle();
167 EXPECT_EQ(kStatus1
, callback_status
);
168 EXPECT_EQ(kStatus1
, client
.last_operation_status());
170 EXPECT_EQ(1, callback_count
);
171 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
172 EXPECT_EQ(1, client
.task_scheduled_count());
173 EXPECT_EQ(0, client
.idle_task_scheduled_count());
176 TEST(SyncTaskManagerTest
, ScheduleTwoTasks
) {
177 base::MessageLoop message_loop
;
178 TaskManagerClient client
;
179 int callback_count
= 0;
180 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
182 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
185 client
.ScheduleTask(kStatus2
, base::Bind(&IncrementAndAssign
, 1,
188 message_loop
.RunUntilIdle();
190 EXPECT_EQ(kStatus2
, callback_status
);
191 EXPECT_EQ(kStatus2
, client
.last_operation_status());
193 EXPECT_EQ(2, callback_count
);
194 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
195 EXPECT_EQ(2, client
.task_scheduled_count());
196 EXPECT_EQ(0, client
.idle_task_scheduled_count());
199 TEST(SyncTaskManagerTest
, ScheduleIdleTask
) {
200 base::MessageLoop message_loop
;
201 TaskManagerClient client
;
203 client
.ScheduleTaskIfIdle(kStatus1
);
204 message_loop
.RunUntilIdle();
206 EXPECT_EQ(kStatus1
, client
.last_operation_status());
208 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
209 EXPECT_EQ(1, client
.task_scheduled_count());
210 EXPECT_EQ(1, client
.idle_task_scheduled_count());
213 TEST(SyncTaskManagerTest
, ScheduleIdleTaskWhileNotIdle
) {
214 base::MessageLoop message_loop
;
215 TaskManagerClient client
;
216 int callback_count
= 0;
217 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
219 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
222 client
.ScheduleTaskIfIdle(kStatus2
);
223 message_loop
.RunUntilIdle();
225 // Idle task must not have run.
226 EXPECT_EQ(kStatus1
, callback_status
);
227 EXPECT_EQ(kStatus1
, client
.last_operation_status());
229 EXPECT_EQ(1, callback_count
);
230 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
231 EXPECT_EQ(1, client
.task_scheduled_count());
232 EXPECT_EQ(0, client
.idle_task_scheduled_count());
235 TEST(SyncTaskManagerTest
, ScheduleAndCancelSyncTask
) {
236 base::MessageLoop message_loop
;
238 int callback_count
= 0;
239 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
241 bool task_started
= false;
242 bool task_completed
= false;
245 SyncTaskManager
task_manager((base::WeakPtr
<SyncTaskManager::Client
>()));
246 task_manager
.Initialize(SYNC_STATUS_OK
);
247 task_manager
.ScheduleSyncTask(
248 scoped_ptr
<SyncTask
>(new MultihopSyncTask(
249 &task_started
, &task_completed
)),
250 base::Bind(&IncrementAndAssign
, 0, &callback_count
, &status
));
253 message_loop
.RunUntilIdle();
254 EXPECT_EQ(0, callback_count
);
255 EXPECT_EQ(SYNC_STATUS_UNKNOWN
, status
);
256 EXPECT_TRUE(task_started
);
257 EXPECT_FALSE(task_completed
);
260 TEST(SyncTaskManagerTest
, ScheduleAndCancelTask
) {
261 base::MessageLoop message_loop
;
263 int callback_count
= 0;
264 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
266 bool task_started
= false;
267 bool task_completed
= false;
270 SyncTaskManager
task_manager((base::WeakPtr
<SyncTaskManager::Client
>()));
271 task_manager
.Initialize(SYNC_STATUS_OK
);
272 MultihopSyncTask
* task
= new MultihopSyncTask(
273 &task_started
, &task_completed
);
274 task_manager
.ScheduleTask(
275 base::Bind(&MultihopSyncTask::Run
, base::Unretained(task
)),
276 base::Bind(&IncrementAndAssignWithOwnedPointer
<MultihopSyncTask
>,
277 base::Owned(task
), &callback_count
, &status
));
280 message_loop
.RunUntilIdle();
281 EXPECT_EQ(0, callback_count
);
282 EXPECT_EQ(SYNC_STATUS_UNKNOWN
, status
);
283 EXPECT_TRUE(task_started
);
284 EXPECT_FALSE(task_completed
);
287 TEST(SyncTaskManagerTest
, ScheduleTaskAtPriority
) {
288 base::MessageLoop message_loop
;
289 SyncTaskManager
task_manager((base::WeakPtr
<SyncTaskManager::Client
>()));
290 task_manager
.Initialize(SYNC_STATUS_OK
);
292 int callback_count
= 0;
293 SyncStatusCode callback_status1
= SYNC_STATUS_OK
;
294 SyncStatusCode callback_status2
= SYNC_STATUS_OK
;
295 SyncStatusCode callback_status3
= SYNC_STATUS_OK
;
296 SyncStatusCode callback_status4
= SYNC_STATUS_OK
;
297 SyncStatusCode callback_status5
= SYNC_STATUS_OK
;
299 // This will run first even if its priority is low, since there're no
301 task_manager
.ScheduleTaskAtPriority(
302 base::Bind(&DumbTask
, kStatus1
),
303 SyncTaskManager::PRIORITY_LOW
,
304 base::Bind(&IncrementAndAssign
, 0, &callback_count
, &callback_status1
));
306 // This runs last (expected counter == 4).
307 task_manager
.ScheduleTaskAtPriority(
308 base::Bind(&DumbTask
, kStatus2
),
309 SyncTaskManager::PRIORITY_LOW
,
310 base::Bind(&IncrementAndAssign
, 4, &callback_count
, &callback_status2
));
312 // This runs second (expected counter == 1).
313 task_manager
.ScheduleTaskAtPriority(
314 base::Bind(&DumbTask
, kStatus3
),
315 SyncTaskManager::PRIORITY_HIGH
,
316 base::Bind(&IncrementAndAssign
, 1, &callback_count
, &callback_status3
));
318 // This runs fourth (expected counter == 3).
319 task_manager
.ScheduleTaskAtPriority(
320 base::Bind(&DumbTask
, kStatus4
),
321 SyncTaskManager::PRIORITY_MED
,
322 base::Bind(&IncrementAndAssign
, 3, &callback_count
, &callback_status4
));
324 // This runs third (expected counter == 2).
325 task_manager
.ScheduleTaskAtPriority(
326 base::Bind(&DumbTask
, kStatus5
),
327 SyncTaskManager::PRIORITY_HIGH
,
328 base::Bind(&IncrementAndAssign
, 2, &callback_count
, &callback_status5
));
330 message_loop
.RunUntilIdle();
332 EXPECT_EQ(kStatus1
, callback_status1
);
333 EXPECT_EQ(kStatus2
, callback_status2
);
334 EXPECT_EQ(kStatus3
, callback_status3
);
335 EXPECT_EQ(kStatus4
, callback_status4
);
336 EXPECT_EQ(kStatus5
, callback_status5
);
337 EXPECT_EQ(5, callback_count
);
340 } // namespace sync_file_system