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/fake_drive_service.h"
18 #include "chrome/common/pref_names.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "google_apis/drive/drive_api_parser.h"
21 #include "google_apis/drive/gdata_wapi_parser.h"
22 #include "google_apis/drive/test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 // Dummy value passed for the |expected_file_size| parameter of DownloadFile().
30 const int64 kDummyDownloadFileSize = 0;
32 void CopyTitleFromGetResourceEntryCallback(
33 std::vector<std::string>* title_list_out,
34 google_apis::GDataErrorCode error_in,
35 scoped_ptr<google_apis::ResourceEntry> resource_entry_in) {
36 title_list_out->push_back(resource_entry_in->title());
39 class JobListLogger : public JobListObserver {
51 EventLog(EventType type, const JobInfo& info) : type(type), info(info) {
55 // Checks whether the specified type of event has occurred.
56 bool Has(EventType type, JobType job_type) {
57 for (size_t i = 0; i < events.size(); ++i) {
58 if (events[i].type == type && events[i].info.job_type == job_type)
64 // Gets the progress event information of the specified type.
65 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) {
66 for (size_t i = 0; i < events.size(); ++i) {
67 if (events[i].type == UPDATED && events[i].info.job_type == job_type)
68 progress->push_back(events[i].info.num_completed_bytes);
72 // JobListObserver overrides.
73 virtual void OnJobAdded(const JobInfo& info) OVERRIDE {
74 events.push_back(EventLog(ADDED, info));
77 virtual void OnJobUpdated(const JobInfo& info) OVERRIDE {
78 events.push_back(EventLog(UPDATED, info));
81 virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE {
82 events.push_back(EventLog(DONE, info));
86 std::vector<EventLog> events;
89 // Fake drive service extended for testing cancellation.
90 // When upload_new_file_cancelable is set, this Drive service starts
91 // returning a closure to cancel from InitiateUploadNewFile(). The task will
92 // finish only when the cancel closure is called.
93 class CancelTestableFakeDriveService : public FakeDriveService {
95 CancelTestableFakeDriveService()
96 : upload_new_file_cancelable_(false) {
99 void set_upload_new_file_cancelable(bool cancelable) {
100 upload_new_file_cancelable_ = cancelable;
103 virtual google_apis::CancelCallback InitiateUploadNewFile(
104 const std::string& content_type,
105 int64 content_length,
106 const std::string& parent_resource_id,
107 const std::string& title,
108 const InitiateUploadNewFileOptions& options,
109 const google_apis::InitiateUploadCallback& callback) OVERRIDE {
110 if (upload_new_file_cancelable_)
111 return base::Bind(callback, google_apis::GDATA_CANCELLED, GURL());
113 return FakeDriveService::InitiateUploadNewFile(content_type,
122 bool upload_new_file_cancelable_;
127 class JobSchedulerTest : public testing::Test {
130 : pref_service_(new TestingPrefServiceSimple) {
131 test_util::RegisterDrivePrefs(pref_service_->registry());
134 virtual void SetUp() OVERRIDE {
135 fake_network_change_notifier_.reset(
136 new test_util::FakeNetworkChangeNotifier);
138 fake_drive_service_.reset(new CancelTestableFakeDriveService);
139 fake_drive_service_->LoadResourceListForWapi(
140 "gdata/root_feed.json");
141 fake_drive_service_->LoadAccountMetadataForWapi(
142 "gdata/account_metadata.json");
143 fake_drive_service_->LoadAppListForDriveApi(
144 "drive/applist.json");
146 scheduler_.reset(new JobScheduler(pref_service_.get(),
147 fake_drive_service_.get(),
148 base::MessageLoopProxy::current().get()));
149 scheduler_->SetDisableThrottling(true);
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);
159 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
160 void ConnectToWifi() {
161 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
164 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
165 void ConnectToCellular() {
166 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
169 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
170 void ConnectToWimax() {
171 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
174 // Sets up FakeNetworkChangeNotifier as if it's disconnected.
175 void ConnectToNone() {
176 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
179 static int GetMetadataQueueMaxJobCount() {
180 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
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<CancelTestableFakeDriveService> fake_drive_service_;
188 scoped_ptr<JobScheduler> scheduler_;
191 TEST_F(JobSchedulerTest, GetAboutResource) {
194 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
195 scoped_ptr<google_apis::AboutResource> about_resource;
196 scheduler_->GetAboutResource(
197 google_apis::test_util::CreateCopyResultCallback(
198 &error, &about_resource));
199 base::RunLoop().RunUntilIdle();
200 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
201 ASSERT_TRUE(about_resource);
204 TEST_F(JobSchedulerTest, GetAppList) {
207 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
208 scoped_ptr<google_apis::AppList> app_list;
210 scheduler_->GetAppList(
211 google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
212 base::RunLoop().RunUntilIdle();
214 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
215 ASSERT_TRUE(app_list);
218 TEST_F(JobSchedulerTest, GetAllResourceList) {
221 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
222 scoped_ptr<google_apis::ResourceList> resource_list;
224 scheduler_->GetAllResourceList(
225 google_apis::test_util::CreateCopyResultCallback(
226 &error, &resource_list));
227 base::RunLoop().RunUntilIdle();
229 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
230 ASSERT_TRUE(resource_list);
233 TEST_F(JobSchedulerTest, GetResourceListInDirectory) {
236 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
237 scoped_ptr<google_apis::ResourceList> resource_list;
239 scheduler_->GetResourceListInDirectory(
240 fake_drive_service_->GetRootResourceId(),
241 google_apis::test_util::CreateCopyResultCallback(
242 &error, &resource_list));
243 base::RunLoop().RunUntilIdle();
245 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
246 ASSERT_TRUE(resource_list);
249 TEST_F(JobSchedulerTest, Search) {
252 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
253 scoped_ptr<google_apis::ResourceList> resource_list;
256 "File", // search query
257 google_apis::test_util::CreateCopyResultCallback(
258 &error, &resource_list));
259 base::RunLoop().RunUntilIdle();
261 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
262 ASSERT_TRUE(resource_list);
265 TEST_F(JobSchedulerTest, GetChangeList) {
268 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
270 // Create a new directory.
271 // The loaded (initial) changestamp is 654321. Thus, by this operation,
272 // it should become 654322.
274 scoped_ptr<google_apis::ResourceEntry> resource_entry;
275 fake_drive_service_->AddNewDirectory(
276 fake_drive_service_->GetRootResourceId(),
278 google_apis::test_util::CreateCopyResultCallback(
279 &error, &resource_entry));
280 base::RunLoop().RunUntilIdle();
281 ASSERT_EQ(google_apis::HTTP_CREATED, error);
284 error = google_apis::GDATA_OTHER_ERROR;
285 scoped_ptr<google_apis::ResourceList> resource_list;
286 scheduler_->GetChangeList(
287 654321 + 1, // start_changestamp
288 google_apis::test_util::CreateCopyResultCallback(
289 &error, &resource_list));
290 base::RunLoop().RunUntilIdle();
292 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
293 ASSERT_TRUE(resource_list);
296 TEST_F(JobSchedulerTest, GetRemainingChangeList) {
298 fake_drive_service_->set_default_max_results(2);
300 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
301 scoped_ptr<google_apis::ResourceList> resource_list;
303 scheduler_->GetAllResourceList(
304 google_apis::test_util::CreateCopyResultCallback(
305 &error, &resource_list));
306 base::RunLoop().RunUntilIdle();
308 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
309 ASSERT_TRUE(resource_list);
311 const google_apis::Link* next_link =
312 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
313 ASSERT_TRUE(next_link);
314 // Keep the next url before releasing the |resource_list|.
315 GURL next_url(next_link->href());
317 error = google_apis::GDATA_OTHER_ERROR;
318 resource_list.reset();
320 scheduler_->GetRemainingChangeList(
322 google_apis::test_util::CreateCopyResultCallback(
323 &error, &resource_list));
324 base::RunLoop().RunUntilIdle();
326 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
327 ASSERT_TRUE(resource_list);
330 TEST_F(JobSchedulerTest, GetRemainingFileList) {
332 fake_drive_service_->set_default_max_results(2);
334 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
335 scoped_ptr<google_apis::ResourceList> resource_list;
337 scheduler_->GetResourceListInDirectory(
338 fake_drive_service_->GetRootResourceId(),
339 google_apis::test_util::CreateCopyResultCallback(
340 &error, &resource_list));
341 base::RunLoop().RunUntilIdle();
343 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
344 ASSERT_TRUE(resource_list);
346 const google_apis::Link* next_link =
347 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
348 ASSERT_TRUE(next_link);
349 // Keep the next url before releasing the |resource_list|.
350 GURL next_url(next_link->href());
352 error = google_apis::GDATA_OTHER_ERROR;
353 resource_list.reset();
355 scheduler_->GetRemainingFileList(
357 google_apis::test_util::CreateCopyResultCallback(
358 &error, &resource_list));
359 base::RunLoop().RunUntilIdle();
361 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
362 ASSERT_TRUE(resource_list);
365 TEST_F(JobSchedulerTest, GetResourceEntry) {
368 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
369 scoped_ptr<google_apis::ResourceEntry> entry;
371 scheduler_->GetResourceEntry(
372 "file:2_file_resource_id", // resource ID
373 ClientContext(USER_INITIATED),
374 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
375 base::RunLoop().RunUntilIdle();
377 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
381 TEST_F(JobSchedulerTest, GetShareUrl) {
384 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
387 scheduler_->GetShareUrl(
388 "file:2_file_resource_id", // resource ID
389 GURL("chrome-extension://test-id/"), // embed origin
390 ClientContext(USER_INITIATED),
391 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
392 base::RunLoop().RunUntilIdle();
394 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
395 ASSERT_FALSE(share_url.is_empty());
398 TEST_F(JobSchedulerTest, TrashResource) {
401 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
403 scheduler_->TrashResource(
404 "file:2_file_resource_id",
405 ClientContext(USER_INITIATED),
406 google_apis::test_util::CreateCopyResultCallback(&error));
407 base::RunLoop().RunUntilIdle();
409 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
412 TEST_F(JobSchedulerTest, CopyResource) {
415 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
416 scoped_ptr<google_apis::ResourceEntry> entry;
418 scheduler_->CopyResource(
419 "file:2_file_resource_id", // resource ID
420 "folder:1_folder_resource_id", // parent resource ID
421 "New Document", // new title
423 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
424 base::RunLoop().RunUntilIdle();
426 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
430 TEST_F(JobSchedulerTest, UpdateResource) {
433 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
434 scoped_ptr<google_apis::ResourceEntry> entry;
436 scheduler_->UpdateResource(
437 "file:2_file_resource_id", // resource ID
438 "folder:1_folder_resource_id", // parent resource ID
439 "New Document", // new title
442 ClientContext(USER_INITIATED),
443 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
444 base::RunLoop().RunUntilIdle();
446 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
450 TEST_F(JobSchedulerTest, RenameResource) {
453 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
455 scheduler_->RenameResource(
456 "file:2_file_resource_id",
458 google_apis::test_util::CreateCopyResultCallback(&error));
459 base::RunLoop().RunUntilIdle();
461 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
464 TEST_F(JobSchedulerTest, AddResourceToDirectory) {
467 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
469 scheduler_->AddResourceToDirectory(
470 "folder:1_folder_resource_id",
471 "file:2_file_resource_id",
472 google_apis::test_util::CreateCopyResultCallback(&error));
473 base::RunLoop().RunUntilIdle();
475 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
478 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
481 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
483 scheduler_->RemoveResourceFromDirectory(
484 "folder:1_folder_resource_id",
485 "file:subdirectory_file_1_id", // resource ID
486 ClientContext(USER_INITIATED),
487 google_apis::test_util::CreateCopyResultCallback(&error));
488 base::RunLoop().RunUntilIdle();
490 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error);
493 TEST_F(JobSchedulerTest, AddNewDirectory) {
496 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
497 scoped_ptr<google_apis::ResourceEntry> entry;
499 scheduler_->AddNewDirectory(
500 fake_drive_service_->GetRootResourceId(), // Root directory.
502 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
503 base::RunLoop().RunUntilIdle();
505 ASSERT_EQ(google_apis::HTTP_CREATED, error);
509 TEST_F(JobSchedulerTest, PriorityHandling) {
510 const base::FilePath kDummyFilePath(FILE_PATH_LITERAL("dummy"));
512 // Saturate the metadata job queue with uninteresting jobs to prevent
513 // following jobs from starting.
514 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
515 scoped_ptr<google_apis::ResourceEntry> entry_dontcare;
516 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
517 scheduler_->CreateFile(
518 fake_drive_service_->GetRootResourceId(),
520 base::StringPrintf("uninteresting file %d", i),
522 ClientContext(USER_INITIATED),
523 google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
527 // Start jobs with different priorities.
528 std::string title_1("new file 1");
529 std::string title_2("new file 2");
530 std::string title_3("new file 3");
531 std::string title_4("new file 4");
532 std::vector<std::string> titles;
534 scheduler_->CreateFile(
535 fake_drive_service_->GetRootResourceId(),
539 ClientContext(USER_INITIATED),
540 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
541 scheduler_->CreateFile(
542 fake_drive_service_->GetRootResourceId(),
546 ClientContext(BACKGROUND),
547 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
548 scheduler_->CreateFile(
549 fake_drive_service_->GetRootResourceId(),
553 ClientContext(BACKGROUND),
554 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
555 scheduler_->CreateFile(
556 fake_drive_service_->GetRootResourceId(),
560 ClientContext(USER_INITIATED),
561 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
563 base::RunLoop().RunUntilIdle();
565 ASSERT_EQ(4ul, titles.size());
566 EXPECT_EQ(title_1, titles[0]);
567 EXPECT_EQ(title_4, titles[1]);
568 EXPECT_EQ(title_2, titles[2]);
569 EXPECT_EQ(title_3, titles[3]);
572 TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
575 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
576 scoped_ptr<google_apis::ResourceEntry> entry;
577 scheduler_->CreateFile(
578 fake_drive_service_->GetRootResourceId(),
579 base::FilePath(FILE_PATH_LITERAL("dummy")),
582 ClientContext(USER_INITIATED),
583 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
584 base::RunLoop().RunUntilIdle();
586 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
589 TEST_F(JobSchedulerTest, NoConnectionBackground) {
592 std::string resource_id("file:2_file_resource_id");
594 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
595 scoped_ptr<google_apis::ResourceEntry> entry;
596 scheduler_->CreateFile(
597 fake_drive_service_->GetRootResourceId(),
598 base::FilePath(FILE_PATH_LITERAL("dummy")),
601 ClientContext(BACKGROUND),
602 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
603 base::RunLoop().RunUntilIdle();
607 // Reconnect to the net.
610 base::RunLoop().RunUntilIdle();
612 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
614 EXPECT_EQ("title", entry->title());
617 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
620 // Disable fetching over cellular network.
621 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
623 // Try to get a file in the background
624 base::ScopedTempDir temp_dir;
625 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
627 const base::FilePath kOutputFilePath =
628 temp_dir.path().AppendASCII("whatever.txt");
629 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
630 base::FilePath output_file_path;
631 scheduler_->DownloadFile(
632 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
633 kDummyDownloadFileSize,
635 "file:2_file_resource_id",
636 ClientContext(BACKGROUND),
637 google_apis::test_util::CreateCopyResultCallback(
638 &download_error, &output_file_path),
639 google_apis::GetContentCallback());
640 // Metadata should still work
641 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
642 scoped_ptr<google_apis::AboutResource> about_resource;
644 // Try to get the metadata
645 scheduler_->GetAboutResource(
646 google_apis::test_util::CreateCopyResultCallback(
647 &metadata_error, &about_resource));
648 base::RunLoop().RunUntilIdle();
650 // Check the metadata
651 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
652 ASSERT_TRUE(about_resource);
654 // Check the download
655 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
657 // Switch to a Wifi connection
660 base::RunLoop().RunUntilIdle();
662 // Check the download again
663 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
665 EXPECT_EQ(output_file_path, kOutputFilePath);
666 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
667 EXPECT_EQ("This is some test content.", content);
670 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
673 // Disable fetching over cellular network.
674 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
676 // Try to get a file in the background
677 base::ScopedTempDir temp_dir;
678 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
680 const base::FilePath kOutputFilePath =
681 temp_dir.path().AppendASCII("whatever.txt");
682 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
683 base::FilePath output_file_path;
684 scheduler_->DownloadFile(
685 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
686 kDummyDownloadFileSize,
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;
697 // Try to get the metadata
698 scheduler_->GetAboutResource(
699 google_apis::test_util::CreateCopyResultCallback(
700 &metadata_error, &about_resource));
701 base::RunLoop().RunUntilIdle();
703 // Check the metadata
704 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
705 ASSERT_TRUE(about_resource);
707 // Check the download
708 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
710 // Switch to a Wifi connection
713 base::RunLoop().RunUntilIdle();
715 // Check the download again
716 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
718 EXPECT_EQ(output_file_path, kOutputFilePath);
719 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
720 EXPECT_EQ("This is some test content.", content);
723 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
726 // Enable fetching over cellular network.
727 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
729 // Try to get a file in the background
730 base::ScopedTempDir temp_dir;
731 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
733 const base::FilePath kOutputFilePath =
734 temp_dir.path().AppendASCII("whatever.txt");
735 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
736 base::FilePath output_file_path;
737 scheduler_->DownloadFile(
738 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
739 kDummyDownloadFileSize,
741 "file:2_file_resource_id",
742 ClientContext(BACKGROUND),
743 google_apis::test_util::CreateCopyResultCallback(
744 &download_error, &output_file_path),
745 google_apis::GetContentCallback());
746 // Metadata should still work
747 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
748 scoped_ptr<google_apis::AboutResource> about_resource;
750 // Try to get the metadata
751 scheduler_->GetAboutResource(
752 google_apis::test_util::CreateCopyResultCallback(
753 &metadata_error, &about_resource));
754 base::RunLoop().RunUntilIdle();
756 // Check the metadata
757 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
758 ASSERT_TRUE(about_resource);
760 // Check the download
761 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
763 EXPECT_EQ(output_file_path, kOutputFilePath);
764 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
765 EXPECT_EQ("This is some test content.", content);
768 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
771 // Enable fetching over cellular network.
772 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
774 // Try to get a file in the background
775 base::ScopedTempDir temp_dir;
776 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
778 const base::FilePath kOutputFilePath =
779 temp_dir.path().AppendASCII("whatever.txt");
780 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
781 base::FilePath output_file_path;
782 scheduler_->DownloadFile(
783 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
784 kDummyDownloadFileSize,
786 "file:2_file_resource_id",
787 ClientContext(BACKGROUND),
788 google_apis::test_util::CreateCopyResultCallback(
789 &download_error, &output_file_path),
790 google_apis::GetContentCallback());
791 // Metadata should still work
792 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
793 scoped_ptr<google_apis::AboutResource> about_resource;
795 // Try to get the metadata
796 scheduler_->GetAboutResource(
797 google_apis::test_util::CreateCopyResultCallback(
798 &metadata_error, &about_resource));
799 base::RunLoop().RunUntilIdle();
801 // Check the metadata
802 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
803 ASSERT_TRUE(about_resource);
805 // Check the download
806 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
808 EXPECT_EQ(output_file_path, kOutputFilePath);
809 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
810 EXPECT_EQ("This is some test content.", content);
813 TEST_F(JobSchedulerTest, JobInfo) {
814 JobListLogger logger;
815 scheduler_->AddObserver(&logger);
817 // Disable background upload/download.
819 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
821 base::ScopedTempDir temp_dir;
822 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
824 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
825 scoped_ptr<google_apis::ResourceEntry> entry;
826 scoped_ptr<google_apis::AboutResource> about_resource;
829 std::set<JobType> expected_types;
832 expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
833 scheduler_->AddNewDirectory(
834 fake_drive_service_->GetRootResourceId(),
836 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
837 expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
838 scheduler_->GetAboutResource(
839 google_apis::test_util::CreateCopyResultCallback(
840 &error, &about_resource));
841 expected_types.insert(TYPE_RENAME_RESOURCE);
842 scheduler_->RenameResource(
843 "file:2_file_resource_id",
845 google_apis::test_util::CreateCopyResultCallback(&error));
846 expected_types.insert(TYPE_DOWNLOAD_FILE);
847 scheduler_->DownloadFile(
848 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
849 kDummyDownloadFileSize,
850 temp_dir.path().AppendASCII("whatever.txt"),
851 "file:2_file_resource_id",
852 ClientContext(BACKGROUND),
853 google_apis::test_util::CreateCopyResultCallback(&error, &path),
854 google_apis::GetContentCallback());
856 // The number of jobs queued so far.
857 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
858 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
859 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
860 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE));
861 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
862 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
863 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
864 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
865 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
868 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
869 scheduler_->AddResourceToDirectory(
870 "folder:1_folder_resource_id",
871 "file:2_file_resource_id",
872 google_apis::test_util::CreateCopyResultCallback(&error));
873 expected_types.insert(TYPE_COPY_RESOURCE);
874 scheduler_->CopyResource(
875 "document:5_document_resource_id",
876 fake_drive_service_->GetRootResourceId(),
878 base::Time(), // last_modified
879 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
881 // 6 jobs in total were queued.
882 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
883 EXPECT_EQ(6U, jobs.size());
884 std::set<JobType> actual_types;
885 std::set<JobID> job_ids;
886 for (size_t i = 0; i < jobs.size(); ++i) {
887 actual_types.insert(jobs[i].job_type);
888 job_ids.insert(jobs[i].job_id);
890 EXPECT_EQ(expected_types, actual_types);
891 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
892 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
893 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE));
894 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
895 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
898 base::RunLoop().RunUntilIdle();
900 // All jobs except the BACKGROUND job should have started running (UPDATED)
901 // and then finished (DONE).
902 jobs = scheduler_->GetJobInfoList();
903 ASSERT_EQ(1U, jobs.size());
904 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
906 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
907 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
908 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE));
909 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
910 TYPE_ADD_RESOURCE_TO_DIRECTORY));
911 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE));
912 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
914 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
915 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
916 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
917 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
918 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
919 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
921 // Run the background downloading job as well.
923 base::RunLoop().RunUntilIdle();
925 // All jobs should have finished.
926 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
927 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
928 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
931 TEST_F(JobSchedulerTest, JobInfoProgress) {
932 JobListLogger logger;
933 scheduler_->AddObserver(&logger);
937 base::ScopedTempDir temp_dir;
938 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
940 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
944 scheduler_->DownloadFile(
945 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
946 kDummyDownloadFileSize,
947 temp_dir.path().AppendASCII("whatever.txt"),
948 "file:2_file_resource_id",
949 ClientContext(BACKGROUND),
950 google_apis::test_util::CreateCopyResultCallback(&error, &path),
951 google_apis::GetContentCallback());
952 base::RunLoop().RunUntilIdle();
954 std::vector<int64> download_progress;
955 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
956 ASSERT_TRUE(!download_progress.empty());
957 EXPECT_TRUE(base::STLIsSorted(download_progress));
958 EXPECT_GE(download_progress.front(), 0);
959 EXPECT_LE(download_progress.back(), 26);
962 path = temp_dir.path().AppendASCII("new_file.txt");
963 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
964 google_apis::GDataErrorCode upload_error =
965 google_apis::GDATA_OTHER_ERROR;
966 scoped_ptr<google_apis::ResourceEntry> entry;
968 scheduler_->UploadNewFile(
969 fake_drive_service_->GetRootResourceId(),
970 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
974 ClientContext(BACKGROUND),
975 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
976 base::RunLoop().RunUntilIdle();
978 std::vector<int64> upload_progress;
979 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
980 ASSERT_TRUE(!upload_progress.empty());
981 EXPECT_TRUE(base::STLIsSorted(upload_progress));
982 EXPECT_GE(upload_progress.front(), 0);
983 EXPECT_LE(upload_progress.back(), 13);
986 TEST_F(JobSchedulerTest, CancelPendingJob) {
987 base::ScopedTempDir temp_dir;
988 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
989 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
990 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
992 // To create a pending job for testing, set the mode to cellular connection
993 // and issue BACKGROUND jobs.
995 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
997 // Start the first job and record its job ID.
998 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
999 scoped_ptr<google_apis::ResourceEntry> entry;
1000 scheduler_->UploadNewFile(
1001 fake_drive_service_->GetRootResourceId(),
1002 base::FilePath::FromUTF8Unsafe("dummy/path"),
1006 ClientContext(BACKGROUND),
1007 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1009 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1010 ASSERT_EQ(1u, jobs.size());
1011 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet.
1012 JobID first_job_id = jobs[0].job_id;
1014 // Start the second job.
1015 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1016 scheduler_->UploadNewFile(
1017 fake_drive_service_->GetRootResourceId(),
1018 base::FilePath::FromUTF8Unsafe("dummy/path"),
1022 ClientContext(BACKGROUND),
1023 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1025 // Cancel the first one.
1026 scheduler_->CancelJob(first_job_id);
1028 // Only the first job should be cancelled.
1030 base::RunLoop().RunUntilIdle();
1031 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1032 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1033 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1036 TEST_F(JobSchedulerTest, CancelRunningJob) {
1039 base::ScopedTempDir temp_dir;
1040 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1041 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
1042 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
1044 // Run as a cancelable task.
1045 fake_drive_service_->set_upload_new_file_cancelable(true);
1046 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
1047 scoped_ptr<google_apis::ResourceEntry> entry;
1048 scheduler_->UploadNewFile(
1049 fake_drive_service_->GetRootResourceId(),
1050 base::FilePath::FromUTF8Unsafe("dummy/path"),
1054 ClientContext(USER_INITIATED),
1055 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1057 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1058 ASSERT_EQ(1u, jobs.size());
1059 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running.
1060 JobID first_job_id = jobs[0].job_id;
1062 // Start the second job normally.
1063 fake_drive_service_->set_upload_new_file_cancelable(false);
1064 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1065 scheduler_->UploadNewFile(
1066 fake_drive_service_->GetRootResourceId(),
1067 base::FilePath::FromUTF8Unsafe("dummy/path"),
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