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