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 "chrome/browser/chromeos/drive/test_util.h" 16 #include "chrome/browser/drive/fake_drive_service.h" 17 #include "chrome/browser/google_apis/drive_api_parser.h" 18 #include "chrome/browser/google_apis/gdata_wapi_parser.h" 19 #include "chrome/browser/google_apis/test_util.h" 20 #include "chrome/common/pref_names.h" 21 #include "content/public/test/test_browser_thread_bundle.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 namespace drive { 25 26 namespace { 27 28 void CopyResourceIdFromGetResourceEntryCallback( 29 std::vector<std::string>* id_list_out, 30 const std::string& requested_id, 31 google_apis::GDataErrorCode error_in, 32 scoped_ptr<google_apis::ResourceEntry> resource_entry_in) { 33 id_list_out->push_back(requested_id); 34 } 35 36 class JobListLogger : public JobListObserver { 37 public: 38 enum EventType { 39 ADDED, 40 UPDATED, 41 DONE, 42 }; 43 44 struct EventLog { 45 EventType type; 46 JobInfo info; 47 48 EventLog(EventType type, const JobInfo& info) : type(type), info(info) { 49 } 50 }; 51 52 // Checks whether the specified type of event has occurred. 53 bool Has(EventType type, JobType job_type) { 54 for (size_t i = 0; i < events.size(); ++i) { 55 if (events[i].type == type && events[i].info.job_type == job_type) 56 return true; 57 } 58 return false; 59 } 60 61 // Gets the progress event information of the specified type. 62 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) { 63 for (size_t i = 0; i < events.size(); ++i) { 64 if (events[i].type == UPDATED && events[i].info.job_type == job_type) 65 progress->push_back(events[i].info.num_completed_bytes); 66 } 67 } 68 69 // JobListObserver overrides. 70 virtual void OnJobAdded(const JobInfo& info) OVERRIDE { 71 events.push_back(EventLog(ADDED, info)); 72 } 73 74 virtual void OnJobUpdated(const JobInfo& info) OVERRIDE { 75 events.push_back(EventLog(UPDATED, info)); 76 } 77 78 virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE { 79 events.push_back(EventLog(DONE, info)); 80 } 81 82 private: 83 std::vector<EventLog> events; 84 }; 85 86 } // namespace 87 88 class JobSchedulerTest : public testing::Test { 89 public: 90 JobSchedulerTest() 91 : pref_service_(new TestingPrefServiceSimple) { 92 test_util::RegisterDrivePrefs(pref_service_->registry()); 93 } 94 95 virtual void SetUp() OVERRIDE { 96 fake_network_change_notifier_.reset( 97 new test_util::FakeNetworkChangeNotifier); 98 99 fake_drive_service_.reset(new FakeDriveService()); 100 fake_drive_service_->LoadResourceListForWapi( 101 "gdata/root_feed.json"); 102 fake_drive_service_->LoadAccountMetadataForWapi( 103 "gdata/account_metadata.json"); 104 fake_drive_service_->LoadAppListForDriveApi( 105 "drive/applist.json"); 106 107 scheduler_.reset(new JobScheduler(pref_service_.get(), 108 fake_drive_service_.get(), 109 base::MessageLoopProxy::current().get())); 110 scheduler_->SetDisableThrottling(true); 111 } 112 113 protected: 114 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with 115 // the specified connection type. 116 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) { 117 fake_network_change_notifier_->SetConnectionType(type); 118 } 119 120 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network. 121 void ConnectToWifi() { 122 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); 123 } 124 125 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network. 126 void ConnectToCellular() { 127 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G); 128 } 129 130 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network. 131 void ConnectToWimax() { 132 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G); 133 } 134 135 // Sets up FakeNetworkChangeNotifier as if it's disconnected. 136 void ConnectToNone() { 137 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE); 138 } 139 140 static int GetMetadataQueueMaxJobCount() { 141 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE]; 142 } 143 144 content::TestBrowserThreadBundle thread_bundle_; 145 scoped_ptr<TestingPrefServiceSimple> pref_service_; 146 scoped_ptr<test_util::FakeNetworkChangeNotifier> 147 fake_network_change_notifier_; 148 scoped_ptr<FakeDriveService> fake_drive_service_; 149 scoped_ptr<JobScheduler> scheduler_; 150 }; 151 152 TEST_F(JobSchedulerTest, GetAboutResource) { 153 ConnectToWifi(); 154 155 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 156 scoped_ptr<google_apis::AboutResource> about_resource; 157 scheduler_->GetAboutResource( 158 google_apis::test_util::CreateCopyResultCallback( 159 &error, &about_resource)); 160 base::RunLoop().RunUntilIdle(); 161 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 162 ASSERT_TRUE(about_resource); 163 } 164 165 TEST_F(JobSchedulerTest, GetAppList) { 166 ConnectToWifi(); 167 168 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 169 scoped_ptr<google_apis::AppList> app_list; 170 171 scheduler_->GetAppList( 172 google_apis::test_util::CreateCopyResultCallback(&error, &app_list)); 173 base::RunLoop().RunUntilIdle(); 174 175 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 176 ASSERT_TRUE(app_list); 177 } 178 179 TEST_F(JobSchedulerTest, GetAllResourceList) { 180 ConnectToWifi(); 181 182 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 183 scoped_ptr<google_apis::ResourceList> resource_list; 184 185 scheduler_->GetAllResourceList( 186 google_apis::test_util::CreateCopyResultCallback( 187 &error, &resource_list)); 188 base::RunLoop().RunUntilIdle(); 189 190 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 191 ASSERT_TRUE(resource_list); 192 } 193 194 TEST_F(JobSchedulerTest, GetResourceListInDirectory) { 195 ConnectToWifi(); 196 197 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 198 scoped_ptr<google_apis::ResourceList> resource_list; 199 200 scheduler_->GetResourceListInDirectory( 201 fake_drive_service_->GetRootResourceId(), 202 google_apis::test_util::CreateCopyResultCallback( 203 &error, &resource_list)); 204 base::RunLoop().RunUntilIdle(); 205 206 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 207 ASSERT_TRUE(resource_list); 208 } 209 210 TEST_F(JobSchedulerTest, Search) { 211 ConnectToWifi(); 212 213 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 214 scoped_ptr<google_apis::ResourceList> resource_list; 215 216 scheduler_->Search( 217 "File", // search query 218 google_apis::test_util::CreateCopyResultCallback( 219 &error, &resource_list)); 220 base::RunLoop().RunUntilIdle(); 221 222 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 223 ASSERT_TRUE(resource_list); 224 } 225 226 TEST_F(JobSchedulerTest, GetChangeList) { 227 ConnectToWifi(); 228 229 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 230 231 // Create a new directory. 232 // The loaded (initial) changestamp is 654321. Thus, by this operation, 233 // it should become 654322. 234 { 235 scoped_ptr<google_apis::ResourceEntry> resource_entry; 236 fake_drive_service_->AddNewDirectory( 237 fake_drive_service_->GetRootResourceId(), 238 "new directory", 239 google_apis::test_util::CreateCopyResultCallback( 240 &error, &resource_entry)); 241 base::RunLoop().RunUntilIdle(); 242 ASSERT_EQ(google_apis::HTTP_CREATED, error); 243 } 244 245 error = google_apis::GDATA_OTHER_ERROR; 246 scoped_ptr<google_apis::ResourceList> resource_list; 247 scheduler_->GetChangeList( 248 654321 + 1, // start_changestamp 249 google_apis::test_util::CreateCopyResultCallback( 250 &error, &resource_list)); 251 base::RunLoop().RunUntilIdle(); 252 253 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 254 ASSERT_TRUE(resource_list); 255 } 256 257 TEST_F(JobSchedulerTest, ContinueGetResourceList) { 258 ConnectToWifi(); 259 fake_drive_service_->set_default_max_results(2); 260 261 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 262 scoped_ptr<google_apis::ResourceList> resource_list; 263 264 scheduler_->GetAllResourceList( 265 google_apis::test_util::CreateCopyResultCallback( 266 &error, &resource_list)); 267 base::RunLoop().RunUntilIdle(); 268 269 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 270 ASSERT_TRUE(resource_list); 271 272 const google_apis::Link* next_link = 273 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT); 274 ASSERT_TRUE(next_link); 275 // Keep the next url before releasing the |resource_list|. 276 GURL next_url(next_link->href()); 277 278 error = google_apis::GDATA_OTHER_ERROR; 279 resource_list.reset(); 280 281 scheduler_->ContinueGetResourceList( 282 next_url, 283 google_apis::test_util::CreateCopyResultCallback( 284 &error, &resource_list)); 285 base::RunLoop().RunUntilIdle(); 286 287 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 288 ASSERT_TRUE(resource_list); 289 } 290 291 TEST_F(JobSchedulerTest, GetResourceEntry) { 292 ConnectToWifi(); 293 294 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 295 scoped_ptr<google_apis::ResourceEntry> entry; 296 297 scheduler_->GetResourceEntry( 298 "file:2_file_resource_id", // resource ID 299 ClientContext(USER_INITIATED), 300 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 301 base::RunLoop().RunUntilIdle(); 302 303 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 304 ASSERT_TRUE(entry); 305 } 306 307 TEST_F(JobSchedulerTest, GetShareUrl) { 308 ConnectToWifi(); 309 310 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 311 GURL share_url; 312 313 scheduler_->GetShareUrl( 314 "file:2_file_resource_id", // resource ID 315 GURL("chrome-extension://test-id/"), // embed origin 316 ClientContext(USER_INITIATED), 317 google_apis::test_util::CreateCopyResultCallback(&error, &share_url)); 318 base::RunLoop().RunUntilIdle(); 319 320 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 321 ASSERT_FALSE(share_url.is_empty()); 322 } 323 324 TEST_F(JobSchedulerTest, DeleteResource) { 325 ConnectToWifi(); 326 327 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 328 329 scheduler_->DeleteResource( 330 "file:2_file_resource_id", 331 google_apis::test_util::CreateCopyResultCallback(&error)); 332 base::RunLoop().RunUntilIdle(); 333 334 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 335 } 336 337 TEST_F(JobSchedulerTest, CopyResource) { 338 ConnectToWifi(); 339 340 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 341 scoped_ptr<google_apis::ResourceEntry> entry; 342 343 scheduler_->CopyResource( 344 "file:2_file_resource_id", // resource ID 345 "folder:1_folder_resource_id", // parent resource ID 346 "New Document", // new title 347 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 348 base::RunLoop().RunUntilIdle(); 349 350 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 351 ASSERT_TRUE(entry); 352 } 353 354 TEST_F(JobSchedulerTest, CopyHostedDocument) { 355 ConnectToWifi(); 356 357 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 358 scoped_ptr<google_apis::ResourceEntry> entry; 359 360 scheduler_->CopyHostedDocument( 361 "document:5_document_resource_id", // resource ID 362 "New Document", // new title 363 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 364 base::RunLoop().RunUntilIdle(); 365 366 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 367 ASSERT_TRUE(entry); 368 } 369 370 TEST_F(JobSchedulerTest, RenameResource) { 371 ConnectToWifi(); 372 373 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 374 375 scheduler_->RenameResource( 376 "file:2_file_resource_id", 377 "New Title", 378 google_apis::test_util::CreateCopyResultCallback(&error)); 379 base::RunLoop().RunUntilIdle(); 380 381 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 382 } 383 384 TEST_F(JobSchedulerTest, AddResourceToDirectory) { 385 ConnectToWifi(); 386 387 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 388 389 scheduler_->AddResourceToDirectory( 390 "folder:1_folder_resource_id", 391 "file:2_file_resource_id", 392 google_apis::test_util::CreateCopyResultCallback(&error)); 393 base::RunLoop().RunUntilIdle(); 394 395 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 396 } 397 398 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) { 399 ConnectToWifi(); 400 401 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 402 403 scheduler_->RemoveResourceFromDirectory( 404 "folder:1_folder_resource_id", 405 "file:subdirectory_file_1_id", // resource ID 406 google_apis::test_util::CreateCopyResultCallback(&error)); 407 base::RunLoop().RunUntilIdle(); 408 409 ASSERT_EQ(google_apis::HTTP_SUCCESS, error); 410 } 411 412 TEST_F(JobSchedulerTest, AddNewDirectory) { 413 ConnectToWifi(); 414 415 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 416 scoped_ptr<google_apis::ResourceEntry> entry; 417 418 scheduler_->AddNewDirectory( 419 fake_drive_service_->GetRootResourceId(), // Root directory. 420 "New Directory", 421 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 422 base::RunLoop().RunUntilIdle(); 423 424 ASSERT_EQ(google_apis::HTTP_CREATED, error); 425 ASSERT_TRUE(entry); 426 } 427 428 TEST_F(JobSchedulerTest, GetResourceEntryPriority) { 429 // Saturate the metadata job queue with uninteresting jobs to prevent 430 // following jobs from starting. 431 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR; 432 scoped_ptr<google_apis::ResourceEntry> entry_dontcare; 433 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) { 434 scheduler_->GetResourceEntry( 435 "uninteresting_resource_id", 436 ClientContext(USER_INITIATED), 437 google_apis::test_util::CreateCopyResultCallback(&error_dontcare, 438 &entry_dontcare)); 439 } 440 441 // Start jobs with different priorities. 442 std::string resource_1("file:1_file_resource_id"); 443 std::string resource_2("file:2_file_resource_id"); 444 std::string resource_3("file:3_file_resource_id"); 445 std::string resource_4("file:4_file_resource_id"); 446 std::vector<std::string> resource_ids; 447 448 scheduler_->GetResourceEntry( 449 resource_1, // resource ID 450 ClientContext(USER_INITIATED), 451 base::Bind(&CopyResourceIdFromGetResourceEntryCallback, 452 &resource_ids, 453 resource_1)); 454 scheduler_->GetResourceEntry( 455 resource_2, // resource ID 456 ClientContext(BACKGROUND), 457 base::Bind(&CopyResourceIdFromGetResourceEntryCallback, 458 &resource_ids, 459 resource_2)); 460 scheduler_->GetResourceEntry( 461 resource_3, // resource ID 462 ClientContext(BACKGROUND), 463 base::Bind(&CopyResourceIdFromGetResourceEntryCallback, 464 &resource_ids, 465 resource_3)); 466 scheduler_->GetResourceEntry( 467 resource_4, // resource ID 468 ClientContext(USER_INITIATED), 469 base::Bind(&CopyResourceIdFromGetResourceEntryCallback, 470 &resource_ids, 471 resource_4)); 472 473 base::RunLoop().RunUntilIdle(); 474 475 ASSERT_EQ(resource_ids.size(), 4ul); 476 EXPECT_EQ(resource_ids[0], resource_1); 477 EXPECT_EQ(resource_ids[1], resource_4); 478 EXPECT_EQ(resource_ids[2], resource_2); 479 EXPECT_EQ(resource_ids[3], resource_3); 480 } 481 482 TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionUserInitiated) { 483 ConnectToNone(); 484 485 std::string resource_id("file:2_file_resource_id"); 486 487 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 488 scoped_ptr<google_apis::ResourceEntry> entry; 489 scheduler_->GetResourceEntry( 490 resource_id, 491 ClientContext(USER_INITIATED), 492 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 493 base::RunLoop().RunUntilIdle(); 494 495 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error); 496 } 497 498 TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionBackground) { 499 ConnectToNone(); 500 501 std::string resource_id("file:2_file_resource_id"); 502 503 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 504 scoped_ptr<google_apis::ResourceEntry> entry; 505 scheduler_->GetResourceEntry( 506 resource_id, 507 ClientContext(BACKGROUND), 508 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 509 base::RunLoop().RunUntilIdle(); 510 511 EXPECT_FALSE(entry); 512 513 // Reconnect to the net. 514 ConnectToWifi(); 515 516 base::RunLoop().RunUntilIdle(); 517 518 EXPECT_EQ(google_apis::HTTP_SUCCESS, error); 519 ASSERT_TRUE(entry); 520 EXPECT_EQ(resource_id, entry->resource_id()); 521 } 522 523 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) { 524 ConnectToCellular(); 525 526 // Disable fetching over cellular network. 527 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 528 529 // Try to get a file in the background 530 base::ScopedTempDir temp_dir; 531 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 532 533 const base::FilePath kOutputFilePath = 534 temp_dir.path().AppendASCII("whatever.txt"); 535 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 536 base::FilePath output_file_path; 537 scheduler_->DownloadFile( 538 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 539 kOutputFilePath, 540 "file:2_file_resource_id", 541 ClientContext(BACKGROUND), 542 google_apis::test_util::CreateCopyResultCallback( 543 &download_error, &output_file_path), 544 google_apis::GetContentCallback()); 545 // Metadata should still work 546 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 547 scoped_ptr<google_apis::AboutResource> about_resource; 548 549 // Try to get the metadata 550 scheduler_->GetAboutResource( 551 google_apis::test_util::CreateCopyResultCallback( 552 &metadata_error, &about_resource)); 553 base::RunLoop().RunUntilIdle(); 554 555 // Check the metadata 556 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 557 ASSERT_TRUE(about_resource); 558 559 // Check the download 560 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 561 562 // Switch to a Wifi connection 563 ConnectToWifi(); 564 565 base::RunLoop().RunUntilIdle(); 566 567 // Check the download again 568 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 569 std::string content; 570 EXPECT_EQ(output_file_path, kOutputFilePath); 571 ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content)); 572 EXPECT_EQ("This is some test content.", content); 573 } 574 575 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) { 576 ConnectToWimax(); 577 578 // Disable fetching over cellular network. 579 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 580 581 // Try to get a file in the background 582 base::ScopedTempDir temp_dir; 583 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 584 585 const base::FilePath kOutputFilePath = 586 temp_dir.path().AppendASCII("whatever.txt"); 587 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 588 base::FilePath output_file_path; 589 scheduler_->DownloadFile( 590 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 591 kOutputFilePath, 592 "file:2_file_resource_id", 593 ClientContext(BACKGROUND), 594 google_apis::test_util::CreateCopyResultCallback( 595 &download_error, &output_file_path), 596 google_apis::GetContentCallback()); 597 // Metadata should still work 598 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 599 scoped_ptr<google_apis::AboutResource> about_resource; 600 601 // Try to get the metadata 602 scheduler_->GetAboutResource( 603 google_apis::test_util::CreateCopyResultCallback( 604 &metadata_error, &about_resource)); 605 base::RunLoop().RunUntilIdle(); 606 607 // Check the metadata 608 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 609 ASSERT_TRUE(about_resource); 610 611 // Check the download 612 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error); 613 614 // Switch to a Wifi connection 615 ConnectToWifi(); 616 617 base::RunLoop().RunUntilIdle(); 618 619 // Check the download again 620 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 621 std::string content; 622 EXPECT_EQ(output_file_path, kOutputFilePath); 623 ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content)); 624 EXPECT_EQ("This is some test content.", content); 625 } 626 627 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) { 628 ConnectToCellular(); 629 630 // Enable fetching over cellular network. 631 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 632 633 // Try to get a file in the background 634 base::ScopedTempDir temp_dir; 635 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 636 637 const base::FilePath kOutputFilePath = 638 temp_dir.path().AppendASCII("whatever.txt"); 639 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 640 base::FilePath output_file_path; 641 scheduler_->DownloadFile( 642 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 643 kOutputFilePath, 644 "file:2_file_resource_id", 645 ClientContext(BACKGROUND), 646 google_apis::test_util::CreateCopyResultCallback( 647 &download_error, &output_file_path), 648 google_apis::GetContentCallback()); 649 // Metadata should still work 650 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 651 scoped_ptr<google_apis::AboutResource> about_resource; 652 653 // Try to get the metadata 654 scheduler_->GetAboutResource( 655 google_apis::test_util::CreateCopyResultCallback( 656 &metadata_error, &about_resource)); 657 base::RunLoop().RunUntilIdle(); 658 659 // Check the metadata 660 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 661 ASSERT_TRUE(about_resource); 662 663 // Check the download 664 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 665 std::string content; 666 EXPECT_EQ(output_file_path, kOutputFilePath); 667 ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content)); 668 EXPECT_EQ("This is some test content.", content); 669 } 670 671 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) { 672 ConnectToWimax(); 673 674 // Enable fetching over cellular network. 675 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false); 676 677 // Try to get a file in the background 678 base::ScopedTempDir temp_dir; 679 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 680 681 const base::FilePath kOutputFilePath = 682 temp_dir.path().AppendASCII("whatever.txt"); 683 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR; 684 base::FilePath output_file_path; 685 scheduler_->DownloadFile( 686 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 687 kOutputFilePath, 688 "file:2_file_resource_id", 689 ClientContext(BACKGROUND), 690 google_apis::test_util::CreateCopyResultCallback( 691 &download_error, &output_file_path), 692 google_apis::GetContentCallback()); 693 // Metadata should still work 694 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR; 695 scoped_ptr<google_apis::AboutResource> about_resource; 696 697 // Try to get the metadata 698 scheduler_->GetAboutResource( 699 google_apis::test_util::CreateCopyResultCallback( 700 &metadata_error, &about_resource)); 701 base::RunLoop().RunUntilIdle(); 702 703 // Check the metadata 704 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error); 705 ASSERT_TRUE(about_resource); 706 707 // Check the download 708 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error); 709 std::string content; 710 EXPECT_EQ(output_file_path, kOutputFilePath); 711 ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content)); 712 EXPECT_EQ("This is some test content.", content); 713 } 714 715 TEST_F(JobSchedulerTest, JobInfo) { 716 JobListLogger logger; 717 scheduler_->AddObserver(&logger); 718 719 // Disable background upload/download. 720 ConnectToWimax(); 721 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true); 722 723 base::ScopedTempDir temp_dir; 724 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 725 726 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 727 scoped_ptr<google_apis::ResourceEntry> entry; 728 scoped_ptr<google_apis::AboutResource> about_resource; 729 base::FilePath path; 730 731 std::set<JobType> expected_types; 732 733 // Add many jobs. 734 expected_types.insert(TYPE_ADD_NEW_DIRECTORY); 735 scheduler_->AddNewDirectory( 736 fake_drive_service_->GetRootResourceId(), 737 "New Directory", 738 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 739 expected_types.insert(TYPE_GET_ABOUT_RESOURCE); 740 scheduler_->GetAboutResource( 741 google_apis::test_util::CreateCopyResultCallback( 742 &error, &about_resource)); 743 expected_types.insert(TYPE_RENAME_RESOURCE); 744 scheduler_->RenameResource( 745 "file:2_file_resource_id", 746 "New Title", 747 google_apis::test_util::CreateCopyResultCallback(&error)); 748 expected_types.insert(TYPE_DOWNLOAD_FILE); 749 scheduler_->DownloadFile( 750 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 751 temp_dir.path().AppendASCII("whatever.txt"), 752 "file:2_file_resource_id", 753 ClientContext(BACKGROUND), 754 google_apis::test_util::CreateCopyResultCallback(&error, &path), 755 google_apis::GetContentCallback()); 756 757 // The number of jobs queued so far. 758 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size()); 759 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY)); 760 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE)); 761 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE)); 762 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE)); 763 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 764 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 765 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE)); 766 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 767 768 // Add more jobs. 769 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY); 770 scheduler_->AddResourceToDirectory( 771 "folder:1_folder_resource_id", 772 "file:2_file_resource_id", 773 google_apis::test_util::CreateCopyResultCallback(&error)); 774 expected_types.insert(TYPE_COPY_HOSTED_DOCUMENT); 775 scheduler_->CopyHostedDocument( 776 "document:5_document_resource_id", 777 "New Document", 778 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 779 780 // 6 jobs in total were queued. 781 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList(); 782 EXPECT_EQ(6U, jobs.size()); 783 std::set<JobType> actual_types; 784 std::set<JobID> job_ids; 785 for (size_t i = 0; i < jobs.size(); ++i) { 786 actual_types.insert(jobs[i].job_type); 787 job_ids.insert(jobs[i].job_id); 788 } 789 EXPECT_EQ(expected_types, actual_types); 790 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique"; 791 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 792 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_HOSTED_DOCUMENT)); 793 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 794 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT)); 795 796 // Run the jobs. 797 base::RunLoop().RunUntilIdle(); 798 799 // All jobs except the BACKGROUND job should have started running (UPDATED) 800 // and then finished (DONE). 801 jobs = scheduler_->GetJobInfoList(); 802 ASSERT_EQ(1U, jobs.size()); 803 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type); 804 805 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY)); 806 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE)); 807 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE)); 808 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, 809 TYPE_ADD_RESOURCE_TO_DIRECTORY)); 810 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_HOSTED_DOCUMENT)); 811 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 812 813 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY)); 814 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE)); 815 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE)); 816 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY)); 817 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT)); 818 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 819 820 // Run the background downloading job as well. 821 ConnectToWifi(); 822 base::RunLoop().RunUntilIdle(); 823 824 // All jobs should have finished. 825 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size()); 826 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE)); 827 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE)); 828 } 829 830 831 TEST_F(JobSchedulerTest, JobInfoProgress) { 832 JobListLogger logger; 833 scheduler_->AddObserver(&logger); 834 835 ConnectToWifi(); 836 837 base::ScopedTempDir temp_dir; 838 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 839 840 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 841 base::FilePath path; 842 843 // Download job. 844 scheduler_->DownloadFile( 845 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path 846 temp_dir.path().AppendASCII("whatever.txt"), 847 "file:2_file_resource_id", 848 ClientContext(BACKGROUND), 849 google_apis::test_util::CreateCopyResultCallback(&error, &path), 850 google_apis::GetContentCallback()); 851 base::RunLoop().RunUntilIdle(); 852 853 std::vector<int64> download_progress; 854 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress); 855 ASSERT_TRUE(!download_progress.empty()); 856 EXPECT_TRUE(base::STLIsSorted(download_progress)); 857 EXPECT_GE(download_progress.front(), 0); 858 EXPECT_LE(download_progress.back(), 26); 859 860 // Upload job. 861 path = temp_dir.path().AppendASCII("new_file.txt"); 862 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello")); 863 google_apis::GDataErrorCode upload_error = 864 google_apis::GDATA_OTHER_ERROR; 865 scoped_ptr<google_apis::ResourceEntry> entry; 866 867 scheduler_->UploadNewFile( 868 fake_drive_service_->GetRootResourceId(), 869 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), 870 path, 871 "dummy title", 872 "plain/plain", 873 ClientContext(BACKGROUND), 874 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry)); 875 base::RunLoop().RunUntilIdle(); 876 877 std::vector<int64> upload_progress; 878 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress); 879 ASSERT_TRUE(!upload_progress.empty()); 880 EXPECT_TRUE(base::STLIsSorted(upload_progress)); 881 EXPECT_GE(upload_progress.front(), 0); 882 EXPECT_LE(upload_progress.back(), 13); 883 } 884 885 } // namespace drive 886