job_scheduler_unittest.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1// Copyright (c) 2012 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 "chrome/browser/chromeos/drive/job_scheduler.h" 6 7#include <set> 8 9#include "base/bind.h" 10#include "base/file_util.h" 11#include "base/files/scoped_temp_dir.h" 12#include "base/prefs/testing_pref_service.h" 13#include "base/run_loop.h" 14#include "base/stl_util.h" 15#include "base/strings/stringprintf.h" 16#include "chrome/browser/chromeos/drive/test_util.h" 17#include "chrome/browser/drive/event_logger.h" 18#include "chrome/browser/drive/fake_drive_service.h" 19#include "chrome/browser/drive/test_util.h" 20#include "chrome/common/pref_names.h" 21#include "content/public/test/test_browser_thread_bundle.h" 22#include "google_apis/drive/drive_api_parser.h" 23#include "google_apis/drive/gdata_wapi_parser.h" 24#include "google_apis/drive/test_util.h" 25#include "testing/gtest/include/gtest/gtest.h" 26 27namespace drive { 28 29namespace { 30 31// Dummy value passed for the |expected_file_size| parameter of DownloadFile(). 32const int64 kDummyDownloadFileSize = 0; 33 34void CopyTitleFromGetResourceEntryCallback( 35 std::vector<std::string>* title_list_out, 36 google_apis::GDataErrorCode error_in, 37 scoped_ptr<google_apis::ResourceEntry> resource_entry_in) { 38 title_list_out->push_back(resource_entry_in->title()); 39} 40 41class JobListLogger : public JobListObserver { 42 public: 43 enum EventType { 44 ADDED, 45 UPDATED, 46 DONE, 47 }; 48 49 struct EventLog { 50 EventType type; 51 JobInfo info; 52 53 EventLog(EventType type, const JobInfo& info) : type(type), info(info) { 54 } 55 }; 56 57 // Checks whether the specified type of event has occurred. 58 bool Has(EventType type, JobType job_type) { 59 for (size_t i = 0; i < events.size(); ++i) { 60 if (events[i].type == type && events[i].info.job_type == job_type) 61 return true; 62 } 63 return false; 64 } 65 66 // Gets the progress event information of the specified type. 67 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) { 68 for (size_t i = 0; i < events.size(); ++i) { 69 if (events[i].type == UPDATED && events[i].info.job_type == job_type) 70 progress->push_back(events[i].info.num_completed_bytes); 71 } 72 } 73 74 // JobListObserver overrides. 75 virtual void OnJobAdded(const JobInfo& info) OVERRIDE { 76 events.push_back(EventLog(ADDED, info)); 77 } 78 79 virtual void OnJobUpdated(const JobInfo& info) OVERRIDE { 80 events.push_back(EventLog(UPDATED, info)); 81 } 82 83 virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE { 84 events.push_back(EventLog(DONE, info)); 85 } 86 87 private: 88 std::vector<EventLog> events; 89}; 90 91// Fake drive service extended for testing cancellation. 92// When upload_new_file_cancelable is set, this Drive service starts 93// returning a closure to cancel from InitiateUploadNewFile(). The task will 94// finish only when the cancel closure is called. 95class CancelTestableFakeDriveService : public FakeDriveService { 96 public: 97 CancelTestableFakeDriveService() 98 : upload_new_file_cancelable_(false) { 99 } 100 101 void set_upload_new_file_cancelable(bool cancelable) { 102 upload_new_file_cancelable_ = cancelable; 103 } 104 105 virtual google_apis::CancelCallback InitiateUploadNewFile( 106 const std::string& content_type, 107 int64 content_length, 108 const std::string& parent_resource_id, 109 const std::string& title, 110 const InitiateUploadNewFileOptions& options, 111 const google_apis::InitiateUploadCallback& callback) OVERRIDE { 112 if (upload_new_file_cancelable_) 113 return base::Bind(callback, google_apis::GDATA_CANCELLED, GURL()); 114 115 return FakeDriveService::InitiateUploadNewFile(content_type, 116 content_length, 117 parent_resource_id, 118 title, 119 options, 120 callback); 121 } 122 123 private: 124 bool upload_new_file_cancelable_; 125}; 126 127} // namespace 128 129class JobSchedulerTest : public testing::Test { 130 public: 131 JobSchedulerTest() 132 : pref_service_(new TestingPrefServiceSimple) { 133 test_util::RegisterDrivePrefs(pref_service_->registry()); 134 } 135 136 virtual void SetUp() OVERRIDE { 137 fake_network_change_notifier_.reset( 138 new test_util::FakeNetworkChangeNotifier); 139 140 logger_.reset(new EventLogger); 141 142 fake_drive_service_.reset(new CancelTestableFakeDriveService); 143 test_util::SetUpTestEntries(fake_drive_service_.get()); 144 fake_drive_service_->LoadAppListForDriveApi("drive/applist.json"); 145 146 scheduler_.reset(new JobScheduler(pref_service_.get(), 147 logger_.get(), 148 fake_drive_service_.get(), 149 base::MessageLoopProxy::current().get())); 150 scheduler_->SetDisableThrottling(true); 151 } 152 153 protected: 154 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with 155 // the specified connection type. 156 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) { 157 fake_network_change_notifier_->SetConnectionType(type); 158 } 159 160 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network. 161 void ConnectToWifi() { 162 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); 163 } 164 165 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network. 166 void ConnectToCellular() { 167 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G); 168 } 169 170 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network. 171 void ConnectToWimax() { 172 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G); 173 } 174 175 // Sets up FakeNetworkChangeNotifier as if it's disconnected. 176 void ConnectToNone() { 177 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE); 178 } 179 180 static int GetMetadataQueueMaxJobCount() { 181 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE]; 182 } 183 184 content::TestBrowserThreadBundle thread_bundle_; 185 scoped_ptr<TestingPrefServiceSimple> pref_service_; 186 scoped_ptr<test_util::FakeNetworkChangeNotifier> 187 fake_network_change_notifier_; 188 scoped_ptr<EventLogger> logger_; 189 scoped_ptr<CancelTestableFakeDriveService> fake_drive_service_; 190 scoped_ptr<JobScheduler> scheduler_; 191}; 192 193TEST_F(JobSchedulerTest, GetAboutResource) { 194 ConnectToWifi(); 195 196 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 197 scoped_ptr<google_apis::AboutResource> about_resource; 198 scheduler_->GetAboutResource( 199 google_apis::test_util::CreateCopyResultCallback( 200 &error, &about_resource)); 201 base::RunLoop().RunUntilIdle(); 202 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 203 ASSERT_TRUE(about_resource); 204} 205 206TEST_F(JobSchedulerTest, GetAppList) { 207 ConnectToWifi(); 208 209 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 210 scoped_ptr<google_apis::AppList> app_list; 211 212 scheduler_->GetAppList( 213 google_apis::test_util::CreateCopyResultCallback(&error, &app_list)); 214 base::RunLoop().RunUntilIdle(); 215 216 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 217 ASSERT_TRUE(app_list); 218} 219 220TEST_F(JobSchedulerTest, GetAllResourceList) { 221 ConnectToWifi(); 222 223 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 224 scoped_ptr<google_apis::ResourceList> resource_list; 225 226 scheduler_->GetAllResourceList( 227 google_apis::test_util::CreateCopyResultCallback( 228 &error, &resource_list)); 229 base::RunLoop().RunUntilIdle(); 230 231 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 232 ASSERT_TRUE(resource_list); 233} 234 235TEST_F(JobSchedulerTest, GetResourceListInDirectory) { 236 ConnectToWifi(); 237 238 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 239 scoped_ptr<google_apis::ResourceList> resource_list; 240 241 scheduler_->GetResourceListInDirectory( 242 fake_drive_service_->GetRootResourceId(), 243 google_apis::test_util::CreateCopyResultCallback( 244 &error, &resource_list)); 245 base::RunLoop().RunUntilIdle(); 246 247 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 248 ASSERT_TRUE(resource_list); 249} 250 251TEST_F(JobSchedulerTest, Search) { 252 ConnectToWifi(); 253 254 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 255 scoped_ptr<google_apis::ResourceList> resource_list; 256 257 scheduler_->Search( 258 "File", // search query 259 google_apis::test_util::CreateCopyResultCallback( 260 &error, &resource_list)); 261 base::RunLoop().RunUntilIdle(); 262 263 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 264 ASSERT_TRUE(resource_list); 265} 266 267TEST_F(JobSchedulerTest, GetChangeList) { 268 ConnectToWifi(); 269 270 int64 old_largest_change_id = 271 fake_drive_service_->about_resource().largest_change_id(); 272 273 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 274 275 // Create a new directory. 276 { 277 scoped_ptr<google_apis::ResourceEntry> resource_entry; 278 fake_drive_service_->AddNewDirectory( 279 fake_drive_service_->GetRootResourceId(), 280 "new directory", 281 DriveServiceInterface::AddNewDirectoryOptions(), 282 google_apis::test_util::CreateCopyResultCallback( 283 &error, &resource_entry)); 284 base::RunLoop().RunUntilIdle(); 285 ASSERT_EQ(google_apis::HTTP_CREATED, error); 286 } 287 288 error = google_apis::GDATA_OTHER_ERROR; 289 scoped_ptr<google_apis::ResourceList> resource_list; 290 scheduler_->GetChangeList( 291 old_largest_change_id + 1, 292 google_apis::test_util::CreateCopyResultCallback( 293 &error, &resource_list)); 294 base::RunLoop().RunUntilIdle(); 295 296 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 297 ASSERT_TRUE(resource_list); 298} 299 300TEST_F(JobSchedulerTest, GetRemainingChangeList) { 301 ConnectToWifi(); 302 fake_drive_service_->set_default_max_results(2); 303 304 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 305 scoped_ptr<google_apis::ResourceList> resource_list; 306 307 scheduler_->GetAllResourceList( 308 google_apis::test_util::CreateCopyResultCallback( 309 &error, &resource_list)); 310 base::RunLoop().RunUntilIdle(); 311 312 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 313 ASSERT_TRUE(resource_list); 314 315 const google_apis::Link* next_link = 316 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT); 317 ASSERT_TRUE(next_link); 318 // Keep the next url before releasing the |resource_list|. 319 GURL next_url(next_link->href()); 320 321 error = google_apis::GDATA_OTHER_ERROR; 322 resource_list.reset(); 323 324 scheduler_->GetRemainingChangeList( 325 next_url, 326 google_apis::test_util::CreateCopyResultCallback( 327 &error, &resource_list)); 328 base::RunLoop().RunUntilIdle(); 329 330 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 331 ASSERT_TRUE(resource_list); 332} 333 334TEST_F(JobSchedulerTest, GetRemainingFileList) { 335 ConnectToWifi(); 336 fake_drive_service_->set_default_max_results(2); 337 338 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 339 scoped_ptr<google_apis::ResourceList> resource_list; 340 341 scheduler_->GetResourceListInDirectory( 342 fake_drive_service_->GetRootResourceId(), 343 google_apis::test_util::CreateCopyResultCallback( 344 &error, &resource_list)); 345 base::RunLoop().RunUntilIdle(); 346 347 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 348 ASSERT_TRUE(resource_list); 349 350 const google_apis::Link* next_link = 351 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT); 352 ASSERT_TRUE(next_link); 353 // Keep the next url before releasing the |resource_list|. 354 GURL next_url(next_link->href()); 355 356 error = google_apis::GDATA_OTHER_ERROR; 357 resource_list.reset(); 358 359 scheduler_->GetRemainingFileList( 360 next_url, 361 google_apis::test_util::CreateCopyResultCallback( 362 &error, &resource_list)); 363 base::RunLoop().RunUntilIdle(); 364 365 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 366 ASSERT_TRUE(resource_list); 367} 368 369TEST_F(JobSchedulerTest, GetResourceEntry) { 370 ConnectToWifi(); 371 372 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 373 scoped_ptr<google_apis::ResourceEntry> entry; 374 375 scheduler_->GetResourceEntry( 376 "file:2_file_resource_id", // resource ID 377 ClientContext(USER_INITIATED), 378 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 379 base::RunLoop().RunUntilIdle(); 380 381 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 382 ASSERT_TRUE(entry); 383} 384 385TEST_F(JobSchedulerTest, GetShareUrl) { 386 ConnectToWifi(); 387 388 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 389 GURL share_url; 390 391 scheduler_->GetShareUrl( 392 "file:2_file_resource_id", // resource ID 393 GURL("chrome-extension://test-id/"), // embed origin 394 ClientContext(USER_INITIATED), 395 google_apis::test_util::CreateCopyResultCallback(&error, &share_url)); 396 base::RunLoop().RunUntilIdle(); 397 398 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 399 ASSERT_FALSE(share_url.is_empty()); 400} 401 402TEST_F(JobSchedulerTest, TrashResource) { 403 ConnectToWifi(); 404 405 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 406 407 scheduler_->TrashResource( 408 "file:2_file_resource_id", 409 ClientContext(USER_INITIATED), 410 google_apis::test_util::CreateCopyResultCallback(&error)); 411 base::RunLoop().RunUntilIdle(); 412 413 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 414} 415 416TEST_F(JobSchedulerTest, CopyResource) { 417 ConnectToWifi(); 418 419 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 420 scoped_ptr<google_apis::ResourceEntry> entry; 421 422 scheduler_->CopyResource( 423 "file:2_file_resource_id", // resource ID 424 "folder:1_folder_resource_id", // parent resource ID 425 "New Document", // new title 426 base::Time(), 427 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 428 base::RunLoop().RunUntilIdle(); 429 430 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 431 ASSERT_TRUE(entry); 432} 433 434TEST_F(JobSchedulerTest, UpdateResource) { 435 ConnectToWifi(); 436 437 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 438 scoped_ptr<google_apis::ResourceEntry> entry; 439 440 scheduler_->UpdateResource( 441 "file:2_file_resource_id", // resource ID 442 "folder:1_folder_resource_id", // parent resource ID 443 "New Document", // new title 444 base::Time(), 445 base::Time(), 446 ClientContext(USER_INITIATED), 447 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 448 base::RunLoop().RunUntilIdle(); 449 450 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 451 ASSERT_TRUE(entry); 452} 453 454TEST_F(JobSchedulerTest, RenameResource) { 455 ConnectToWifi(); 456 457 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 458 459 scheduler_->RenameResource( 460 "file:2_file_resource_id", 461 "New Title", 462 google_apis::test_util::CreateCopyResultCallback(&error)); 463 base::RunLoop().RunUntilIdle(); 464 465 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 466} 467 468TEST_F(JobSchedulerTest, AddResourceToDirectory) { 469 ConnectToWifi(); 470 471 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 472 473 scheduler_->AddResourceToDirectory( 474 "folder:1_folder_resource_id", 475 "file:2_file_resource_id", 476 google_apis::test_util::CreateCopyResultCallback(&error)); 477 base::RunLoop().RunUntilIdle(); 478 479 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 480} 481 482TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) { 483 ConnectToWifi(); 484 485 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 486 487 scheduler_->RemoveResourceFromDirectory( 488 "folder:1_folder_resource_id", 489 "file:subdirectory_file_1_id", // resource ID 490 ClientContext(USER_INITIATED), 491 google_apis::test_util::CreateCopyResultCallback(&error)); 492 base::RunLoop().RunUntilIdle(); 493 494 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error); 495} 496 497TEST_F(JobSchedulerTest, AddNewDirectory) { 498 ConnectToWifi(); 499 500 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 501 scoped_ptr<google_apis::ResourceEntry> entry; 502 503 scheduler_->AddNewDirectory( 504 fake_drive_service_->GetRootResourceId(), // Root directory. 505 "New Directory", 506 DriveServiceInterface::AddNewDirectoryOptions(), 507 ClientContext(USER_INITIATED), 508 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 509 base::RunLoop().RunUntilIdle(); 510 511 ASSERT_EQ(google_apis::HTTP_CREATED, error); 512 ASSERT_TRUE(entry); 513} 514 515TEST_F(JobSchedulerTest, PriorityHandling) { 516 // Saturate the metadata job queue with uninteresting jobs to prevent 517 // following jobs from starting. 518 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR; 519 scoped_ptr<google_apis::ResourceEntry> entry_dontcare; 520 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) { 521 std::string resource_id("file:2_file_resource_id"); 522 scheduler_->GetResourceEntry( 523 resource_id, 524 ClientContext(USER_INITIATED), 525 google_apis::test_util::CreateCopyResultCallback(&error_dontcare, 526 &entry_dontcare)); 527 } 528 529 // Start jobs with different priorities. 530 std::string title_1("new file 1"); 531 std::string title_2("new file 2"); 532 std::string title_3("new file 3"); 533 std::string title_4("new file 4"); 534 std::vector<std::string> titles; 535 536 scheduler_->AddNewDirectory( 537 fake_drive_service_->GetRootResourceId(), 538 title_1, 539 DriveServiceInterface::AddNewDirectoryOptions(), 540 ClientContext(USER_INITIATED), 541 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles)); 542 scheduler_->AddNewDirectory( 543 fake_drive_service_->GetRootResourceId(), 544 title_2, 545 DriveServiceInterface::AddNewDirectoryOptions(), 546 ClientContext(BACKGROUND), 547 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles)); 548 scheduler_->AddNewDirectory( 549 fake_drive_service_->GetRootResourceId(), 550 title_3, 551 DriveServiceInterface::AddNewDirectoryOptions(), 552 ClientContext(BACKGROUND), 553 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles)); 554 scheduler_->AddNewDirectory( 555 fake_drive_service_->GetRootResourceId(), 556 title_4, 557 DriveServiceInterface::AddNewDirectoryOptions(), 558 ClientContext(USER_INITIATED), 559 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles)); 560 561 base::RunLoop().RunUntilIdle(); 562 563 ASSERT_EQ(4ul, titles.size()); 564 EXPECT_EQ(title_1, titles[0]); 565 EXPECT_EQ(title_4, titles[1]); 566 EXPECT_EQ(title_2, titles[2]); 567 EXPECT_EQ(title_3, titles[3]); 568} 569 570TEST_F(JobSchedulerTest, NoConnectionUserInitiated) { 571 ConnectToNone(); 572 573 std::string resource_id("file:2_file_resource_id"); 574 575 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 576 scoped_ptr<google_apis::ResourceEntry> entry; 577 scheduler_->GetResourceEntry( 578 resource_id, 579 ClientContext(USER_INITIATED), 580 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 581 base::RunLoop().RunUntilIdle(); 582 583 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error); 584} 585 586TEST_F(JobSchedulerTest, NoConnectionBackground) { 587 ConnectToNone(); 588 589 std::string resource_id("file:2_file_resource_id"); 590 591 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 592 scoped_ptr<google_apis::ResourceEntry> entry; 593 scheduler_->GetResourceEntry( 594 resource_id, 595 ClientContext(BACKGROUND), 596 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 597 base::RunLoop().RunUntilIdle(); 598 599 EXPECT_FALSE(entry); 600 601 // Reconnect to the net. 602 ConnectToWifi(); 603 604 base::RunLoop().RunUntilIdle(); 605 606 EXPECT_EQ(google_apis::HTTP_SUCCESS, error); 607 ASSERT_TRUE(entry); 608} 609 610TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) { 611 ConnectToCellular(); 612 613 // Disable fetching over cellular network. 614 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 615 616 // Try to get a file in the background 617 base::ScopedTempDir temp_dir; 618 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 619 620 const base::FilePath kOutputFilePath = 621 temp_dir.path().AppendASCII("whatever.txt"); 622 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 623 base::FilePath output_file_path; 624 scheduler_->DownloadFile( 625 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 626 kDummyDownloadFileSize, 627 kOutputFilePath, 628 "file:2_file_resource_id", 629 ClientContext(BACKGROUND), 630 google_apis::test_util::CreateCopyResultCallback( 631 &download_error, &output_file_path), 632 google_apis::GetContentCallback()); 633 // Metadata should still work 634 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 635 scoped_ptr<google_apis::AboutResource> about_resource; 636 637 // Try to get the metadata 638 scheduler_->GetAboutResource( 639 google_apis::test_util::CreateCopyResultCallback( 640 &metadata_error, &about_resource)); 641 base::RunLoop().RunUntilIdle(); 642 643 // Check the metadata 644 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 645 ASSERT_TRUE(about_resource); 646 647 // Check the download 648 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 649 650 // Switch to a Wifi connection 651 ConnectToWifi(); 652 653 base::RunLoop().RunUntilIdle(); 654 655 // Check the download again 656 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 657 std::string content; 658 EXPECT_EQ(output_file_path, kOutputFilePath); 659 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 660 EXPECT_EQ("This is some test content.", content); 661} 662 663TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) { 664 ConnectToWimax(); 665 666 // Disable fetching over cellular network. 667 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 668 669 // Try to get a file in the background 670 base::ScopedTempDir temp_dir; 671 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 672 673 const base::FilePath kOutputFilePath = 674 temp_dir.path().AppendASCII("whatever.txt"); 675 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 676 base::FilePath output_file_path; 677 scheduler_->DownloadFile( 678 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 679 kDummyDownloadFileSize, 680 kOutputFilePath, 681 "file:2_file_resource_id", 682 ClientContext(BACKGROUND), 683 google_apis::test_util::CreateCopyResultCallback( 684 &download_error, &output_file_path), 685 google_apis::GetContentCallback()); 686 // Metadata should still work 687 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 688 scoped_ptr<google_apis::AboutResource> about_resource; 689 690 // Try to get the metadata 691 scheduler_->GetAboutResource( 692 google_apis::test_util::CreateCopyResultCallback( 693 &metadata_error, &about_resource)); 694 base::RunLoop().RunUntilIdle(); 695 696 // Check the metadata 697 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 698 ASSERT_TRUE(about_resource); 699 700 // Check the download 701 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 702 703 // Switch to a Wifi connection 704 ConnectToWifi(); 705 706 base::RunLoop().RunUntilIdle(); 707 708 // Check the download again 709 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 710 std::string content; 711 EXPECT_EQ(output_file_path, kOutputFilePath); 712 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 713 EXPECT_EQ("This is some test content.", content); 714} 715 716TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) { 717 ConnectToCellular(); 718 719 // Enable fetching over cellular network. 720 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 721 722 // Try to get a file in the background 723 base::ScopedTempDir temp_dir; 724 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 725 726 const base::FilePath kOutputFilePath = 727 temp_dir.path().AppendASCII("whatever.txt"); 728 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 729 base::FilePath output_file_path; 730 scheduler_->DownloadFile( 731 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 732 kDummyDownloadFileSize, 733 kOutputFilePath, 734 "file:2_file_resource_id", 735 ClientContext(BACKGROUND), 736 google_apis::test_util::CreateCopyResultCallback( 737 &download_error, &output_file_path), 738 google_apis::GetContentCallback()); 739 // Metadata should still work 740 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 741 scoped_ptr<google_apis::AboutResource> about_resource; 742 743 // Try to get the metadata 744 scheduler_->GetAboutResource( 745 google_apis::test_util::CreateCopyResultCallback( 746 &metadata_error, &about_resource)); 747 base::RunLoop().RunUntilIdle(); 748 749 // Check the metadata 750 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 751 ASSERT_TRUE(about_resource); 752 753 // Check the download 754 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 755 std::string content; 756 EXPECT_EQ(output_file_path, kOutputFilePath); 757 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 758 EXPECT_EQ("This is some test content.", content); 759} 760 761TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) { 762 ConnectToWimax(); 763 764 // Enable fetching over cellular network. 765 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 766 767 // Try to get a file in the background 768 base::ScopedTempDir temp_dir; 769 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 770 771 const base::FilePath kOutputFilePath = 772 temp_dir.path().AppendASCII("whatever.txt"); 773 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 774 base::FilePath output_file_path; 775 scheduler_->DownloadFile( 776 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 777 kDummyDownloadFileSize, 778 kOutputFilePath, 779 "file:2_file_resource_id", 780 ClientContext(BACKGROUND), 781 google_apis::test_util::CreateCopyResultCallback( 782 &download_error, &output_file_path), 783 google_apis::GetContentCallback()); 784 // Metadata should still work 785 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 786 scoped_ptr<google_apis::AboutResource> about_resource; 787 788 // Try to get the metadata 789 scheduler_->GetAboutResource( 790 google_apis::test_util::CreateCopyResultCallback( 791 &metadata_error, &about_resource)); 792 base::RunLoop().RunUntilIdle(); 793 794 // Check the metadata 795 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 796 ASSERT_TRUE(about_resource); 797 798 // Check the download 799 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 800 std::string content; 801 EXPECT_EQ(output_file_path, kOutputFilePath); 802 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 803 EXPECT_EQ("This is some test content.", content); 804} 805 806TEST_F(JobSchedulerTest, JobInfo) { 807 JobListLogger logger; 808 scheduler_->AddObserver(&logger); 809 810 // Disable background upload/download. 811 ConnectToWimax(); 812 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 813 814 base::ScopedTempDir temp_dir; 815 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 816 817 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 818 scoped_ptr<google_apis::ResourceEntry> entry; 819 scoped_ptr<google_apis::AboutResource> about_resource; 820 base::FilePath path; 821 822 std::set<JobType> expected_types; 823 824 // Add many jobs. 825 expected_types.insert(TYPE_ADD_NEW_DIRECTORY); 826 scheduler_->AddNewDirectory( 827 fake_drive_service_->GetRootResourceId(), 828 "New Directory", 829 DriveServiceInterface::AddNewDirectoryOptions(), 830 ClientContext(USER_INITIATED), 831 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 832 expected_types.insert(TYPE_GET_ABOUT_RESOURCE); 833 scheduler_->GetAboutResource( 834 google_apis::test_util::CreateCopyResultCallback( 835 &error, &about_resource)); 836 expected_types.insert(TYPE_RENAME_RESOURCE); 837 scheduler_->RenameResource( 838 "file:2_file_resource_id", 839 "New Title", 840 google_apis::test_util::CreateCopyResultCallback(&error)); 841 expected_types.insert(TYPE_DOWNLOAD_FILE); 842 scheduler_->DownloadFile( 843 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 844 kDummyDownloadFileSize, 845 temp_dir.path().AppendASCII("whatever.txt"), 846 "file:2_file_resource_id", 847 ClientContext(BACKGROUND), 848 google_apis::test_util::CreateCopyResultCallback(&error, &path), 849 google_apis::GetContentCallback()); 850 851 // The number of jobs queued so far. 852 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size()); 853 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY)); 854 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE)); 855 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE)); 856 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE)); 857 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 858 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 859 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE)); 860 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 861 862 // Add more jobs. 863 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY); 864 scheduler_->AddResourceToDirectory( 865 "folder:1_folder_resource_id", 866 "file:2_file_resource_id", 867 google_apis::test_util::CreateCopyResultCallback(&error)); 868 expected_types.insert(TYPE_COPY_RESOURCE); 869 scheduler_->CopyResource( 870 "document:5_document_resource_id", 871 fake_drive_service_->GetRootResourceId(), 872 "New Document", 873 base::Time(), // last_modified 874 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 875 876 // 6 jobs in total were queued. 877 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList(); 878 EXPECT_EQ(6U, jobs.size()); 879 std::set<JobType> actual_types; 880 std::set<JobID> job_ids; 881 for (size_t i = 0; i < jobs.size(); ++i) { 882 actual_types.insert(jobs[i].job_type); 883 job_ids.insert(jobs[i].job_id); 884 } 885 EXPECT_EQ(expected_types, actual_types); 886 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique"; 887 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 888 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE)); 889 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 890 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE)); 891 892 // Run the jobs. 893 base::RunLoop().RunUntilIdle(); 894 895 // All jobs except the BACKGROUND job should have started running (UPDATED) 896 // and then finished (DONE). 897 jobs = scheduler_->GetJobInfoList(); 898 ASSERT_EQ(1U, jobs.size()); 899 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type); 900 901 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY)); 902 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE)); 903 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE)); 904 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, 905 TYPE_ADD_RESOURCE_TO_DIRECTORY)); 906 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE)); 907 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 908 909 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 910 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 911 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE)); 912 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 913 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE)); 914 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 915 916 // Run the background downloading job as well. 917 ConnectToWifi(); 918 base::RunLoop().RunUntilIdle(); 919 920 // All jobs should have finished. 921 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size()); 922 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 923 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 924} 925 926TEST_F(JobSchedulerTest, JobInfoProgress) { 927 JobListLogger logger; 928 scheduler_->AddObserver(&logger); 929 930 ConnectToWifi(); 931 932 base::ScopedTempDir temp_dir; 933 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 934 935 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 936 base::FilePath path; 937 938 // Download job. 939 scheduler_->DownloadFile( 940 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 941 kDummyDownloadFileSize, 942 temp_dir.path().AppendASCII("whatever.txt"), 943 "file:2_file_resource_id", 944 ClientContext(BACKGROUND), 945 google_apis::test_util::CreateCopyResultCallback(&error, &path), 946 google_apis::GetContentCallback()); 947 base::RunLoop().RunUntilIdle(); 948 949 std::vector<int64> download_progress; 950 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress); 951 ASSERT_TRUE(!download_progress.empty()); 952 EXPECT_TRUE(base::STLIsSorted(download_progress)); 953 EXPECT_GE(download_progress.front(), 0); 954 EXPECT_LE(download_progress.back(), 26); 955 956 // Upload job. 957 path = temp_dir.path().AppendASCII("new_file.txt"); 958 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello")); 959 google_apis::GDataErrorCode upload_error = 960 google_apis::GDATA_OTHER_ERROR; 961 scoped_ptr<google_apis::ResourceEntry> entry; 962 963 scheduler_->UploadNewFile( 964 fake_drive_service_->GetRootResourceId(), 965 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), 966 path, 967 "dummy title", 968 "plain/plain", 969 DriveUploader::UploadNewFileOptions(), 970 ClientContext(BACKGROUND), 971 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry)); 972 base::RunLoop().RunUntilIdle(); 973 974 std::vector<int64> upload_progress; 975 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress); 976 ASSERT_TRUE(!upload_progress.empty()); 977 EXPECT_TRUE(base::STLIsSorted(upload_progress)); 978 EXPECT_GE(upload_progress.front(), 0); 979 EXPECT_LE(upload_progress.back(), 13); 980} 981 982TEST_F(JobSchedulerTest, CancelPendingJob) { 983 base::ScopedTempDir temp_dir; 984 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 985 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); 986 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); 987 988 // To create a pending job for testing, set the mode to cellular connection 989 // and issue BACKGROUND jobs. 990 ConnectToCellular(); 991 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 992 993 // Start the first job and record its job ID. 994 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR; 995 scoped_ptr<google_apis::ResourceEntry> entry; 996 scheduler_->UploadNewFile( 997 fake_drive_service_->GetRootResourceId(), 998 base::FilePath::FromUTF8Unsafe("dummy/path"), 999 upload_path, 1000 "dummy title 1", 1001 "text/plain", 1002 DriveUploader::UploadNewFileOptions(), 1003 ClientContext(BACKGROUND), 1004 google_apis::test_util::CreateCopyResultCallback(&error1, &entry)); 1005 1006 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList(); 1007 ASSERT_EQ(1u, jobs.size()); 1008 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet. 1009 JobID first_job_id = jobs[0].job_id; 1010 1011 // Start the second job. 1012 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR; 1013 scheduler_->UploadNewFile( 1014 fake_drive_service_->GetRootResourceId(), 1015 base::FilePath::FromUTF8Unsafe("dummy/path"), 1016 upload_path, 1017 "dummy title 2", 1018 "text/plain", 1019 DriveUploader::UploadNewFileOptions(), 1020 ClientContext(BACKGROUND), 1021 google_apis::test_util::CreateCopyResultCallback(&error2, &entry)); 1022 1023 // Cancel the first one. 1024 scheduler_->CancelJob(first_job_id); 1025 1026 // Only the first job should be cancelled. 1027 ConnectToWifi(); 1028 base::RunLoop().RunUntilIdle(); 1029 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1); 1030 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2); 1031 EXPECT_TRUE(scheduler_->GetJobInfoList().empty()); 1032} 1033 1034TEST_F(JobSchedulerTest, CancelRunningJob) { 1035 ConnectToWifi(); 1036 1037 base::ScopedTempDir temp_dir; 1038 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1039 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); 1040 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); 1041 1042 // Run as a cancelable task. 1043 fake_drive_service_->set_upload_new_file_cancelable(true); 1044 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR; 1045 scoped_ptr<google_apis::ResourceEntry> entry; 1046 scheduler_->UploadNewFile( 1047 fake_drive_service_->GetRootResourceId(), 1048 base::FilePath::FromUTF8Unsafe("dummy/path"), 1049 upload_path, 1050 "dummy title 1", 1051 "text/plain", 1052 DriveUploader::UploadNewFileOptions(), 1053 ClientContext(USER_INITIATED), 1054 google_apis::test_util::CreateCopyResultCallback(&error1, &entry)); 1055 1056 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList(); 1057 ASSERT_EQ(1u, jobs.size()); 1058 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running. 1059 JobID first_job_id = jobs[0].job_id; 1060 1061 // Start the second job normally. 1062 fake_drive_service_->set_upload_new_file_cancelable(false); 1063 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR; 1064 scheduler_->UploadNewFile( 1065 fake_drive_service_->GetRootResourceId(), 1066 base::FilePath::FromUTF8Unsafe("dummy/path"), 1067 upload_path, 1068 "dummy title 2", 1069 "text/plain", 1070 DriveUploader::UploadNewFileOptions(), 1071 ClientContext(USER_INITIATED), 1072 google_apis::test_util::CreateCopyResultCallback(&error2, &entry)); 1073 1074 // Cancel the first one. 1075 scheduler_->CancelJob(first_job_id); 1076 1077 // Only the first job should be cancelled. 1078 base::RunLoop().RunUntilIdle(); 1079 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1); 1080 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2); 1081 EXPECT_TRUE(scheduler_->GetJobInfoList().empty()); 1082} 1083 1084} // namespace drive 1085