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