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