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.
8 #include "base/basictypes.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
15 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
16 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
17 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
18 #include "storage/common/fileapi/file_system_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 #define MAKE_PATH(path) \
22 base::FilePath(storage::VirtualPath::GetNormalizedFilePath( \
23 base::FilePath(FILE_PATH_LITERAL(path))))
25 namespace sync_file_system
{
26 namespace drive_backend
{
30 void DumbTask(SyncStatusCode status
,
31 const SyncStatusCallback
& callback
) {
32 base::MessageLoop::current()->PostTask(
33 FROM_HERE
, base::Bind(callback
, status
));
36 void IncrementAndAssign(int expected_before_counter
,
38 SyncStatusCode
* status_out
,
39 SyncStatusCode status
) {
40 EXPECT_EQ(expected_before_counter
, *counter
);
46 void IncrementAndAssignWithOwnedPointer(T
* object
,
48 SyncStatusCode
* status_out
,
49 SyncStatusCode status
) {
54 class TaskManagerClient
55 : public SyncTaskManager::Client
,
56 public base::SupportsWeakPtr
<TaskManagerClient
> {
58 explicit TaskManagerClient(int64 maximum_background_task
)
59 : maybe_schedule_next_task_count_(0),
60 task_scheduled_count_(0),
61 idle_task_scheduled_count_(0),
62 last_operation_status_(SYNC_STATUS_OK
) {
63 task_manager_
.reset(new SyncTaskManager(
64 AsWeakPtr(), maximum_background_task
,
65 base::ThreadTaskRunnerHandle::Get(),
66 nullptr /* worker_pool */));
67 task_manager_
->Initialize(SYNC_STATUS_OK
);
68 base::MessageLoop::current()->RunUntilIdle();
69 maybe_schedule_next_task_count_
= 0;
71 ~TaskManagerClient() override
{}
73 // DriveFileSyncManager::Client overrides.
74 void MaybeScheduleNextTask() override
{ ++maybe_schedule_next_task_count_
; }
75 void NotifyLastOperationStatus(SyncStatusCode last_operation_status
,
76 bool last_operation_used_network
) override
{
77 last_operation_status_
= last_operation_status
;
80 void RecordTaskLog(scoped_ptr
<TaskLogger::TaskLog
>) override
{}
82 void ScheduleTask(SyncStatusCode status_to_return
,
83 const SyncStatusCallback
& callback
) {
84 task_manager_
->ScheduleTask(
86 base::Bind(&TaskManagerClient::DoTask
, AsWeakPtr(),
87 status_to_return
, false /* idle */),
88 SyncTaskManager::PRIORITY_MED
,
92 void ScheduleTaskIfIdle(SyncStatusCode status_to_return
) {
93 task_manager_
->ScheduleTaskIfIdle(
95 base::Bind(&TaskManagerClient::DoTask
, AsWeakPtr(),
96 status_to_return
, true /* idle */),
97 SyncStatusCallback());
100 int maybe_schedule_next_task_count() const {
101 return maybe_schedule_next_task_count_
;
103 int task_scheduled_count() const { return task_scheduled_count_
; }
104 int idle_task_scheduled_count() const { return idle_task_scheduled_count_
; }
105 SyncStatusCode
last_operation_status() const {
106 return last_operation_status_
;
110 void DoTask(SyncStatusCode status_to_return
,
112 const SyncStatusCallback
& callback
) {
113 ++task_scheduled_count_
;
115 ++idle_task_scheduled_count_
;
116 base::MessageLoop::current()->PostTask(
117 FROM_HERE
, base::Bind(callback
, status_to_return
));
120 scoped_ptr
<SyncTaskManager
> task_manager_
;
122 int maybe_schedule_next_task_count_
;
123 int task_scheduled_count_
;
124 int idle_task_scheduled_count_
;
126 SyncStatusCode last_operation_status_
;
128 DISALLOW_COPY_AND_ASSIGN(TaskManagerClient
);
131 class MultihopSyncTask
: public ExclusiveTask
{
133 MultihopSyncTask(bool* task_started
,
134 bool* task_completed
)
135 : task_started_(task_started
),
136 task_completed_(task_completed
),
137 weak_ptr_factory_(this) {
138 DCHECK(task_started_
);
139 DCHECK(task_completed_
);
142 ~MultihopSyncTask() override
{}
144 void RunExclusive(const SyncStatusCallback
& callback
) override
{
145 DCHECK(!*task_started_
);
146 *task_started_
= true;
147 base::MessageLoop::current()->PostTask(
148 FROM_HERE
, base::Bind(&MultihopSyncTask::CompleteTask
,
149 weak_ptr_factory_
.GetWeakPtr(), callback
));
153 void CompleteTask(const SyncStatusCallback
& callback
) {
154 DCHECK(*task_started_
);
155 DCHECK(!*task_completed_
);
156 *task_completed_
= true;
157 callback
.Run(SYNC_STATUS_OK
);
161 bool* task_completed_
;
162 base::WeakPtrFactory
<MultihopSyncTask
> weak_ptr_factory_
;
164 DISALLOW_COPY_AND_ASSIGN(MultihopSyncTask
);
167 class BackgroundTask
: public SyncTask
{
170 int64 running_background_task
;
172 int64 max_parallel_task
;
175 : running_background_task(0),
177 max_parallel_task(0) {}
180 BackgroundTask(const std::string
& app_id
,
181 const base::FilePath
& path
,
186 weak_ptr_factory_(this) {
189 ~BackgroundTask() override
{}
191 void RunPreflight(scoped_ptr
<SyncTaskToken
> token
) override
{
192 scoped_ptr
<TaskBlocker
> task_blocker(new TaskBlocker
);
193 task_blocker
->app_id
= app_id_
;
194 task_blocker
->paths
.push_back(path_
);
196 SyncTaskManager::UpdateTaskBlocker(
197 token
.Pass(), task_blocker
.Pass(),
198 base::Bind(&BackgroundTask::RunAsBackgroundTask
,
199 weak_ptr_factory_
.GetWeakPtr()));
203 void RunAsBackgroundTask(scoped_ptr
<SyncTaskToken
> token
) {
204 ++(stats_
->running_background_task
);
205 if (stats_
->max_parallel_task
< stats_
->running_background_task
)
206 stats_
->max_parallel_task
= stats_
->running_background_task
;
208 base::MessageLoop::current()->PostTask(
210 base::Bind(&BackgroundTask::CompleteTask
,
211 weak_ptr_factory_
.GetWeakPtr(),
212 base::Passed(&token
)));
215 void CompleteTask(scoped_ptr
<SyncTaskToken
> token
) {
216 ++(stats_
->finished_task
);
217 --(stats_
->running_background_task
);
218 SyncTaskManager::NotifyTaskDone(token
.Pass(), SYNC_STATUS_OK
);
222 base::FilePath path_
;
225 base::WeakPtrFactory
<BackgroundTask
> weak_ptr_factory_
;
227 DISALLOW_COPY_AND_ASSIGN(BackgroundTask
);
230 class BlockerUpdateTestHelper
: public SyncTask
{
232 typedef std::vector
<std::string
> Log
;
234 BlockerUpdateTestHelper(const std::string
& name
,
235 const std::string
& app_id
,
236 const std::vector
<std::string
>& paths
,
240 paths_(paths
.begin(), paths
.end()),
242 weak_ptr_factory_(this) {
245 ~BlockerUpdateTestHelper() override
{}
247 void RunPreflight(scoped_ptr
<SyncTaskToken
> token
) override
{
248 UpdateBlocker(token
.Pass());
252 void UpdateBlocker(scoped_ptr
<SyncTaskToken
> token
) {
253 if (paths_
.empty()) {
254 log_
->push_back(name_
+ ": finished");
255 SyncTaskManager::NotifyTaskDone(token
.Pass(), SYNC_STATUS_OK
);
259 std::string updating_to
= paths_
.front();
262 log_
->push_back(name_
+ ": updating to " + updating_to
);
264 scoped_ptr
<TaskBlocker
> task_blocker(new TaskBlocker
);
265 task_blocker
->app_id
= app_id_
;
266 task_blocker
->paths
.push_back(
267 base::FilePath(storage::VirtualPath::GetNormalizedFilePath(
268 base::FilePath::FromUTF8Unsafe(updating_to
))));
270 SyncTaskManager::UpdateTaskBlocker(
271 token
.Pass(), task_blocker
.Pass(),
272 base::Bind(&BlockerUpdateTestHelper::UpdateBlockerSoon
,
273 weak_ptr_factory_
.GetWeakPtr(),
277 void UpdateBlockerSoon(const std::string
& updated_to
,
278 scoped_ptr
<SyncTaskToken
> token
) {
279 log_
->push_back(name_
+ ": updated to " + updated_to
);
280 base::MessageLoop::current()->PostTask(
282 base::Bind(&BlockerUpdateTestHelper::UpdateBlocker
,
283 weak_ptr_factory_
.GetWeakPtr(), base::Passed(&token
)));
288 std::deque
<std::string
> paths_
;
291 base::WeakPtrFactory
<BlockerUpdateTestHelper
> weak_ptr_factory_
;
293 DISALLOW_COPY_AND_ASSIGN(BlockerUpdateTestHelper
);
296 // Arbitrary non-default status values for testing.
297 const SyncStatusCode kStatus1
= static_cast<SyncStatusCode
>(-1);
298 const SyncStatusCode kStatus2
= static_cast<SyncStatusCode
>(-2);
299 const SyncStatusCode kStatus3
= static_cast<SyncStatusCode
>(-3);
300 const SyncStatusCode kStatus4
= static_cast<SyncStatusCode
>(-4);
301 const SyncStatusCode kStatus5
= static_cast<SyncStatusCode
>(-5);
305 TEST(SyncTaskManagerTest
, ScheduleTask
) {
306 base::MessageLoop message_loop
;
307 TaskManagerClient
client(0 /* maximum_background_task */);
308 int callback_count
= 0;
309 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
311 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
314 message_loop
.RunUntilIdle();
316 EXPECT_EQ(kStatus1
, callback_status
);
317 EXPECT_EQ(kStatus1
, client
.last_operation_status());
319 EXPECT_EQ(1, callback_count
);
320 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
321 EXPECT_EQ(1, client
.task_scheduled_count());
322 EXPECT_EQ(0, client
.idle_task_scheduled_count());
325 TEST(SyncTaskManagerTest
, ScheduleTwoTasks
) {
326 base::MessageLoop message_loop
;
327 TaskManagerClient
client(0 /* maximum_background_task */);
328 int callback_count
= 0;
329 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
331 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
334 client
.ScheduleTask(kStatus2
, base::Bind(&IncrementAndAssign
, 1,
337 message_loop
.RunUntilIdle();
339 EXPECT_EQ(kStatus2
, callback_status
);
340 EXPECT_EQ(kStatus2
, client
.last_operation_status());
342 EXPECT_EQ(2, callback_count
);
343 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
344 EXPECT_EQ(2, client
.task_scheduled_count());
345 EXPECT_EQ(0, client
.idle_task_scheduled_count());
348 TEST(SyncTaskManagerTest
, ScheduleIdleTask
) {
349 base::MessageLoop message_loop
;
350 TaskManagerClient
client(0 /* maximum_background_task */);
352 client
.ScheduleTaskIfIdle(kStatus1
);
353 message_loop
.RunUntilIdle();
355 EXPECT_EQ(kStatus1
, client
.last_operation_status());
357 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
358 EXPECT_EQ(1, client
.task_scheduled_count());
359 EXPECT_EQ(1, client
.idle_task_scheduled_count());
362 TEST(SyncTaskManagerTest
, ScheduleIdleTaskWhileNotIdle
) {
363 base::MessageLoop message_loop
;
364 TaskManagerClient
client(0 /* maximum_background_task */);
365 int callback_count
= 0;
366 SyncStatusCode callback_status
= SYNC_STATUS_OK
;
368 client
.ScheduleTask(kStatus1
, base::Bind(&IncrementAndAssign
, 0,
371 client
.ScheduleTaskIfIdle(kStatus2
);
372 message_loop
.RunUntilIdle();
374 // Idle task must not have run.
375 EXPECT_EQ(kStatus1
, callback_status
);
376 EXPECT_EQ(kStatus1
, client
.last_operation_status());
378 EXPECT_EQ(1, callback_count
);
379 EXPECT_EQ(1, client
.maybe_schedule_next_task_count());
380 EXPECT_EQ(1, client
.task_scheduled_count());
381 EXPECT_EQ(0, client
.idle_task_scheduled_count());
384 TEST(SyncTaskManagerTest
, ScheduleAndCancelSyncTask
) {
385 base::MessageLoop message_loop
;
387 int callback_count
= 0;
388 SyncStatusCode status
= SYNC_STATUS_UNKNOWN
;
390 bool task_started
= false;
391 bool task_completed
= false;
394 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
395 0 /* maximum_background_task */,
396 base::ThreadTaskRunnerHandle::Get(),
397 nullptr /* worker_pool */);
398 task_manager
.Initialize(SYNC_STATUS_OK
);
399 message_loop
.RunUntilIdle();
400 task_manager
.ScheduleSyncTask(
402 scoped_ptr
<SyncTask
>(new MultihopSyncTask(
403 &task_started
, &task_completed
)),
404 SyncTaskManager::PRIORITY_MED
,
405 base::Bind(&IncrementAndAssign
, 0, &callback_count
, &status
));
407 message_loop
.RunUntilIdle();
409 EXPECT_EQ(0, callback_count
);
410 EXPECT_EQ(SYNC_STATUS_UNKNOWN
, status
);
411 EXPECT_TRUE(task_started
);
412 EXPECT_FALSE(task_completed
);
415 TEST(SyncTaskManagerTest
, ScheduleTaskAtPriority
) {
416 base::MessageLoop message_loop
;
417 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
418 0 /* maximum_background_task */,
419 base::ThreadTaskRunnerHandle::Get(),
420 nullptr /* worker_pool */);
421 task_manager
.Initialize(SYNC_STATUS_OK
);
422 message_loop
.RunUntilIdle();
424 int callback_count
= 0;
425 SyncStatusCode callback_status1
= SYNC_STATUS_OK
;
426 SyncStatusCode callback_status2
= SYNC_STATUS_OK
;
427 SyncStatusCode callback_status3
= SYNC_STATUS_OK
;
428 SyncStatusCode callback_status4
= SYNC_STATUS_OK
;
429 SyncStatusCode callback_status5
= SYNC_STATUS_OK
;
431 // This will run first even if its priority is low, since there're no
433 task_manager
.ScheduleTask(
435 base::Bind(&DumbTask
, kStatus1
),
436 SyncTaskManager::PRIORITY_LOW
,
437 base::Bind(&IncrementAndAssign
, 0, &callback_count
, &callback_status1
));
439 // This runs last (expected counter == 4).
440 task_manager
.ScheduleTask(
442 base::Bind(&DumbTask
, kStatus2
),
443 SyncTaskManager::PRIORITY_LOW
,
444 base::Bind(&IncrementAndAssign
, 4, &callback_count
, &callback_status2
));
446 // This runs second (expected counter == 1).
447 task_manager
.ScheduleTask(
449 base::Bind(&DumbTask
, kStatus3
),
450 SyncTaskManager::PRIORITY_HIGH
,
451 base::Bind(&IncrementAndAssign
, 1, &callback_count
, &callback_status3
));
453 // This runs fourth (expected counter == 3).
454 task_manager
.ScheduleTask(
456 base::Bind(&DumbTask
, kStatus4
),
457 SyncTaskManager::PRIORITY_MED
,
458 base::Bind(&IncrementAndAssign
, 3, &callback_count
, &callback_status4
));
460 // This runs third (expected counter == 2).
461 task_manager
.ScheduleTask(
463 base::Bind(&DumbTask
, kStatus5
),
464 SyncTaskManager::PRIORITY_HIGH
,
465 base::Bind(&IncrementAndAssign
, 2, &callback_count
, &callback_status5
));
467 message_loop
.RunUntilIdle();
469 EXPECT_EQ(kStatus1
, callback_status1
);
470 EXPECT_EQ(kStatus2
, callback_status2
);
471 EXPECT_EQ(kStatus3
, callback_status3
);
472 EXPECT_EQ(kStatus4
, callback_status4
);
473 EXPECT_EQ(kStatus5
, callback_status5
);
474 EXPECT_EQ(5, callback_count
);
477 TEST(SyncTaskManagerTest
, BackgroundTask_Sequential
) {
478 base::MessageLoop message_loop
;
479 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
480 10 /* maximum_background_task */,
481 base::ThreadTaskRunnerHandle::Get(),
482 nullptr /* worker_pool */);
483 task_manager
.Initialize(SYNC_STATUS_OK
);
485 SyncStatusCode status
= SYNC_STATUS_FAILED
;
486 BackgroundTask::Stats stats
;
487 task_manager
.ScheduleSyncTask(
489 scoped_ptr
<SyncTask
>(new BackgroundTask(
490 "app_id", MAKE_PATH("/hoge/fuga"),
492 SyncTaskManager::PRIORITY_MED
,
493 CreateResultReceiver(&status
));
495 task_manager
.ScheduleSyncTask(
497 scoped_ptr
<SyncTask
>(new BackgroundTask(
498 "app_id", MAKE_PATH("/hoge"),
500 SyncTaskManager::PRIORITY_MED
,
501 CreateResultReceiver(&status
));
503 task_manager
.ScheduleSyncTask(
505 scoped_ptr
<SyncTask
>(new BackgroundTask(
506 "app_id", MAKE_PATH("/hoge/fuga/piyo"),
508 SyncTaskManager::PRIORITY_MED
,
509 CreateResultReceiver(&status
));
511 message_loop
.RunUntilIdle();
513 EXPECT_EQ(SYNC_STATUS_OK
, status
);
514 EXPECT_EQ(0, stats
.running_background_task
);
515 EXPECT_EQ(3, stats
.finished_task
);
516 EXPECT_EQ(1, stats
.max_parallel_task
);
519 TEST(SyncTaskManagerTest
, BackgroundTask_Parallel
) {
520 base::MessageLoop message_loop
;
521 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
522 10 /* maximum_background_task */,
523 base::ThreadTaskRunnerHandle::Get(),
524 nullptr /* worker_pool */);
525 task_manager
.Initialize(SYNC_STATUS_OK
);
527 SyncStatusCode status
= SYNC_STATUS_FAILED
;
528 BackgroundTask::Stats stats
;
529 task_manager
.ScheduleSyncTask(
531 scoped_ptr
<SyncTask
>(new BackgroundTask(
532 "app_id", MAKE_PATH("/hoge"),
534 SyncTaskManager::PRIORITY_MED
,
535 CreateResultReceiver(&status
));
537 task_manager
.ScheduleSyncTask(
539 scoped_ptr
<SyncTask
>(new BackgroundTask(
540 "app_id", MAKE_PATH("/fuga"),
542 SyncTaskManager::PRIORITY_MED
,
543 CreateResultReceiver(&status
));
545 task_manager
.ScheduleSyncTask(
547 scoped_ptr
<SyncTask
>(new BackgroundTask(
548 "app_id", MAKE_PATH("/piyo"),
550 SyncTaskManager::PRIORITY_MED
,
551 CreateResultReceiver(&status
));
553 message_loop
.RunUntilIdle();
555 EXPECT_EQ(SYNC_STATUS_OK
, status
);
556 EXPECT_EQ(0, stats
.running_background_task
);
557 EXPECT_EQ(3, stats
.finished_task
);
558 EXPECT_EQ(3, stats
.max_parallel_task
);
561 TEST(SyncTaskManagerTest
, BackgroundTask_Throttled
) {
562 base::MessageLoop message_loop
;
563 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
564 2 /* maximum_background_task */,
565 base::ThreadTaskRunnerHandle::Get(),
566 nullptr /* worker_pool */);
567 task_manager
.Initialize(SYNC_STATUS_OK
);
569 SyncStatusCode status
= SYNC_STATUS_FAILED
;
570 BackgroundTask::Stats stats
;
571 task_manager
.ScheduleSyncTask(
573 scoped_ptr
<SyncTask
>(new BackgroundTask(
574 "app_id", MAKE_PATH("/hoge"),
576 SyncTaskManager::PRIORITY_MED
,
577 CreateResultReceiver(&status
));
579 task_manager
.ScheduleSyncTask(
581 scoped_ptr
<SyncTask
>(new BackgroundTask(
582 "app_id", MAKE_PATH("/fuga"),
584 SyncTaskManager::PRIORITY_MED
,
585 CreateResultReceiver(&status
));
587 task_manager
.ScheduleSyncTask(
589 scoped_ptr
<SyncTask
>(new BackgroundTask(
590 "app_id", MAKE_PATH("/piyo"),
592 SyncTaskManager::PRIORITY_MED
,
593 CreateResultReceiver(&status
));
595 message_loop
.RunUntilIdle();
597 EXPECT_EQ(SYNC_STATUS_OK
, status
);
598 EXPECT_EQ(0, stats
.running_background_task
);
599 EXPECT_EQ(3, stats
.finished_task
);
600 EXPECT_EQ(2, stats
.max_parallel_task
);
603 TEST(SyncTaskManagerTest
, UpdateTaskBlocker
) {
604 base::MessageLoop message_loop
;
605 SyncTaskManager
task_manager(base::WeakPtr
<SyncTaskManager::Client
>(),
606 10 /* maximum_background_task */,
607 base::ThreadTaskRunnerHandle::Get(),
608 nullptr /* worker_pool */);
609 task_manager
.Initialize(SYNC_STATUS_OK
);
611 SyncStatusCode status1
= SYNC_STATUS_FAILED
;
612 SyncStatusCode status2
= SYNC_STATUS_FAILED
;
613 BlockerUpdateTestHelper::Log log
;
616 std::vector
<std::string
> paths
;
617 paths
.push_back("/foo/bar");
618 paths
.push_back("/foo");
619 paths
.push_back("/hoge/fuga/piyo");
620 task_manager
.ScheduleSyncTask(
622 scoped_ptr
<SyncTask
>(new BlockerUpdateTestHelper(
623 "task1", "app_id", paths
, &log
)),
624 SyncTaskManager::PRIORITY_MED
,
625 CreateResultReceiver(&status1
));
629 std::vector
<std::string
> paths
;
630 paths
.push_back("/foo");
631 paths
.push_back("/foo/bar");
632 paths
.push_back("/hoge/fuga/piyo");
633 task_manager
.ScheduleSyncTask(
635 scoped_ptr
<SyncTask
>(new BlockerUpdateTestHelper(
636 "task2", "app_id", paths
, &log
)),
637 SyncTaskManager::PRIORITY_MED
,
638 CreateResultReceiver(&status2
));
641 message_loop
.RunUntilIdle();
643 EXPECT_EQ(SYNC_STATUS_OK
, status1
);
644 EXPECT_EQ(SYNC_STATUS_OK
, status2
);
646 ASSERT_EQ(14u, log
.size());
649 // task1 takes "/foo/bar" first.
650 EXPECT_EQ("task1: updating to /foo/bar", log
[i
++]);
652 // task1 blocks task2. task2's update should not complete until task1 update.
653 EXPECT_EQ("task2: updating to /foo", log
[i
++]);
654 EXPECT_EQ("task1: updated to /foo/bar", log
[i
++]);
656 // task1 releases "/foo/bar" and tries to take "/foo". Then, pending task2
657 // takes "/foo" and blocks task1.
658 EXPECT_EQ("task1: updating to /foo", log
[i
++]);
659 EXPECT_EQ("task2: updated to /foo", log
[i
++]);
661 // task2 releases "/foo".
662 EXPECT_EQ("task2: updating to /foo/bar", log
[i
++]);
663 EXPECT_EQ("task1: updated to /foo", log
[i
++]);
665 // task1 releases "/foo".
666 EXPECT_EQ("task1: updating to /hoge/fuga/piyo", log
[i
++]);
667 EXPECT_EQ("task1: updated to /hoge/fuga/piyo", log
[i
++]);
668 EXPECT_EQ("task2: updated to /foo/bar", log
[i
++]);
670 EXPECT_EQ("task1: finished", log
[i
++]);
672 EXPECT_EQ("task2: updating to /hoge/fuga/piyo", log
[i
++]);
673 EXPECT_EQ("task2: updated to /hoge/fuga/piyo", log
[i
++]);
674 EXPECT_EQ("task2: finished", log
[i
++]);
677 } // namespace drive_backend
678 } // namespace sync_file_system