sync_task_manager_unittest.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/weak_ptr.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/message_loop/message_loop.h" 12c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "base/run_loop.h" 13c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "chrome/browser/sync_file_system/drive_backend/sync_task.h" 14c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" 15c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" 16c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 17c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "testing/gtest/include/gtest/gtest.h" 18c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "webkit/common/fileapi/file_system_util.h" 19c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MAKE_PATH(path) \ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FilePath(fileapi::VirtualPath::GetNormalizedFilePath( \ 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FilePath(FILE_PATH_LITERAL(path)))) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive_backend { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumbTask(SyncStatusCode status, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SyncStatusCallback& callback) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoop::current()->PostTask( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(callback, status)); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IncrementAndAssign(int expected_before_counter, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* counter, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncStatusCode* status_out, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncStatusCode status) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_before_counter, *counter); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++(*counter); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status_out = status; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template <typename T> 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IncrementAndAssignWithOwnedPointer(T* object, 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int* counter, 47c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncStatusCode* status_out, 48c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncStatusCode status) { 49c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++(*counter); 50c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch *status_out = status; 51c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 52c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 53c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochclass TaskManagerClient 54c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch : public SyncTaskManager::Client, 55c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch public base::SupportsWeakPtr<TaskManagerClient> { 56c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch public: 57c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch explicit TaskManagerClient(int64 maximum_background_task) 58c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch : maybe_schedule_next_task_count_(0), 59c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch task_scheduled_count_(0), 60c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch idle_task_scheduled_count_(0), 61c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch last_operation_status_(SYNC_STATUS_OK) { 62c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch task_manager_.reset(new SyncTaskManager( 63c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch AsWeakPtr(), maximum_background_task, 64c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::MessageLoopProxy::current())); 65c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch task_manager_->Initialize(SYNC_STATUS_OK); 66c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 67c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch maybe_schedule_next_task_count_ = 0; 68c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 69c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual ~TaskManagerClient() {} 70c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 71c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // DriveFileSyncManager::Client overrides. 72c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual void MaybeScheduleNextTask() OVERRIDE { 73c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++maybe_schedule_next_task_count_; 74c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 75c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual void NotifyLastOperationStatus( 76c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncStatusCode last_operation_status, 77c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool last_operation_used_network) OVERRIDE { 78c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch last_operation_status_ = last_operation_status; 79c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 80c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 81c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch virtual void RecordTaskLog(scoped_ptr<TaskLogger::TaskLog>) OVERRIDE {} 82c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 83c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void ScheduleTask(SyncStatusCode status_to_return, 84c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const SyncStatusCallback& callback) { 85c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch task_manager_->ScheduleTask( 86c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch FROM_HERE, 87c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(), 88c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch status_to_return, false /* idle */), 89c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncTaskManager::PRIORITY_MED, 90c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch callback); 91c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 92c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 93c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void ScheduleTaskIfIdle(SyncStatusCode status_to_return) { 94c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch task_manager_->ScheduleTaskIfIdle( 95c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch FROM_HERE, 96c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::Bind(&TaskManagerClient::DoTask, AsWeakPtr(), 97c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch status_to_return, true /* idle */), 98c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncStatusCallback()); 99c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 100c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 101c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int maybe_schedule_next_task_count() const { 102c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return maybe_schedule_next_task_count_; 103c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 104c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int task_scheduled_count() const { return task_scheduled_count_; } 105c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int idle_task_scheduled_count() const { return idle_task_scheduled_count_; } 106c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch SyncStatusCode last_operation_status() const { 107c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return last_operation_status_; 108c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 109c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 110c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch private: 111c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch void DoTask(SyncStatusCode status_to_return, 112c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool is_idle_task, 113c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const SyncStatusCallback& callback) { 114c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++task_scheduled_count_; 115c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (is_idle_task) 116c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch ++idle_task_scheduled_count_; 117c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::MessageLoop::current()->PostTask( 118c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch FROM_HERE, base::Bind(callback, status_to_return)); 119c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 120c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 121c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch scoped_ptr<SyncTaskManager> task_manager_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int maybe_schedule_next_task_count_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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 132class 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 168class 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 232class 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. 300const SyncStatusCode kStatus1 = static_cast<SyncStatusCode>(-1); 301const SyncStatusCode kStatus2 = static_cast<SyncStatusCode>(-2); 302const SyncStatusCode kStatus3 = static_cast<SyncStatusCode>(-3); 303const SyncStatusCode kStatus4 = static_cast<SyncStatusCode>(-4); 304const SyncStatusCode kStatus5 = static_cast<SyncStatusCode>(-5); 305 306} // namespace 307 308TEST(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 328TEST(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 351TEST(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 365TEST(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 387TEST(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 417TEST(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 478TEST(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 519TEST(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 560TEST(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 601TEST(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