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/files/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 "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 "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 "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 "2_file_resource_id", // resource ID 410 "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 "2_file_resource_id", // resource ID 428 "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, AddResourceToDirectory) { 441 ConnectToWifi(); 442 443 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 444 445 scheduler_->AddResourceToDirectory( 446 "1_folder_resource_id", 447 "2_file_resource_id", 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, RemoveResourceFromDirectory) { 455 ConnectToWifi(); 456 457 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 458 459 scheduler_->RemoveResourceFromDirectory( 460 "1_folder_resource_id", 461 "subdirectory_file_1_id", // resource ID 462 ClientContext(USER_INITIATED), 463 google_apis::test_util::CreateCopyResultCallback(&error)); 464 base::RunLoop().RunUntilIdle(); 465 466 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error); 467} 468 469TEST_F(JobSchedulerTest, AddNewDirectory) { 470 ConnectToWifi(); 471 472 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 473 scoped_ptr<google_apis::FileResource> entry; 474 475 scheduler_->AddNewDirectory( 476 fake_drive_service_->GetRootResourceId(), // Root directory. 477 "New Directory", 478 DriveServiceInterface::AddNewDirectoryOptions(), 479 ClientContext(USER_INITIATED), 480 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 481 base::RunLoop().RunUntilIdle(); 482 483 ASSERT_EQ(google_apis::HTTP_CREATED, error); 484 ASSERT_TRUE(entry); 485} 486 487TEST_F(JobSchedulerTest, PriorityHandling) { 488 // Saturate the metadata job queue with uninteresting jobs to prevent 489 // following jobs from starting. 490 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR; 491 scoped_ptr<google_apis::FileResource> entry_dontcare; 492 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) { 493 std::string resource_id("2_file_resource_id"); 494 scheduler_->GetFileResource( 495 resource_id, 496 ClientContext(USER_INITIATED), 497 google_apis::test_util::CreateCopyResultCallback(&error_dontcare, 498 &entry_dontcare)); 499 } 500 501 // Start jobs with different priorities. 502 std::string title_1("new file 1"); 503 std::string title_2("new file 2"); 504 std::string title_3("new file 3"); 505 std::string title_4("new file 4"); 506 std::vector<std::string> titles; 507 508 scheduler_->AddNewDirectory( 509 fake_drive_service_->GetRootResourceId(), 510 title_1, 511 DriveServiceInterface::AddNewDirectoryOptions(), 512 ClientContext(USER_INITIATED), 513 base::Bind(&CopyTitleFromFileResourceCallback, &titles)); 514 scheduler_->AddNewDirectory( 515 fake_drive_service_->GetRootResourceId(), 516 title_2, 517 DriveServiceInterface::AddNewDirectoryOptions(), 518 ClientContext(BACKGROUND), 519 base::Bind(&CopyTitleFromFileResourceCallback, &titles)); 520 scheduler_->AddNewDirectory( 521 fake_drive_service_->GetRootResourceId(), 522 title_3, 523 DriveServiceInterface::AddNewDirectoryOptions(), 524 ClientContext(BACKGROUND), 525 base::Bind(&CopyTitleFromFileResourceCallback, &titles)); 526 scheduler_->AddNewDirectory( 527 fake_drive_service_->GetRootResourceId(), 528 title_4, 529 DriveServiceInterface::AddNewDirectoryOptions(), 530 ClientContext(USER_INITIATED), 531 base::Bind(&CopyTitleFromFileResourceCallback, &titles)); 532 533 base::RunLoop().RunUntilIdle(); 534 535 ASSERT_EQ(4ul, titles.size()); 536 EXPECT_EQ(title_1, titles[0]); 537 EXPECT_EQ(title_4, titles[1]); 538 EXPECT_EQ(title_2, titles[2]); 539 EXPECT_EQ(title_3, titles[3]); 540} 541 542TEST_F(JobSchedulerTest, NoConnectionUserInitiated) { 543 ConnectToNone(); 544 545 std::string resource_id("2_file_resource_id"); 546 547 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 548 scoped_ptr<google_apis::FileResource> entry; 549 scheduler_->GetFileResource( 550 resource_id, 551 ClientContext(USER_INITIATED), 552 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 553 base::RunLoop().RunUntilIdle(); 554 555 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error); 556} 557 558TEST_F(JobSchedulerTest, NoConnectionBackground) { 559 ConnectToNone(); 560 561 std::string resource_id("2_file_resource_id"); 562 563 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 564 scoped_ptr<google_apis::FileResource> entry; 565 scheduler_->GetFileResource( 566 resource_id, 567 ClientContext(BACKGROUND), 568 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 569 base::RunLoop().RunUntilIdle(); 570 571 EXPECT_FALSE(entry); 572 573 // Reconnect to the net. 574 ConnectToWifi(); 575 576 base::RunLoop().RunUntilIdle(); 577 578 EXPECT_EQ(google_apis::HTTP_SUCCESS, error); 579 ASSERT_TRUE(entry); 580} 581 582TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) { 583 ConnectToCellular(); 584 585 // Disable fetching over cellular network. 586 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 587 588 // Try to get a file in the background 589 base::ScopedTempDir temp_dir; 590 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 591 592 const base::FilePath kOutputFilePath = 593 temp_dir.path().AppendASCII("whatever.txt"); 594 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 595 base::FilePath output_file_path; 596 scheduler_->DownloadFile( 597 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 598 kDummyDownloadFileSize, 599 kOutputFilePath, 600 "2_file_resource_id", 601 ClientContext(BACKGROUND), 602 google_apis::test_util::CreateCopyResultCallback( 603 &download_error, &output_file_path), 604 google_apis::GetContentCallback()); 605 // Metadata should still work 606 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 607 scoped_ptr<google_apis::AboutResource> about_resource; 608 609 // Try to get the metadata 610 scheduler_->GetAboutResource( 611 google_apis::test_util::CreateCopyResultCallback( 612 &metadata_error, &about_resource)); 613 base::RunLoop().RunUntilIdle(); 614 615 // Check the metadata 616 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 617 ASSERT_TRUE(about_resource); 618 619 // Check the download 620 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 621 622 // Switch to a Wifi connection 623 ConnectToWifi(); 624 625 base::RunLoop().RunUntilIdle(); 626 627 // Check the download again 628 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 629 std::string content; 630 EXPECT_EQ(output_file_path, kOutputFilePath); 631 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 632 EXPECT_EQ("This is some test content.", content); 633} 634 635TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) { 636 ConnectToWimax(); 637 638 // Disable fetching over cellular network. 639 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 640 641 // Try to get a file in the background 642 base::ScopedTempDir temp_dir; 643 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 644 645 const base::FilePath kOutputFilePath = 646 temp_dir.path().AppendASCII("whatever.txt"); 647 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 648 base::FilePath output_file_path; 649 scheduler_->DownloadFile( 650 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 651 kDummyDownloadFileSize, 652 kOutputFilePath, 653 "2_file_resource_id", 654 ClientContext(BACKGROUND), 655 google_apis::test_util::CreateCopyResultCallback( 656 &download_error, &output_file_path), 657 google_apis::GetContentCallback()); 658 // Metadata should still work 659 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 660 scoped_ptr<google_apis::AboutResource> about_resource; 661 662 // Try to get the metadata 663 scheduler_->GetAboutResource( 664 google_apis::test_util::CreateCopyResultCallback( 665 &metadata_error, &about_resource)); 666 base::RunLoop().RunUntilIdle(); 667 668 // Check the metadata 669 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 670 ASSERT_TRUE(about_resource); 671 672 // Check the download 673 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 674 675 // Switch to a Wifi connection 676 ConnectToWifi(); 677 678 base::RunLoop().RunUntilIdle(); 679 680 // Check the download again 681 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 682 std::string content; 683 EXPECT_EQ(output_file_path, kOutputFilePath); 684 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 685 EXPECT_EQ("This is some test content.", content); 686} 687 688TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) { 689 ConnectToCellular(); 690 691 // Enable fetching over cellular network. 692 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 693 694 // Try to get a file in the background 695 base::ScopedTempDir temp_dir; 696 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 697 698 const base::FilePath kOutputFilePath = 699 temp_dir.path().AppendASCII("whatever.txt"); 700 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 701 base::FilePath output_file_path; 702 scheduler_->DownloadFile( 703 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 704 kDummyDownloadFileSize, 705 kOutputFilePath, 706 "2_file_resource_id", 707 ClientContext(BACKGROUND), 708 google_apis::test_util::CreateCopyResultCallback( 709 &download_error, &output_file_path), 710 google_apis::GetContentCallback()); 711 // Metadata should still work 712 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 713 scoped_ptr<google_apis::AboutResource> about_resource; 714 715 // Try to get the metadata 716 scheduler_->GetAboutResource( 717 google_apis::test_util::CreateCopyResultCallback( 718 &metadata_error, &about_resource)); 719 base::RunLoop().RunUntilIdle(); 720 721 // Check the metadata 722 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 723 ASSERT_TRUE(about_resource); 724 725 // Check the download 726 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 727 std::string content; 728 EXPECT_EQ(output_file_path, kOutputFilePath); 729 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 730 EXPECT_EQ("This is some test content.", content); 731} 732 733TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) { 734 ConnectToWimax(); 735 736 // Enable fetching over cellular network. 737 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 738 739 // Try to get a file in the background 740 base::ScopedTempDir temp_dir; 741 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 742 743 const base::FilePath kOutputFilePath = 744 temp_dir.path().AppendASCII("whatever.txt"); 745 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 746 base::FilePath output_file_path; 747 scheduler_->DownloadFile( 748 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 749 kDummyDownloadFileSize, 750 kOutputFilePath, 751 "2_file_resource_id", 752 ClientContext(BACKGROUND), 753 google_apis::test_util::CreateCopyResultCallback( 754 &download_error, &output_file_path), 755 google_apis::GetContentCallback()); 756 // Metadata should still work 757 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 758 scoped_ptr<google_apis::AboutResource> about_resource; 759 760 // Try to get the metadata 761 scheduler_->GetAboutResource( 762 google_apis::test_util::CreateCopyResultCallback( 763 &metadata_error, &about_resource)); 764 base::RunLoop().RunUntilIdle(); 765 766 // Check the metadata 767 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 768 ASSERT_TRUE(about_resource); 769 770 // Check the download 771 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 772 std::string content; 773 EXPECT_EQ(output_file_path, kOutputFilePath); 774 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content)); 775 EXPECT_EQ("This is some test content.", content); 776} 777 778TEST_F(JobSchedulerTest, JobInfo) { 779 JobListLogger logger; 780 scheduler_->AddObserver(&logger); 781 782 // Disable background upload/download. 783 ConnectToWimax(); 784 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 785 786 base::ScopedTempDir temp_dir; 787 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 788 789 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 790 scoped_ptr<google_apis::FileResource> entry; 791 scoped_ptr<google_apis::AboutResource> about_resource; 792 base::FilePath path; 793 794 std::set<JobType> expected_types; 795 796 // Add many jobs. 797 expected_types.insert(TYPE_ADD_NEW_DIRECTORY); 798 scheduler_->AddNewDirectory( 799 fake_drive_service_->GetRootResourceId(), 800 "New Directory", 801 DriveServiceInterface::AddNewDirectoryOptions(), 802 ClientContext(USER_INITIATED), 803 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 804 expected_types.insert(TYPE_GET_ABOUT_RESOURCE); 805 scheduler_->GetAboutResource( 806 google_apis::test_util::CreateCopyResultCallback( 807 &error, &about_resource)); 808 expected_types.insert(TYPE_UPDATE_RESOURCE); 809 scheduler_->UpdateResource( 810 "2_file_resource_id", 811 std::string(), 812 "New Title", 813 base::Time(), 814 base::Time(), 815 ClientContext(USER_INITIATED), 816 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 817 expected_types.insert(TYPE_DOWNLOAD_FILE); 818 scheduler_->DownloadFile( 819 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 820 kDummyDownloadFileSize, 821 temp_dir.path().AppendASCII("whatever.txt"), 822 "2_file_resource_id", 823 ClientContext(BACKGROUND), 824 google_apis::test_util::CreateCopyResultCallback(&error, &path), 825 google_apis::GetContentCallback()); 826 827 // The number of jobs queued so far. 828 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size()); 829 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY)); 830 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE)); 831 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_UPDATE_RESOURCE)); 832 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE)); 833 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 834 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 835 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE)); 836 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 837 838 // Add more jobs. 839 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY); 840 scheduler_->AddResourceToDirectory( 841 "1_folder_resource_id", 842 "2_file_resource_id", 843 google_apis::test_util::CreateCopyResultCallback(&error)); 844 expected_types.insert(TYPE_COPY_RESOURCE); 845 scheduler_->CopyResource( 846 "5_document_resource_id", 847 fake_drive_service_->GetRootResourceId(), 848 "New Document", 849 base::Time(), // last_modified 850 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 851 852 // 6 jobs in total were queued. 853 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList(); 854 EXPECT_EQ(6U, jobs.size()); 855 std::set<JobType> actual_types; 856 std::set<JobID> job_ids; 857 for (size_t i = 0; i < jobs.size(); ++i) { 858 actual_types.insert(jobs[i].job_type); 859 job_ids.insert(jobs[i].job_id); 860 } 861 EXPECT_EQ(expected_types, actual_types); 862 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique"; 863 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 864 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE)); 865 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 866 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE)); 867 868 // Run the jobs. 869 base::RunLoop().RunUntilIdle(); 870 871 // All jobs except the BACKGROUND job should have started running (UPDATED) 872 // and then finished (DONE). 873 jobs = scheduler_->GetJobInfoList(); 874 ASSERT_EQ(1U, jobs.size()); 875 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type); 876 877 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY)); 878 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE)); 879 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_UPDATE_RESOURCE)); 880 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, 881 TYPE_ADD_RESOURCE_TO_DIRECTORY)); 882 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE)); 883 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 884 885 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 886 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 887 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE)); 888 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 889 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE)); 890 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 891 892 // Run the background downloading job as well. 893 ConnectToWifi(); 894 base::RunLoop().RunUntilIdle(); 895 896 // All jobs should have finished. 897 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size()); 898 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 899 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 900} 901 902TEST_F(JobSchedulerTest, JobInfoProgress) { 903 JobListLogger logger; 904 scheduler_->AddObserver(&logger); 905 906 ConnectToWifi(); 907 908 base::ScopedTempDir temp_dir; 909 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 910 911 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 912 base::FilePath path; 913 914 // Download job. 915 scheduler_->DownloadFile( 916 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 917 kDummyDownloadFileSize, 918 temp_dir.path().AppendASCII("whatever.txt"), 919 "2_file_resource_id", 920 ClientContext(BACKGROUND), 921 google_apis::test_util::CreateCopyResultCallback(&error, &path), 922 google_apis::GetContentCallback()); 923 base::RunLoop().RunUntilIdle(); 924 925 std::vector<int64> download_progress; 926 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress); 927 ASSERT_TRUE(!download_progress.empty()); 928 EXPECT_TRUE(base::STLIsSorted(download_progress)); 929 EXPECT_GE(download_progress.front(), 0); 930 EXPECT_LE(download_progress.back(), 26); 931 932 // Upload job. 933 path = temp_dir.path().AppendASCII("new_file.txt"); 934 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello")); 935 google_apis::GDataErrorCode upload_error = 936 google_apis::GDATA_OTHER_ERROR; 937 scoped_ptr<google_apis::FileResource> entry; 938 939 scheduler_->UploadNewFile( 940 fake_drive_service_->GetRootResourceId(), 941 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), 942 path, 943 "dummy title", 944 "plain/plain", 945 DriveUploader::UploadNewFileOptions(), 946 ClientContext(BACKGROUND), 947 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry)); 948 base::RunLoop().RunUntilIdle(); 949 950 std::vector<int64> upload_progress; 951 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress); 952 ASSERT_TRUE(!upload_progress.empty()); 953 EXPECT_TRUE(base::STLIsSorted(upload_progress)); 954 EXPECT_GE(upload_progress.front(), 0); 955 EXPECT_LE(upload_progress.back(), 13); 956} 957 958TEST_F(JobSchedulerTest, CancelPendingJob) { 959 base::ScopedTempDir temp_dir; 960 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 961 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); 962 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); 963 964 // To create a pending job for testing, set the mode to cellular connection 965 // and issue BACKGROUND jobs. 966 ConnectToCellular(); 967 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 968 969 // Start the first job and record its job ID. 970 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR; 971 scoped_ptr<google_apis::FileResource> entry; 972 scheduler_->UploadNewFile( 973 fake_drive_service_->GetRootResourceId(), 974 base::FilePath::FromUTF8Unsafe("dummy/path"), 975 upload_path, 976 "dummy title 1", 977 "text/plain", 978 DriveUploader::UploadNewFileOptions(), 979 ClientContext(BACKGROUND), 980 google_apis::test_util::CreateCopyResultCallback(&error1, &entry)); 981 982 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList(); 983 ASSERT_EQ(1u, jobs.size()); 984 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet. 985 JobID first_job_id = jobs[0].job_id; 986 987 // Start the second job. 988 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR; 989 scheduler_->UploadNewFile( 990 fake_drive_service_->GetRootResourceId(), 991 base::FilePath::FromUTF8Unsafe("dummy/path"), 992 upload_path, 993 "dummy title 2", 994 "text/plain", 995 DriveUploader::UploadNewFileOptions(), 996 ClientContext(BACKGROUND), 997 google_apis::test_util::CreateCopyResultCallback(&error2, &entry)); 998 999 // Cancel the first one. 1000 scheduler_->CancelJob(first_job_id); 1001 1002 // Only the first job should be cancelled. 1003 ConnectToWifi(); 1004 base::RunLoop().RunUntilIdle(); 1005 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1); 1006 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2); 1007 EXPECT_TRUE(scheduler_->GetJobInfoList().empty()); 1008} 1009 1010TEST_F(JobSchedulerTest, CancelRunningJob) { 1011 ConnectToWifi(); 1012 1013 base::ScopedTempDir temp_dir; 1014 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1015 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); 1016 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); 1017 1018 // Run as a cancelable task. 1019 fake_drive_service_->set_upload_new_file_cancelable(true); 1020 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR; 1021 scoped_ptr<google_apis::FileResource> entry; 1022 scheduler_->UploadNewFile( 1023 fake_drive_service_->GetRootResourceId(), 1024 base::FilePath::FromUTF8Unsafe("dummy/path"), 1025 upload_path, 1026 "dummy title 1", 1027 "text/plain", 1028 DriveUploader::UploadNewFileOptions(), 1029 ClientContext(USER_INITIATED), 1030 google_apis::test_util::CreateCopyResultCallback(&error1, &entry)); 1031 1032 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList(); 1033 ASSERT_EQ(1u, jobs.size()); 1034 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running. 1035 JobID first_job_id = jobs[0].job_id; 1036 1037 // Start the second job normally. 1038 fake_drive_service_->set_upload_new_file_cancelable(false); 1039 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR; 1040 scheduler_->UploadNewFile( 1041 fake_drive_service_->GetRootResourceId(), 1042 base::FilePath::FromUTF8Unsafe("dummy/path"), 1043 upload_path, 1044 "dummy title 2", 1045 "text/plain", 1046 DriveUploader::UploadNewFileOptions(), 1047 ClientContext(USER_INITIATED), 1048 google_apis::test_util::CreateCopyResultCallback(&error2, &entry)); 1049 1050 // Cancel the first one. 1051 scheduler_->CancelJob(first_job_id); 1052 1053 // Only the first job should be cancelled. 1054 base::RunLoop().RunUntilIdle(); 1055 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1); 1056 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2); 1057 EXPECT_TRUE(scheduler_->GetJobInfoList().empty()); 1058} 1059 1060} // namespace drive 1061