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