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.
5 #include "chrome/browser/chromeos/drive/job_scheduler.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/browser/chromeos/drive/test_util.h"
17 #include "chrome/browser/drive/event_logger.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/drive/test_util.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "google_apis/drive/drive_api_parser.h"
23 #include "google_apis/drive/gdata_wapi_parser.h"
24 #include "google_apis/drive/test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
31 // Dummy value passed for the |expected_file_size| parameter of DownloadFile().
32 const int64 kDummyDownloadFileSize = 0;
34 void CopyTitleFromGetResourceEntryCallback(
35 std::vector<std::string>* title_list_out,
36 google_apis::GDataErrorCode error_in,
37 scoped_ptr<google_apis::ResourceEntry> resource_entry_in) {
38 title_list_out->push_back(resource_entry_in->title());
41 class JobListLogger : public JobListObserver {
53 EventLog(EventType type, const JobInfo& info) : type(type), info(info) {
57 // Checks whether the specified type of event has occurred.
58 bool Has(EventType type, JobType job_type) {
59 for (size_t i = 0; i < events.size(); ++i) {
60 if (events[i].type == type && events[i].info.job_type == job_type)
66 // Gets the progress event information of the specified type.
67 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) {
68 for (size_t i = 0; i < events.size(); ++i) {
69 if (events[i].type == UPDATED && events[i].info.job_type == job_type)
70 progress->push_back(events[i].info.num_completed_bytes);
74 // JobListObserver overrides.
75 virtual void OnJobAdded(const JobInfo& info) OVERRIDE {
76 events.push_back(EventLog(ADDED, info));
79 virtual void OnJobUpdated(const JobInfo& info) OVERRIDE {
80 events.push_back(EventLog(UPDATED, info));
83 virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE {
84 events.push_back(EventLog(DONE, info));
88 std::vector<EventLog> events;
91 // Fake drive service extended for testing cancellation.
92 // When upload_new_file_cancelable is set, this Drive service starts
93 // returning a closure to cancel from InitiateUploadNewFile(). The task will
94 // finish only when the cancel closure is called.
95 class CancelTestableFakeDriveService : public FakeDriveService {
97 CancelTestableFakeDriveService()
98 : upload_new_file_cancelable_(false) {
101 void set_upload_new_file_cancelable(bool cancelable) {
102 upload_new_file_cancelable_ = cancelable;
105 virtual google_apis::CancelCallback InitiateUploadNewFile(
106 const std::string& content_type,
107 int64 content_length,
108 const std::string& parent_resource_id,
109 const std::string& title,
110 const InitiateUploadNewFileOptions& options,
111 const google_apis::InitiateUploadCallback& callback) OVERRIDE {
112 if (upload_new_file_cancelable_)
113 return base::Bind(callback, google_apis::GDATA_CANCELLED, GURL());
115 return FakeDriveService::InitiateUploadNewFile(content_type,
124 bool upload_new_file_cancelable_;
129 class JobSchedulerTest : public testing::Test {
132 : pref_service_(new TestingPrefServiceSimple) {
133 test_util::RegisterDrivePrefs(pref_service_->registry());
136 virtual void SetUp() OVERRIDE {
137 fake_network_change_notifier_.reset(
138 new test_util::FakeNetworkChangeNotifier);
140 logger_.reset(new EventLogger);
142 fake_drive_service_.reset(new CancelTestableFakeDriveService);
143 test_util::SetUpTestEntries(fake_drive_service_.get());
144 fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
146 scheduler_.reset(new JobScheduler(pref_service_.get(),
148 fake_drive_service_.get(),
149 base::MessageLoopProxy::current().get()));
150 scheduler_->SetDisableThrottling(true);
154 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
155 // the specified connection type.
156 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
157 fake_network_change_notifier_->SetConnectionType(type);
160 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
161 void ConnectToWifi() {
162 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
165 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
166 void ConnectToCellular() {
167 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
170 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
171 void ConnectToWimax() {
172 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
175 // Sets up FakeNetworkChangeNotifier as if it's disconnected.
176 void ConnectToNone() {
177 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
180 static int GetMetadataQueueMaxJobCount() {
181 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
184 content::TestBrowserThreadBundle thread_bundle_;
185 scoped_ptr<TestingPrefServiceSimple> pref_service_;
186 scoped_ptr<test_util::FakeNetworkChangeNotifier>
187 fake_network_change_notifier_;
188 scoped_ptr<EventLogger> logger_;
189 scoped_ptr<CancelTestableFakeDriveService> fake_drive_service_;
190 scoped_ptr<JobScheduler> scheduler_;
193 TEST_F(JobSchedulerTest, GetAboutResource) {
196 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
197 scoped_ptr<google_apis::AboutResource> about_resource;
198 scheduler_->GetAboutResource(
199 google_apis::test_util::CreateCopyResultCallback(
200 &error, &about_resource));
201 base::RunLoop().RunUntilIdle();
202 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
203 ASSERT_TRUE(about_resource);
206 TEST_F(JobSchedulerTest, GetAppList) {
209 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
210 scoped_ptr<google_apis::AppList> app_list;
212 scheduler_->GetAppList(
213 google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
214 base::RunLoop().RunUntilIdle();
216 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
217 ASSERT_TRUE(app_list);
220 TEST_F(JobSchedulerTest, GetAllResourceList) {
223 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
224 scoped_ptr<google_apis::ResourceList> resource_list;
226 scheduler_->GetAllResourceList(
227 google_apis::test_util::CreateCopyResultCallback(
228 &error, &resource_list));
229 base::RunLoop().RunUntilIdle();
231 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
232 ASSERT_TRUE(resource_list);
235 TEST_F(JobSchedulerTest, GetResourceListInDirectory) {
238 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
239 scoped_ptr<google_apis::ResourceList> resource_list;
241 scheduler_->GetResourceListInDirectory(
242 fake_drive_service_->GetRootResourceId(),
243 google_apis::test_util::CreateCopyResultCallback(
244 &error, &resource_list));
245 base::RunLoop().RunUntilIdle();
247 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
248 ASSERT_TRUE(resource_list);
251 TEST_F(JobSchedulerTest, Search) {
254 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
255 scoped_ptr<google_apis::ResourceList> resource_list;
258 "File", // search query
259 google_apis::test_util::CreateCopyResultCallback(
260 &error, &resource_list));
261 base::RunLoop().RunUntilIdle();
263 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
264 ASSERT_TRUE(resource_list);
267 TEST_F(JobSchedulerTest, GetChangeList) {
270 int64 old_largest_change_id =
271 fake_drive_service_->about_resource().largest_change_id();
273 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
275 // Create a new directory.
277 scoped_ptr<google_apis::ResourceEntry> resource_entry;
278 fake_drive_service_->AddNewDirectory(
279 fake_drive_service_->GetRootResourceId(),
281 DriveServiceInterface::AddNewDirectoryOptions(),
282 google_apis::test_util::CreateCopyResultCallback(
283 &error, &resource_entry));
284 base::RunLoop().RunUntilIdle();
285 ASSERT_EQ(google_apis::HTTP_CREATED, error);
288 error = google_apis::GDATA_OTHER_ERROR;
289 scoped_ptr<google_apis::ResourceList> resource_list;
290 scheduler_->GetChangeList(
291 old_largest_change_id + 1,
292 google_apis::test_util::CreateCopyResultCallback(
293 &error, &resource_list));
294 base::RunLoop().RunUntilIdle();
296 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
297 ASSERT_TRUE(resource_list);
300 TEST_F(JobSchedulerTest, GetRemainingChangeList) {
302 fake_drive_service_->set_default_max_results(2);
304 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
305 scoped_ptr<google_apis::ResourceList> resource_list;
307 scheduler_->GetAllResourceList(
308 google_apis::test_util::CreateCopyResultCallback(
309 &error, &resource_list));
310 base::RunLoop().RunUntilIdle();
312 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
313 ASSERT_TRUE(resource_list);
315 const google_apis::Link* next_link =
316 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
317 ASSERT_TRUE(next_link);
318 // Keep the next url before releasing the |resource_list|.
319 GURL next_url(next_link->href());
321 error = google_apis::GDATA_OTHER_ERROR;
322 resource_list.reset();
324 scheduler_->GetRemainingChangeList(
326 google_apis::test_util::CreateCopyResultCallback(
327 &error, &resource_list));
328 base::RunLoop().RunUntilIdle();
330 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
331 ASSERT_TRUE(resource_list);
334 TEST_F(JobSchedulerTest, GetRemainingFileList) {
336 fake_drive_service_->set_default_max_results(2);
338 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
339 scoped_ptr<google_apis::ResourceList> resource_list;
341 scheduler_->GetResourceListInDirectory(
342 fake_drive_service_->GetRootResourceId(),
343 google_apis::test_util::CreateCopyResultCallback(
344 &error, &resource_list));
345 base::RunLoop().RunUntilIdle();
347 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
348 ASSERT_TRUE(resource_list);
350 const google_apis::Link* next_link =
351 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
352 ASSERT_TRUE(next_link);
353 // Keep the next url before releasing the |resource_list|.
354 GURL next_url(next_link->href());
356 error = google_apis::GDATA_OTHER_ERROR;
357 resource_list.reset();
359 scheduler_->GetRemainingFileList(
361 google_apis::test_util::CreateCopyResultCallback(
362 &error, &resource_list));
363 base::RunLoop().RunUntilIdle();
365 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
366 ASSERT_TRUE(resource_list);
369 TEST_F(JobSchedulerTest, GetResourceEntry) {
372 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
373 scoped_ptr<google_apis::ResourceEntry> entry;
375 scheduler_->GetResourceEntry(
376 "file:2_file_resource_id", // resource ID
377 ClientContext(USER_INITIATED),
378 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
379 base::RunLoop().RunUntilIdle();
381 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
385 TEST_F(JobSchedulerTest, GetShareUrl) {
388 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
391 scheduler_->GetShareUrl(
392 "file:2_file_resource_id", // resource ID
393 GURL("chrome-extension://test-id/"), // embed origin
394 ClientContext(USER_INITIATED),
395 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
396 base::RunLoop().RunUntilIdle();
398 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
399 ASSERT_FALSE(share_url.is_empty());
402 TEST_F(JobSchedulerTest, TrashResource) {
405 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
407 scheduler_->TrashResource(
408 "file:2_file_resource_id",
409 ClientContext(USER_INITIATED),
410 google_apis::test_util::CreateCopyResultCallback(&error));
411 base::RunLoop().RunUntilIdle();
413 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
416 TEST_F(JobSchedulerTest, CopyResource) {
419 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
420 scoped_ptr<google_apis::ResourceEntry> entry;
422 scheduler_->CopyResource(
423 "file:2_file_resource_id", // resource ID
424 "folder:1_folder_resource_id", // parent resource ID
425 "New Document", // new title
427 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
428 base::RunLoop().RunUntilIdle();
430 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
434 TEST_F(JobSchedulerTest, UpdateResource) {
437 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
438 scoped_ptr<google_apis::ResourceEntry> entry;
440 scheduler_->UpdateResource(
441 "file:2_file_resource_id", // resource ID
442 "folder:1_folder_resource_id", // parent resource ID
443 "New Document", // new title
446 ClientContext(USER_INITIATED),
447 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
448 base::RunLoop().RunUntilIdle();
450 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
454 TEST_F(JobSchedulerTest, RenameResource) {
457 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
459 scheduler_->RenameResource(
460 "file:2_file_resource_id",
462 google_apis::test_util::CreateCopyResultCallback(&error));
463 base::RunLoop().RunUntilIdle();
465 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
468 TEST_F(JobSchedulerTest, AddResourceToDirectory) {
471 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
473 scheduler_->AddResourceToDirectory(
474 "folder:1_folder_resource_id",
475 "file:2_file_resource_id",
476 google_apis::test_util::CreateCopyResultCallback(&error));
477 base::RunLoop().RunUntilIdle();
479 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
482 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
485 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
487 scheduler_->RemoveResourceFromDirectory(
488 "folder:1_folder_resource_id",
489 "file:subdirectory_file_1_id", // resource ID
490 ClientContext(USER_INITIATED),
491 google_apis::test_util::CreateCopyResultCallback(&error));
492 base::RunLoop().RunUntilIdle();
494 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error);
497 TEST_F(JobSchedulerTest, AddNewDirectory) {
500 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
501 scoped_ptr<google_apis::ResourceEntry> entry;
503 scheduler_->AddNewDirectory(
504 fake_drive_service_->GetRootResourceId(), // Root directory.
506 DriveServiceInterface::AddNewDirectoryOptions(),
507 ClientContext(USER_INITIATED),
508 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
509 base::RunLoop().RunUntilIdle();
511 ASSERT_EQ(google_apis::HTTP_CREATED, error);
515 TEST_F(JobSchedulerTest, PriorityHandling) {
516 // Saturate the metadata job queue with uninteresting jobs to prevent
517 // following jobs from starting.
518 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
519 scoped_ptr<google_apis::ResourceEntry> entry_dontcare;
520 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
521 std::string resource_id("file:2_file_resource_id");
522 scheduler_->GetResourceEntry(
524 ClientContext(USER_INITIATED),
525 google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
529 // Start jobs with different priorities.
530 std::string title_1("new file 1");
531 std::string title_2("new file 2");
532 std::string title_3("new file 3");
533 std::string title_4("new file 4");
534 std::vector<std::string> titles;
536 scheduler_->AddNewDirectory(
537 fake_drive_service_->GetRootResourceId(),
539 DriveServiceInterface::AddNewDirectoryOptions(),
540 ClientContext(USER_INITIATED),
541 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
542 scheduler_->AddNewDirectory(
543 fake_drive_service_->GetRootResourceId(),
545 DriveServiceInterface::AddNewDirectoryOptions(),
546 ClientContext(BACKGROUND),
547 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
548 scheduler_->AddNewDirectory(
549 fake_drive_service_->GetRootResourceId(),
551 DriveServiceInterface::AddNewDirectoryOptions(),
552 ClientContext(BACKGROUND),
553 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
554 scheduler_->AddNewDirectory(
555 fake_drive_service_->GetRootResourceId(),
557 DriveServiceInterface::AddNewDirectoryOptions(),
558 ClientContext(USER_INITIATED),
559 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
561 base::RunLoop().RunUntilIdle();
563 ASSERT_EQ(4ul, titles.size());
564 EXPECT_EQ(title_1, titles[0]);
565 EXPECT_EQ(title_4, titles[1]);
566 EXPECT_EQ(title_2, titles[2]);
567 EXPECT_EQ(title_3, titles[3]);
570 TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
573 std::string resource_id("file:2_file_resource_id");
575 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
576 scoped_ptr<google_apis::ResourceEntry> entry;
577 scheduler_->GetResourceEntry(
579 ClientContext(USER_INITIATED),
580 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
581 base::RunLoop().RunUntilIdle();
583 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
586 TEST_F(JobSchedulerTest, NoConnectionBackground) {
589 std::string resource_id("file:2_file_resource_id");
591 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
592 scoped_ptr<google_apis::ResourceEntry> entry;
593 scheduler_->GetResourceEntry(
595 ClientContext(BACKGROUND),
596 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
597 base::RunLoop().RunUntilIdle();
601 // Reconnect to the net.
604 base::RunLoop().RunUntilIdle();
606 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
610 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
613 // Disable fetching over cellular network.
614 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
616 // Try to get a file in the background
617 base::ScopedTempDir temp_dir;
618 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
620 const base::FilePath kOutputFilePath =
621 temp_dir.path().AppendASCII("whatever.txt");
622 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
623 base::FilePath output_file_path;
624 scheduler_->DownloadFile(
625 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
626 kDummyDownloadFileSize,
628 "file:2_file_resource_id",
629 ClientContext(BACKGROUND),
630 google_apis::test_util::CreateCopyResultCallback(
631 &download_error, &output_file_path),
632 google_apis::GetContentCallback());
633 // Metadata should still work
634 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
635 scoped_ptr<google_apis::AboutResource> about_resource;
637 // Try to get the metadata
638 scheduler_->GetAboutResource(
639 google_apis::test_util::CreateCopyResultCallback(
640 &metadata_error, &about_resource));
641 base::RunLoop().RunUntilIdle();
643 // Check the metadata
644 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
645 ASSERT_TRUE(about_resource);
647 // Check the download
648 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
650 // Switch to a Wifi connection
653 base::RunLoop().RunUntilIdle();
655 // Check the download again
656 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
658 EXPECT_EQ(output_file_path, kOutputFilePath);
659 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
660 EXPECT_EQ("This is some test content.", content);
663 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
666 // Disable fetching over cellular network.
667 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
669 // Try to get a file in the background
670 base::ScopedTempDir temp_dir;
671 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
673 const base::FilePath kOutputFilePath =
674 temp_dir.path().AppendASCII("whatever.txt");
675 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
676 base::FilePath output_file_path;
677 scheduler_->DownloadFile(
678 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
679 kDummyDownloadFileSize,
681 "file:2_file_resource_id",
682 ClientContext(BACKGROUND),
683 google_apis::test_util::CreateCopyResultCallback(
684 &download_error, &output_file_path),
685 google_apis::GetContentCallback());
686 // Metadata should still work
687 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
688 scoped_ptr<google_apis::AboutResource> about_resource;
690 // Try to get the metadata
691 scheduler_->GetAboutResource(
692 google_apis::test_util::CreateCopyResultCallback(
693 &metadata_error, &about_resource));
694 base::RunLoop().RunUntilIdle();
696 // Check the metadata
697 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
698 ASSERT_TRUE(about_resource);
700 // Check the download
701 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
703 // Switch to a Wifi connection
706 base::RunLoop().RunUntilIdle();
708 // Check the download again
709 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
711 EXPECT_EQ(output_file_path, kOutputFilePath);
712 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
713 EXPECT_EQ("This is some test content.", content);
716 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
719 // Enable fetching over cellular network.
720 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
722 // Try to get a file in the background
723 base::ScopedTempDir temp_dir;
724 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
726 const base::FilePath kOutputFilePath =
727 temp_dir.path().AppendASCII("whatever.txt");
728 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
729 base::FilePath output_file_path;
730 scheduler_->DownloadFile(
731 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
732 kDummyDownloadFileSize,
734 "file:2_file_resource_id",
735 ClientContext(BACKGROUND),
736 google_apis::test_util::CreateCopyResultCallback(
737 &download_error, &output_file_path),
738 google_apis::GetContentCallback());
739 // Metadata should still work
740 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
741 scoped_ptr<google_apis::AboutResource> about_resource;
743 // Try to get the metadata
744 scheduler_->GetAboutResource(
745 google_apis::test_util::CreateCopyResultCallback(
746 &metadata_error, &about_resource));
747 base::RunLoop().RunUntilIdle();
749 // Check the metadata
750 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
751 ASSERT_TRUE(about_resource);
753 // Check the download
754 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
756 EXPECT_EQ(output_file_path, kOutputFilePath);
757 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
758 EXPECT_EQ("This is some test content.", content);
761 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
764 // Enable fetching over cellular network.
765 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
767 // Try to get a file in the background
768 base::ScopedTempDir temp_dir;
769 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
771 const base::FilePath kOutputFilePath =
772 temp_dir.path().AppendASCII("whatever.txt");
773 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
774 base::FilePath output_file_path;
775 scheduler_->DownloadFile(
776 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
777 kDummyDownloadFileSize,
779 "file:2_file_resource_id",
780 ClientContext(BACKGROUND),
781 google_apis::test_util::CreateCopyResultCallback(
782 &download_error, &output_file_path),
783 google_apis::GetContentCallback());
784 // Metadata should still work
785 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
786 scoped_ptr<google_apis::AboutResource> about_resource;
788 // Try to get the metadata
789 scheduler_->GetAboutResource(
790 google_apis::test_util::CreateCopyResultCallback(
791 &metadata_error, &about_resource));
792 base::RunLoop().RunUntilIdle();
794 // Check the metadata
795 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
796 ASSERT_TRUE(about_resource);
798 // Check the download
799 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
801 EXPECT_EQ(output_file_path, kOutputFilePath);
802 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
803 EXPECT_EQ("This is some test content.", content);
806 TEST_F(JobSchedulerTest, JobInfo) {
807 JobListLogger logger;
808 scheduler_->AddObserver(&logger);
810 // Disable background upload/download.
812 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
814 base::ScopedTempDir temp_dir;
815 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
817 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
818 scoped_ptr<google_apis::ResourceEntry> entry;
819 scoped_ptr<google_apis::AboutResource> about_resource;
822 std::set<JobType> expected_types;
825 expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
826 scheduler_->AddNewDirectory(
827 fake_drive_service_->GetRootResourceId(),
829 DriveServiceInterface::AddNewDirectoryOptions(),
830 ClientContext(USER_INITIATED),
831 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
832 expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
833 scheduler_->GetAboutResource(
834 google_apis::test_util::CreateCopyResultCallback(
835 &error, &about_resource));
836 expected_types.insert(TYPE_RENAME_RESOURCE);
837 scheduler_->RenameResource(
838 "file:2_file_resource_id",
840 google_apis::test_util::CreateCopyResultCallback(&error));
841 expected_types.insert(TYPE_DOWNLOAD_FILE);
842 scheduler_->DownloadFile(
843 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
844 kDummyDownloadFileSize,
845 temp_dir.path().AppendASCII("whatever.txt"),
846 "file:2_file_resource_id",
847 ClientContext(BACKGROUND),
848 google_apis::test_util::CreateCopyResultCallback(&error, &path),
849 google_apis::GetContentCallback());
851 // The number of jobs queued so far.
852 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
853 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
854 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
855 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE));
856 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
857 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
858 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
859 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
860 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
863 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
864 scheduler_->AddResourceToDirectory(
865 "folder:1_folder_resource_id",
866 "file:2_file_resource_id",
867 google_apis::test_util::CreateCopyResultCallback(&error));
868 expected_types.insert(TYPE_COPY_RESOURCE);
869 scheduler_->CopyResource(
870 "document:5_document_resource_id",
871 fake_drive_service_->GetRootResourceId(),
873 base::Time(), // last_modified
874 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
876 // 6 jobs in total were queued.
877 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
878 EXPECT_EQ(6U, jobs.size());
879 std::set<JobType> actual_types;
880 std::set<JobID> job_ids;
881 for (size_t i = 0; i < jobs.size(); ++i) {
882 actual_types.insert(jobs[i].job_type);
883 job_ids.insert(jobs[i].job_id);
885 EXPECT_EQ(expected_types, actual_types);
886 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
887 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
888 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE));
889 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
890 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
893 base::RunLoop().RunUntilIdle();
895 // All jobs except the BACKGROUND job should have started running (UPDATED)
896 // and then finished (DONE).
897 jobs = scheduler_->GetJobInfoList();
898 ASSERT_EQ(1U, jobs.size());
899 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
901 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
902 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
903 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE));
904 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
905 TYPE_ADD_RESOURCE_TO_DIRECTORY));
906 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE));
907 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
909 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
910 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
911 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
912 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
913 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
914 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
916 // Run the background downloading job as well.
918 base::RunLoop().RunUntilIdle();
920 // All jobs should have finished.
921 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
922 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
923 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
926 TEST_F(JobSchedulerTest, JobInfoProgress) {
927 JobListLogger logger;
928 scheduler_->AddObserver(&logger);
932 base::ScopedTempDir temp_dir;
933 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
935 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
939 scheduler_->DownloadFile(
940 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
941 kDummyDownloadFileSize,
942 temp_dir.path().AppendASCII("whatever.txt"),
943 "file:2_file_resource_id",
944 ClientContext(BACKGROUND),
945 google_apis::test_util::CreateCopyResultCallback(&error, &path),
946 google_apis::GetContentCallback());
947 base::RunLoop().RunUntilIdle();
949 std::vector<int64> download_progress;
950 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
951 ASSERT_TRUE(!download_progress.empty());
952 EXPECT_TRUE(base::STLIsSorted(download_progress));
953 EXPECT_GE(download_progress.front(), 0);
954 EXPECT_LE(download_progress.back(), 26);
957 path = temp_dir.path().AppendASCII("new_file.txt");
958 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
959 google_apis::GDataErrorCode upload_error =
960 google_apis::GDATA_OTHER_ERROR;
961 scoped_ptr<google_apis::ResourceEntry> entry;
963 scheduler_->UploadNewFile(
964 fake_drive_service_->GetRootResourceId(),
965 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
969 DriveUploader::UploadNewFileOptions(),
970 ClientContext(BACKGROUND),
971 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
972 base::RunLoop().RunUntilIdle();
974 std::vector<int64> upload_progress;
975 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
976 ASSERT_TRUE(!upload_progress.empty());
977 EXPECT_TRUE(base::STLIsSorted(upload_progress));
978 EXPECT_GE(upload_progress.front(), 0);
979 EXPECT_LE(upload_progress.back(), 13);
982 TEST_F(JobSchedulerTest, CancelPendingJob) {
983 base::ScopedTempDir temp_dir;
984 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
985 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
986 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
988 // To create a pending job for testing, set the mode to cellular connection
989 // and issue BACKGROUND jobs.
991 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
993 // Start the first job and record its job ID.
994 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
995 scoped_ptr<google_apis::ResourceEntry> entry;
996 scheduler_->UploadNewFile(
997 fake_drive_service_->GetRootResourceId(),
998 base::FilePath::FromUTF8Unsafe("dummy/path"),
1002 DriveUploader::UploadNewFileOptions(),
1003 ClientContext(BACKGROUND),
1004 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1006 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1007 ASSERT_EQ(1u, jobs.size());
1008 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet.
1009 JobID first_job_id = jobs[0].job_id;
1011 // Start the second job.
1012 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1013 scheduler_->UploadNewFile(
1014 fake_drive_service_->GetRootResourceId(),
1015 base::FilePath::FromUTF8Unsafe("dummy/path"),
1019 DriveUploader::UploadNewFileOptions(),
1020 ClientContext(BACKGROUND),
1021 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1023 // Cancel the first one.
1024 scheduler_->CancelJob(first_job_id);
1026 // Only the first job should be cancelled.
1028 base::RunLoop().RunUntilIdle();
1029 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1030 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1031 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1034 TEST_F(JobSchedulerTest, CancelRunningJob) {
1037 base::ScopedTempDir temp_dir;
1038 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1039 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
1040 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
1042 // Run as a cancelable task.
1043 fake_drive_service_->set_upload_new_file_cancelable(true);
1044 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
1045 scoped_ptr<google_apis::ResourceEntry> entry;
1046 scheduler_->UploadNewFile(
1047 fake_drive_service_->GetRootResourceId(),
1048 base::FilePath::FromUTF8Unsafe("dummy/path"),
1052 DriveUploader::UploadNewFileOptions(),
1053 ClientContext(USER_INITIATED),
1054 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1056 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1057 ASSERT_EQ(1u, jobs.size());
1058 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running.
1059 JobID first_job_id = jobs[0].job_id;
1061 // Start the second job normally.
1062 fake_drive_service_->set_upload_new_file_cancelable(false);
1063 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1064 scheduler_->UploadNewFile(
1065 fake_drive_service_->GetRootResourceId(),
1066 base::FilePath::FromUTF8Unsafe("dummy/path"),
1070 DriveUploader::UploadNewFileOptions(),
1071 ClientContext(USER_INITIATED),
1072 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1074 // Cancel the first one.
1075 scheduler_->CancelJob(first_job_id);
1077 // Only the first job should be cancelled.
1078 base::RunLoop().RunUntilIdle();
1079 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1080 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1081 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1084 } // namespace drive