sync_task_manager_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 <deque>
6#include <string>
7
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "base/memory/weak_ptr.h"
11#include "base/message_loop/message_loop.h"
12#include "base/run_loop.h"
13#include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
14#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
15#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
16#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "webkit/common/fileapi/file_system_util.h"
19
20#define MAKE_PATH(path)                                       \
21  base::FilePath(fileapi::VirtualPath::GetNormalizedFilePath( \
22      base::FilePath(FILE_PATH_LITERAL(path))))
23
24namespace sync_file_system {
25namespace drive_backend {
26
27namespace {
28
29void DumbTask(SyncStatusCode status,
30              const SyncStatusCallback& callback) {
31  base::MessageLoop::current()->PostTask(
32      FROM_HERE, base::Bind(callback, status));
33}
34
35void IncrementAndAssign(int expected_before_counter,
36                        int* counter,
37                        SyncStatusCode* status_out,
38                        SyncStatusCode status) {
39  EXPECT_EQ(expected_before_counter, *counter);
40  ++(*counter);
41  *status_out = status;
42}
43
44template <typename T>
45void IncrementAndAssignWithOwnedPointer(T* object,
46                                        int* counter,
47                                        SyncStatusCode* status_out,
48                                        SyncStatusCode status) {
49  ++(*counter);
50  *status_out = status;
51}
52
53class TaskManagerClient
54    : public SyncTaskManager::Client,
55      public base::SupportsWeakPtr<TaskManagerClient> {
56 public:
57  explicit TaskManagerClient(int64 maximum_background_task)
58      : maybe_schedule_next_task_count_(0),
59        task_scheduled_count_(0),
60        idle_task_scheduled_count_(0),
61        last_operation_status_(SYNC_STATUS_OK) {
62    task_manager_.reset(new SyncTaskManager(
63        AsWeakPtr(), maximum_background_task));
64    task_manager_->Initialize(SYNC_STATUS_OK);
65    maybe_schedule_next_task_count_ = 0;
66  }
67  virtual ~TaskManagerClient() {}
68
69  // DriveFileSyncManager::Client overrides.
70  virtual void MaybeScheduleNextTask() OVERRIDE {
71    ++maybe_schedule_next_task_count_;
72  }
73  virtual void NotifyLastOperationStatus(
74      SyncStatusCode last_operation_status,
75      bool last_operation_used_network) OVERRIDE {
76    last_operation_status_ = last_operation_status;
77  }
78
79  virtual void RecordTaskLog(scoped_ptr<TaskLogger::TaskLog>) OVERRIDE {}
80
81  void ScheduleTask(SyncStatusCode status_to_return,
82                    const SyncStatusCallback& callback) {
83    task_manager_->ScheduleTask(
84        FROM_HERE,
85        base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(),
86                   status_to_return, false /* idle */),
87        SyncTaskManager::PRIORITY_MED,
88        callback);
89  }
90
91  void ScheduleTaskIfIdle(SyncStatusCode status_to_return) {
92    task_manager_->ScheduleTaskIfIdle(
93        FROM_HERE,
94        base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(),
95                   status_to_return, true /* idle */),
96        SyncStatusCallback());
97  }
98
99  int maybe_schedule_next_task_count() const {
100    return maybe_schedule_next_task_count_;
101  }
102  int task_scheduled_count() const { return task_scheduled_count_; }
103  int idle_task_scheduled_count() const { return idle_task_scheduled_count_; }
104  SyncStatusCode last_operation_status() const {
105    return last_operation_status_;
106  }
107
108 private:
109  void DoTask(SyncStatusCode status_to_return,
110              bool is_idle_task,
111              const SyncStatusCallback& callback) {
112    ++task_scheduled_count_;
113    if (is_idle_task)
114      ++idle_task_scheduled_count_;
115    base::MessageLoop::current()->PostTask(
116        FROM_HERE, base::Bind(callback, status_to_return));
117  }
118
119  scoped_ptr<SyncTaskManager> task_manager_;
120
121  int maybe_schedule_next_task_count_;
122  int task_scheduled_count_;
123  int idle_task_scheduled_count_;
124
125  SyncStatusCode last_operation_status_;
126
127  DISALLOW_COPY_AND_ASSIGN(TaskManagerClient);
128};
129
130class MultihopSyncTask : public ExclusiveTask {
131 public:
132  MultihopSyncTask(bool* task_started,
133                   bool* task_completed)
134      : task_started_(task_started),
135        task_completed_(task_completed),
136        weak_ptr_factory_(this) {
137    DCHECK(task_started_);
138    DCHECK(task_completed_);
139  }
140
141  virtual ~MultihopSyncTask() {}
142
143  virtual void RunExclusive(const SyncStatusCallback& callback) OVERRIDE {
144    DCHECK(!*task_started_);
145    *task_started_ = true;
146    base::MessageLoop::current()->PostTask(
147        FROM_HERE, base::Bind(&MultihopSyncTask::CompleteTask,
148                              weak_ptr_factory_.GetWeakPtr(), callback));
149  }
150
151 private:
152  void CompleteTask(const SyncStatusCallback& callback) {
153    DCHECK(*task_started_);
154    DCHECK(!*task_completed_);
155    *task_completed_ = true;
156    callback.Run(SYNC_STATUS_OK);
157  }
158
159  bool* task_started_;
160  bool* task_completed_;
161  base::WeakPtrFactory<MultihopSyncTask> weak_ptr_factory_;
162
163  DISALLOW_COPY_AND_ASSIGN(MultihopSyncTask);
164};
165
166class BackgroundTask : public SyncTask {
167 public:
168  struct Stats {
169    int64 running_background_task;
170    int64 finished_task;
171    int64 max_parallel_task;
172
173    Stats()
174        : running_background_task(0),
175          finished_task(0),
176          max_parallel_task(0) {}
177  };
178
179  BackgroundTask(const std::string& app_id,
180                 const base::FilePath& path,
181                 Stats* stats)
182      : app_id_(app_id),
183        path_(path),
184        stats_(stats),
185        weak_ptr_factory_(this) {
186  }
187
188  virtual ~BackgroundTask() {
189  }
190
191  virtual void RunPreflight(scoped_ptr<SyncTaskToken> token) OVERRIDE {
192    scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor);
193    blocking_factor->app_id = app_id_;
194    blocking_factor->paths.push_back(path_);
195
196    SyncTaskManager::UpdateBlockingFactor(
197        token.Pass(), blocking_factor.Pass(),
198        base::Bind(&BackgroundTask::RunAsBackgroundTask,
199                   weak_ptr_factory_.GetWeakPtr()));
200  }
201
202 private:
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;
207
208    base::MessageLoop::current()->PostTask(
209        FROM_HERE,
210        base::Bind(&BackgroundTask::CompleteTask,
211                   weak_ptr_factory_.GetWeakPtr(),
212                   base::Passed(&token)));
213  }
214
215  void CompleteTask(scoped_ptr<SyncTaskToken> token) {
216    ++(stats_->finished_task);
217    --(stats_->running_background_task);
218    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
219  }
220
221  std::string app_id_;
222  base::FilePath path_;
223  Stats* stats_;
224
225  base::WeakPtrFactory<BackgroundTask> weak_ptr_factory_;
226
227  DISALLOW_COPY_AND_ASSIGN(BackgroundTask);
228};
229
230class BlockerUpdateTestHelper : public SyncTask {
231 public:
232  typedef std::vector<std::string> Log;
233
234  BlockerUpdateTestHelper(const std::string& name,
235                          const std::string& app_id,
236                          const std::vector<std::string>& paths,
237                          Log* log)
238      : name_(name),
239        app_id_(app_id),
240        paths_(paths.begin(), paths.end()),
241        log_(log),
242        weak_ptr_factory_(this) {
243  }
244
245  virtual ~BlockerUpdateTestHelper() {
246  }
247
248  virtual void RunPreflight(scoped_ptr<SyncTaskToken> token) OVERRIDE {
249    UpdateBlocker(token.Pass());
250  }
251
252 private:
253  void UpdateBlocker(scoped_ptr<SyncTaskToken> token) {
254    if (paths_.empty()) {
255      log_->push_back(name_ + ": finished");
256      SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
257      return;
258    }
259
260    std::string updating_to = paths_.front();
261    paths_.pop_front();
262
263    log_->push_back(name_ + ": updating to " + updating_to);
264
265    scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor);
266    blocking_factor->app_id = app_id_;
267    blocking_factor->paths.push_back(
268        base::FilePath(fileapi::VirtualPath::GetNormalizedFilePath(
269            base::FilePath::FromUTF8Unsafe(updating_to))));
270
271    SyncTaskManager::UpdateBlockingFactor(
272        token.Pass(), blocking_factor.Pass(),
273        base::Bind(&BlockerUpdateTestHelper::UpdateBlockerSoon,
274                   weak_ptr_factory_.GetWeakPtr(),
275                   updating_to));
276  }
277
278  void UpdateBlockerSoon(const std::string& updated_to,
279                         scoped_ptr<SyncTaskToken> token) {
280    log_->push_back(name_ + ": updated to " + updated_to);
281    base::MessageLoop::current()->PostTask(
282        FROM_HERE,
283        base::Bind(&BlockerUpdateTestHelper::UpdateBlocker,
284                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
285  }
286
287  std::string name_;
288  std::string app_id_;
289  std::deque<std::string> paths_;
290  Log* log_;
291
292  base::WeakPtrFactory<BlockerUpdateTestHelper> weak_ptr_factory_;
293
294  DISALLOW_COPY_AND_ASSIGN(BlockerUpdateTestHelper);
295};
296
297// Arbitrary non-default status values for testing.
298const SyncStatusCode kStatus1 = static_cast<SyncStatusCode>(-1);
299const SyncStatusCode kStatus2 = static_cast<SyncStatusCode>(-2);
300const SyncStatusCode kStatus3 = static_cast<SyncStatusCode>(-3);
301const SyncStatusCode kStatus4 = static_cast<SyncStatusCode>(-4);
302const SyncStatusCode kStatus5 = static_cast<SyncStatusCode>(-5);
303
304}  // namespace
305
306TEST(SyncTaskManagerTest, ScheduleTask) {
307  base::MessageLoop message_loop;
308  TaskManagerClient client(0 /* maximum_background_task */);
309  int callback_count = 0;
310  SyncStatusCode callback_status = SYNC_STATUS_OK;
311
312  client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
313                                           &callback_count,
314                                           &callback_status));
315  message_loop.RunUntilIdle();
316
317  EXPECT_EQ(kStatus1, callback_status);
318  EXPECT_EQ(kStatus1, client.last_operation_status());
319
320  EXPECT_EQ(1, callback_count);
321  EXPECT_EQ(1, client.maybe_schedule_next_task_count());
322  EXPECT_EQ(1, client.task_scheduled_count());
323  EXPECT_EQ(0, client.idle_task_scheduled_count());
324}
325
326TEST(SyncTaskManagerTest, ScheduleTwoTasks) {
327  base::MessageLoop message_loop;
328  TaskManagerClient client(0 /* maximum_background_task */);
329  int callback_count = 0;
330  SyncStatusCode callback_status = SYNC_STATUS_OK;
331
332  client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
333                                           &callback_count,
334                                           &callback_status));
335  client.ScheduleTask(kStatus2, base::Bind(&IncrementAndAssign, 1,
336                                           &callback_count,
337                                           &callback_status));
338  message_loop.RunUntilIdle();
339
340  EXPECT_EQ(kStatus2, callback_status);
341  EXPECT_EQ(kStatus2, client.last_operation_status());
342
343  EXPECT_EQ(2, callback_count);
344  EXPECT_EQ(1, client.maybe_schedule_next_task_count());
345  EXPECT_EQ(2, client.task_scheduled_count());
346  EXPECT_EQ(0, client.idle_task_scheduled_count());
347}
348
349TEST(SyncTaskManagerTest, ScheduleIdleTask) {
350  base::MessageLoop message_loop;
351  TaskManagerClient client(0 /* maximum_background_task */);
352
353  client.ScheduleTaskIfIdle(kStatus1);
354  message_loop.RunUntilIdle();
355
356  EXPECT_EQ(kStatus1, client.last_operation_status());
357
358  EXPECT_EQ(1, client.maybe_schedule_next_task_count());
359  EXPECT_EQ(1, client.task_scheduled_count());
360  EXPECT_EQ(1, client.idle_task_scheduled_count());
361}
362
363TEST(SyncTaskManagerTest, ScheduleIdleTaskWhileNotIdle) {
364  base::MessageLoop message_loop;
365  TaskManagerClient client(0 /* maximum_background_task */);
366  int callback_count = 0;
367  SyncStatusCode callback_status = SYNC_STATUS_OK;
368
369  client.ScheduleTask(kStatus1, base::Bind(&IncrementAndAssign, 0,
370                                           &callback_count,
371                                           &callback_status));
372  client.ScheduleTaskIfIdle(kStatus2);
373  message_loop.RunUntilIdle();
374
375  // Idle task must not have run.
376  EXPECT_EQ(kStatus1, callback_status);
377  EXPECT_EQ(kStatus1, client.last_operation_status());
378
379  EXPECT_EQ(1, callback_count);
380  EXPECT_EQ(1, client.maybe_schedule_next_task_count());
381  EXPECT_EQ(1, client.task_scheduled_count());
382  EXPECT_EQ(0, client.idle_task_scheduled_count());
383}
384
385TEST(SyncTaskManagerTest, ScheduleAndCancelSyncTask) {
386  base::MessageLoop message_loop;
387
388  int callback_count = 0;
389  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
390
391  bool task_started = false;
392  bool task_completed = false;
393
394  {
395    SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
396                                 0 /* maximum_background_task */);
397    task_manager.Initialize(SYNC_STATUS_OK);
398    task_manager.ScheduleSyncTask(
399        FROM_HERE,
400        scoped_ptr<SyncTask>(new MultihopSyncTask(
401            &task_started, &task_completed)),
402        SyncTaskManager::PRIORITY_MED,
403        base::Bind(&IncrementAndAssign, 0, &callback_count, &status));
404  }
405
406  message_loop.RunUntilIdle();
407  EXPECT_EQ(0, callback_count);
408  EXPECT_EQ(SYNC_STATUS_UNKNOWN, status);
409  EXPECT_TRUE(task_started);
410  EXPECT_FALSE(task_completed);
411}
412
413TEST(SyncTaskManagerTest, ScheduleTaskAtPriority) {
414  base::MessageLoop message_loop;
415  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
416                               0 /* maximum_background_task */);
417  task_manager.Initialize(SYNC_STATUS_OK);
418
419  int callback_count = 0;
420  SyncStatusCode callback_status1 = SYNC_STATUS_OK;
421  SyncStatusCode callback_status2 = SYNC_STATUS_OK;
422  SyncStatusCode callback_status3 = SYNC_STATUS_OK;
423  SyncStatusCode callback_status4 = SYNC_STATUS_OK;
424  SyncStatusCode callback_status5 = SYNC_STATUS_OK;
425
426  // This will run first even if its priority is low, since there're no
427  // pending tasks.
428  task_manager.ScheduleTask(
429      FROM_HERE,
430      base::Bind(&DumbTask, kStatus1),
431      SyncTaskManager::PRIORITY_LOW,
432      base::Bind(&IncrementAndAssign, 0, &callback_count, &callback_status1));
433
434  // This runs last (expected counter == 4).
435  task_manager.ScheduleTask(
436      FROM_HERE,
437      base::Bind(&DumbTask, kStatus2),
438      SyncTaskManager::PRIORITY_LOW,
439      base::Bind(&IncrementAndAssign, 4, &callback_count, &callback_status2));
440
441  // This runs second (expected counter == 1).
442  task_manager.ScheduleTask(
443      FROM_HERE,
444      base::Bind(&DumbTask, kStatus3),
445      SyncTaskManager::PRIORITY_HIGH,
446      base::Bind(&IncrementAndAssign, 1, &callback_count, &callback_status3));
447
448  // This runs fourth (expected counter == 3).
449  task_manager.ScheduleTask(
450      FROM_HERE,
451      base::Bind(&DumbTask, kStatus4),
452      SyncTaskManager::PRIORITY_MED,
453      base::Bind(&IncrementAndAssign, 3, &callback_count, &callback_status4));
454
455  // This runs third (expected counter == 2).
456  task_manager.ScheduleTask(
457      FROM_HERE,
458      base::Bind(&DumbTask, kStatus5),
459      SyncTaskManager::PRIORITY_HIGH,
460      base::Bind(&IncrementAndAssign, 2, &callback_count, &callback_status5));
461
462  message_loop.RunUntilIdle();
463
464  EXPECT_EQ(kStatus1, callback_status1);
465  EXPECT_EQ(kStatus2, callback_status2);
466  EXPECT_EQ(kStatus3, callback_status3);
467  EXPECT_EQ(kStatus4, callback_status4);
468  EXPECT_EQ(kStatus5, callback_status5);
469  EXPECT_EQ(5, callback_count);
470}
471
472TEST(SyncTaskManagerTest, BackgroundTask_Sequential) {
473  base::MessageLoop message_loop;
474  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
475                               10 /* maximum_background_task */);
476  task_manager.Initialize(SYNC_STATUS_OK);
477
478  SyncStatusCode status = SYNC_STATUS_FAILED;
479  BackgroundTask::Stats stats;
480  task_manager.ScheduleSyncTask(
481      FROM_HERE,
482      scoped_ptr<SyncTask>(new BackgroundTask(
483          "app_id", MAKE_PATH("/hoge/fuga"),
484          &stats)),
485      SyncTaskManager::PRIORITY_MED,
486      CreateResultReceiver(&status));
487
488  task_manager.ScheduleSyncTask(
489      FROM_HERE,
490      scoped_ptr<SyncTask>(new BackgroundTask(
491          "app_id", MAKE_PATH("/hoge"),
492          &stats)),
493      SyncTaskManager::PRIORITY_MED,
494      CreateResultReceiver(&status));
495
496  task_manager.ScheduleSyncTask(
497      FROM_HERE,
498      scoped_ptr<SyncTask>(new BackgroundTask(
499          "app_id", MAKE_PATH("/hoge/fuga/piyo"),
500          &stats)),
501      SyncTaskManager::PRIORITY_MED,
502      CreateResultReceiver(&status));
503
504  message_loop.RunUntilIdle();
505
506  EXPECT_EQ(SYNC_STATUS_OK, status);
507  EXPECT_EQ(0, stats.running_background_task);
508  EXPECT_EQ(3, stats.finished_task);
509  EXPECT_EQ(1, stats.max_parallel_task);
510}
511
512TEST(SyncTaskManagerTest, BackgroundTask_Parallel) {
513  base::MessageLoop message_loop;
514  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
515                               10 /* maximum_background_task */);
516  task_manager.Initialize(SYNC_STATUS_OK);
517
518  SyncStatusCode status = SYNC_STATUS_FAILED;
519  BackgroundTask::Stats stats;
520  task_manager.ScheduleSyncTask(
521      FROM_HERE,
522      scoped_ptr<SyncTask>(new BackgroundTask(
523          "app_id", MAKE_PATH("/hoge"),
524          &stats)),
525      SyncTaskManager::PRIORITY_MED,
526      CreateResultReceiver(&status));
527
528  task_manager.ScheduleSyncTask(
529      FROM_HERE,
530      scoped_ptr<SyncTask>(new BackgroundTask(
531          "app_id", MAKE_PATH("/fuga"),
532          &stats)),
533      SyncTaskManager::PRIORITY_MED,
534      CreateResultReceiver(&status));
535
536  task_manager.ScheduleSyncTask(
537      FROM_HERE,
538      scoped_ptr<SyncTask>(new BackgroundTask(
539          "app_id", MAKE_PATH("/piyo"),
540          &stats)),
541      SyncTaskManager::PRIORITY_MED,
542      CreateResultReceiver(&status));
543
544  message_loop.RunUntilIdle();
545
546  EXPECT_EQ(SYNC_STATUS_OK, status);
547  EXPECT_EQ(0, stats.running_background_task);
548  EXPECT_EQ(3, stats.finished_task);
549  EXPECT_EQ(3, stats.max_parallel_task);
550}
551
552TEST(SyncTaskManagerTest, BackgroundTask_Throttled) {
553  base::MessageLoop message_loop;
554  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
555                               2 /* maximum_background_task */);
556  task_manager.Initialize(SYNC_STATUS_OK);
557
558  SyncStatusCode status = SYNC_STATUS_FAILED;
559  BackgroundTask::Stats stats;
560  task_manager.ScheduleSyncTask(
561      FROM_HERE,
562      scoped_ptr<SyncTask>(new BackgroundTask(
563          "app_id", MAKE_PATH("/hoge"),
564          &stats)),
565      SyncTaskManager::PRIORITY_MED,
566      CreateResultReceiver(&status));
567
568  task_manager.ScheduleSyncTask(
569      FROM_HERE,
570      scoped_ptr<SyncTask>(new BackgroundTask(
571          "app_id", MAKE_PATH("/fuga"),
572          &stats)),
573      SyncTaskManager::PRIORITY_MED,
574      CreateResultReceiver(&status));
575
576  task_manager.ScheduleSyncTask(
577      FROM_HERE,
578      scoped_ptr<SyncTask>(new BackgroundTask(
579          "app_id", MAKE_PATH("/piyo"),
580          &stats)),
581      SyncTaskManager::PRIORITY_MED,
582      CreateResultReceiver(&status));
583
584  message_loop.RunUntilIdle();
585
586  EXPECT_EQ(SYNC_STATUS_OK, status);
587  EXPECT_EQ(0, stats.running_background_task);
588  EXPECT_EQ(3, stats.finished_task);
589  EXPECT_EQ(2, stats.max_parallel_task);
590}
591
592TEST(SyncTaskManagerTest, UpdateBlockingFactor) {
593  base::MessageLoop message_loop;
594  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
595                               10 /* maximum_background_task */);
596  task_manager.Initialize(SYNC_STATUS_OK);
597
598  SyncStatusCode status = SYNC_STATUS_FAILED;
599  BlockerUpdateTestHelper::Log log;
600
601  {
602    std::vector<std::string> paths;
603    paths.push_back("/foo/bar");
604    paths.push_back("/foo");
605    paths.push_back("/hoge/fuga/piyo");
606    task_manager.ScheduleSyncTask(
607        FROM_HERE,
608        scoped_ptr<SyncTask>(new BlockerUpdateTestHelper(
609            "task1", "app_id", paths, &log)),
610        SyncTaskManager::PRIORITY_MED,
611        CreateResultReceiver(&status));
612  }
613
614  {
615    std::vector<std::string> paths;
616    paths.push_back("/foo");
617    paths.push_back("/foo/bar");
618    paths.push_back("/hoge/fuga/piyo");
619    task_manager.ScheduleSyncTask(
620        FROM_HERE,
621        scoped_ptr<SyncTask>(new BlockerUpdateTestHelper(
622            "task2", "app_id", paths, &log)),
623        SyncTaskManager::PRIORITY_MED,
624        CreateResultReceiver(&status));
625  }
626
627  message_loop.RunUntilIdle();
628
629  EXPECT_EQ(SYNC_STATUS_OK, status);
630
631  ASSERT_EQ(14u, log.size());
632  int i = 0;
633
634  // task1 takes "/foo/bar" first.
635  EXPECT_EQ("task1: updating to /foo/bar", log[i++]);
636  EXPECT_EQ("task1: updated to /foo/bar", log[i++]);
637
638  // task1 blocks task2. task2's update should be pending until task1 update.
639  EXPECT_EQ("task2: updating to /foo", log[i++]);
640
641  // task1 releases "/foo/bar" and tries to take "/foo". Then, pending task2
642  // takes "/foo" and blocks task1.
643  EXPECT_EQ("task1: updating to /foo", log[i++]);
644  EXPECT_EQ("task2: updated to /foo", log[i++]);
645
646  // task2 releases "/foo".
647  EXPECT_EQ("task2: updating to /foo/bar", log[i++]);
648  EXPECT_EQ("task1: updated to /foo", log[i++]);
649
650  // task1 releases "/foo".
651  EXPECT_EQ("task1: updating to /hoge/fuga/piyo", log[i++]);
652  EXPECT_EQ("task1: updated to /hoge/fuga/piyo", log[i++]);
653  EXPECT_EQ("task2: updated to /foo/bar", log[i++]);
654
655  EXPECT_EQ("task1: finished", log[i++]);
656
657  EXPECT_EQ("task2: updating to /hoge/fuga/piyo", log[i++]);
658  EXPECT_EQ("task2: updated to /hoge/fuga/piyo", log[i++]);
659  EXPECT_EQ("task2: finished", log[i++]);
660}
661
662}  // namespace drive_backend
663}  // namespace sync_file_system
664