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/browser/google_apis/drive_api_parser.h"
19 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
20 #include "chrome/browser/google_apis/test_util.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/public/test/test_browser_thread_bundle.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 google_apis::InitiateUploadCallback& callback) OVERRIDE {
109 if (upload_new_file_cancelable_)
110 return base::Bind(callback, google_apis::GDATA_CANCELLED, GURL());
112 return FakeDriveService::InitiateUploadNewFile(content_type,
120 bool upload_new_file_cancelable_;
125 class JobSchedulerTest : public testing::Test {
128 : pref_service_(new TestingPrefServiceSimple) {
129 test_util::RegisterDrivePrefs(pref_service_->registry());
132 virtual void SetUp() OVERRIDE {
133 fake_network_change_notifier_.reset(
134 new test_util::FakeNetworkChangeNotifier);
136 fake_drive_service_.reset(new CancelTestableFakeDriveService);
137 fake_drive_service_->LoadResourceListForWapi(
138 "gdata/root_feed.json");
139 fake_drive_service_->LoadAccountMetadataForWapi(
140 "gdata/account_metadata.json");
141 fake_drive_service_->LoadAppListForDriveApi(
142 "drive/applist.json");
144 scheduler_.reset(new JobScheduler(pref_service_.get(),
145 fake_drive_service_.get(),
146 base::MessageLoopProxy::current().get()));
147 scheduler_->SetDisableThrottling(true);
151 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
152 // the specified connection type.
153 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
154 fake_network_change_notifier_->SetConnectionType(type);
157 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
158 void ConnectToWifi() {
159 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
162 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
163 void ConnectToCellular() {
164 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
167 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
168 void ConnectToWimax() {
169 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
172 // Sets up FakeNetworkChangeNotifier as if it's disconnected.
173 void ConnectToNone() {
174 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
177 static int GetMetadataQueueMaxJobCount() {
178 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
181 content::TestBrowserThreadBundle thread_bundle_;
182 scoped_ptr<TestingPrefServiceSimple> pref_service_;
183 scoped_ptr<test_util::FakeNetworkChangeNotifier>
184 fake_network_change_notifier_;
185 scoped_ptr<CancelTestableFakeDriveService> fake_drive_service_;
186 scoped_ptr<JobScheduler> scheduler_;
189 TEST_F(JobSchedulerTest, GetAboutResource) {
192 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
193 scoped_ptr<google_apis::AboutResource> about_resource;
194 scheduler_->GetAboutResource(
195 google_apis::test_util::CreateCopyResultCallback(
196 &error, &about_resource));
197 base::RunLoop().RunUntilIdle();
198 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
199 ASSERT_TRUE(about_resource);
202 TEST_F(JobSchedulerTest, GetAppList) {
205 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
206 scoped_ptr<google_apis::AppList> app_list;
208 scheduler_->GetAppList(
209 google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
210 base::RunLoop().RunUntilIdle();
212 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
213 ASSERT_TRUE(app_list);
216 TEST_F(JobSchedulerTest, GetAllResourceList) {
219 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
220 scoped_ptr<google_apis::ResourceList> resource_list;
222 scheduler_->GetAllResourceList(
223 google_apis::test_util::CreateCopyResultCallback(
224 &error, &resource_list));
225 base::RunLoop().RunUntilIdle();
227 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
228 ASSERT_TRUE(resource_list);
231 TEST_F(JobSchedulerTest, GetResourceListInDirectory) {
234 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
235 scoped_ptr<google_apis::ResourceList> resource_list;
237 scheduler_->GetResourceListInDirectory(
238 fake_drive_service_->GetRootResourceId(),
239 google_apis::test_util::CreateCopyResultCallback(
240 &error, &resource_list));
241 base::RunLoop().RunUntilIdle();
243 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
244 ASSERT_TRUE(resource_list);
247 TEST_F(JobSchedulerTest, Search) {
250 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
251 scoped_ptr<google_apis::ResourceList> resource_list;
254 "File", // search query
255 google_apis::test_util::CreateCopyResultCallback(
256 &error, &resource_list));
257 base::RunLoop().RunUntilIdle();
259 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
260 ASSERT_TRUE(resource_list);
263 TEST_F(JobSchedulerTest, GetChangeList) {
266 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
268 // Create a new directory.
269 // The loaded (initial) changestamp is 654321. Thus, by this operation,
270 // it should become 654322.
272 scoped_ptr<google_apis::ResourceEntry> resource_entry;
273 fake_drive_service_->AddNewDirectory(
274 fake_drive_service_->GetRootResourceId(),
276 google_apis::test_util::CreateCopyResultCallback(
277 &error, &resource_entry));
278 base::RunLoop().RunUntilIdle();
279 ASSERT_EQ(google_apis::HTTP_CREATED, error);
282 error = google_apis::GDATA_OTHER_ERROR;
283 scoped_ptr<google_apis::ResourceList> resource_list;
284 scheduler_->GetChangeList(
285 654321 + 1, // start_changestamp
286 google_apis::test_util::CreateCopyResultCallback(
287 &error, &resource_list));
288 base::RunLoop().RunUntilIdle();
290 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
291 ASSERT_TRUE(resource_list);
294 TEST_F(JobSchedulerTest, GetRemainingChangeList) {
296 fake_drive_service_->set_default_max_results(2);
298 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
299 scoped_ptr<google_apis::ResourceList> resource_list;
301 scheduler_->GetAllResourceList(
302 google_apis::test_util::CreateCopyResultCallback(
303 &error, &resource_list));
304 base::RunLoop().RunUntilIdle();
306 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
307 ASSERT_TRUE(resource_list);
309 const google_apis::Link* next_link =
310 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
311 ASSERT_TRUE(next_link);
312 // Keep the next url before releasing the |resource_list|.
313 GURL next_url(next_link->href());
315 error = google_apis::GDATA_OTHER_ERROR;
316 resource_list.reset();
318 scheduler_->GetRemainingChangeList(
320 google_apis::test_util::CreateCopyResultCallback(
321 &error, &resource_list));
322 base::RunLoop().RunUntilIdle();
324 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
325 ASSERT_TRUE(resource_list);
328 TEST_F(JobSchedulerTest, GetRemainingFileList) {
330 fake_drive_service_->set_default_max_results(2);
332 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
333 scoped_ptr<google_apis::ResourceList> resource_list;
335 scheduler_->GetResourceListInDirectory(
336 fake_drive_service_->GetRootResourceId(),
337 google_apis::test_util::CreateCopyResultCallback(
338 &error, &resource_list));
339 base::RunLoop().RunUntilIdle();
341 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
342 ASSERT_TRUE(resource_list);
344 const google_apis::Link* next_link =
345 resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
346 ASSERT_TRUE(next_link);
347 // Keep the next url before releasing the |resource_list|.
348 GURL next_url(next_link->href());
350 error = google_apis::GDATA_OTHER_ERROR;
351 resource_list.reset();
353 scheduler_->GetRemainingFileList(
355 google_apis::test_util::CreateCopyResultCallback(
356 &error, &resource_list));
357 base::RunLoop().RunUntilIdle();
359 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
360 ASSERT_TRUE(resource_list);
363 TEST_F(JobSchedulerTest, GetShareUrl) {
366 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
369 scheduler_->GetShareUrl(
370 "file:2_file_resource_id", // resource ID
371 GURL("chrome-extension://test-id/"), // embed origin
372 ClientContext(USER_INITIATED),
373 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
374 base::RunLoop().RunUntilIdle();
376 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
377 ASSERT_FALSE(share_url.is_empty());
380 TEST_F(JobSchedulerTest, DeleteResource) {
383 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
385 scheduler_->DeleteResource(
386 "file:2_file_resource_id",
387 google_apis::test_util::CreateCopyResultCallback(&error));
388 base::RunLoop().RunUntilIdle();
390 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
393 TEST_F(JobSchedulerTest, CopyResource) {
396 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
397 scoped_ptr<google_apis::ResourceEntry> entry;
399 scheduler_->CopyResource(
400 "file:2_file_resource_id", // resource ID
401 "folder:1_folder_resource_id", // parent resource ID
402 "New Document", // new title
404 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
405 base::RunLoop().RunUntilIdle();
407 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
411 TEST_F(JobSchedulerTest, CopyHostedDocument) {
414 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
415 scoped_ptr<google_apis::ResourceEntry> entry;
417 scheduler_->CopyHostedDocument(
418 "document:5_document_resource_id", // resource ID
419 "New Document", // new title
420 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
421 base::RunLoop().RunUntilIdle();
423 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
427 TEST_F(JobSchedulerTest, MoveResource) {
430 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
431 scoped_ptr<google_apis::ResourceEntry> entry;
433 scheduler_->MoveResource(
434 "file:2_file_resource_id", // resource ID
435 "folder:1_folder_resource_id", // parent resource ID
436 "New Document", // new title
438 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
439 base::RunLoop().RunUntilIdle();
441 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
445 TEST_F(JobSchedulerTest, RenameResource) {
448 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
450 scheduler_->RenameResource(
451 "file:2_file_resource_id",
453 google_apis::test_util::CreateCopyResultCallback(&error));
454 base::RunLoop().RunUntilIdle();
456 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
459 TEST_F(JobSchedulerTest, AddResourceToDirectory) {
462 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
464 scheduler_->AddResourceToDirectory(
465 "folder:1_folder_resource_id",
466 "file:2_file_resource_id",
467 google_apis::test_util::CreateCopyResultCallback(&error));
468 base::RunLoop().RunUntilIdle();
470 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
473 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
476 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
478 scheduler_->RemoveResourceFromDirectory(
479 "folder:1_folder_resource_id",
480 "file:subdirectory_file_1_id", // resource ID
481 google_apis::test_util::CreateCopyResultCallback(&error));
482 base::RunLoop().RunUntilIdle();
484 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
487 TEST_F(JobSchedulerTest, AddNewDirectory) {
490 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
491 scoped_ptr<google_apis::ResourceEntry> entry;
493 scheduler_->AddNewDirectory(
494 fake_drive_service_->GetRootResourceId(), // Root directory.
496 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
497 base::RunLoop().RunUntilIdle();
499 ASSERT_EQ(google_apis::HTTP_CREATED, error);
503 TEST_F(JobSchedulerTest, PriorityHandling) {
504 const base::FilePath kDummyFilePath(FILE_PATH_LITERAL("dummy"));
506 // Saturate the metadata job queue with uninteresting jobs to prevent
507 // following jobs from starting.
508 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
509 scoped_ptr<google_apis::ResourceEntry> entry_dontcare;
510 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
511 scheduler_->CreateFile(
512 fake_drive_service_->GetRootResourceId(),
514 base::StringPrintf("uninteresting file %d", i),
516 ClientContext(USER_INITIATED),
517 google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
521 // Start jobs with different priorities.
522 std::string title_1("new file 1");
523 std::string title_2("new file 2");
524 std::string title_3("new file 3");
525 std::string title_4("new file 4");
526 std::vector<std::string> titles;
528 scheduler_->CreateFile(
529 fake_drive_service_->GetRootResourceId(),
533 ClientContext(USER_INITIATED),
534 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
535 scheduler_->CreateFile(
536 fake_drive_service_->GetRootResourceId(),
540 ClientContext(BACKGROUND),
541 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
542 scheduler_->CreateFile(
543 fake_drive_service_->GetRootResourceId(),
547 ClientContext(BACKGROUND),
548 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
549 scheduler_->CreateFile(
550 fake_drive_service_->GetRootResourceId(),
554 ClientContext(USER_INITIATED),
555 base::Bind(&CopyTitleFromGetResourceEntryCallback, &titles));
557 base::RunLoop().RunUntilIdle();
559 ASSERT_EQ(4ul, titles.size());
560 EXPECT_EQ(title_1, titles[0]);
561 EXPECT_EQ(title_4, titles[1]);
562 EXPECT_EQ(title_2, titles[2]);
563 EXPECT_EQ(title_3, titles[3]);
566 TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
569 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
570 scoped_ptr<google_apis::ResourceEntry> entry;
571 scheduler_->CreateFile(
572 fake_drive_service_->GetRootResourceId(),
573 base::FilePath(FILE_PATH_LITERAL("dummy")),
576 ClientContext(USER_INITIATED),
577 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
578 base::RunLoop().RunUntilIdle();
580 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
583 TEST_F(JobSchedulerTest, NoConnectionBackground) {
586 std::string resource_id("file:2_file_resource_id");
588 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
589 scoped_ptr<google_apis::ResourceEntry> entry;
590 scheduler_->CreateFile(
591 fake_drive_service_->GetRootResourceId(),
592 base::FilePath(FILE_PATH_LITERAL("dummy")),
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);
608 EXPECT_EQ("title", entry->title());
611 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
614 // Disable fetching over cellular network.
615 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
617 // Try to get a file in the background
618 base::ScopedTempDir temp_dir;
619 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
621 const base::FilePath kOutputFilePath =
622 temp_dir.path().AppendASCII("whatever.txt");
623 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
624 base::FilePath output_file_path;
625 scheduler_->DownloadFile(
626 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
627 kDummyDownloadFileSize,
629 "file:2_file_resource_id",
630 ClientContext(BACKGROUND),
631 google_apis::test_util::CreateCopyResultCallback(
632 &download_error, &output_file_path),
633 google_apis::GetContentCallback());
634 // Metadata should still work
635 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
636 scoped_ptr<google_apis::AboutResource> about_resource;
638 // Try to get the metadata
639 scheduler_->GetAboutResource(
640 google_apis::test_util::CreateCopyResultCallback(
641 &metadata_error, &about_resource));
642 base::RunLoop().RunUntilIdle();
644 // Check the metadata
645 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
646 ASSERT_TRUE(about_resource);
648 // Check the download
649 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
651 // Switch to a Wifi connection
654 base::RunLoop().RunUntilIdle();
656 // Check the download again
657 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
659 EXPECT_EQ(output_file_path, kOutputFilePath);
660 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
661 EXPECT_EQ("This is some test content.", content);
664 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
667 // Disable fetching over cellular network.
668 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
670 // Try to get a file in the background
671 base::ScopedTempDir temp_dir;
672 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
674 const base::FilePath kOutputFilePath =
675 temp_dir.path().AppendASCII("whatever.txt");
676 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
677 base::FilePath output_file_path;
678 scheduler_->DownloadFile(
679 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
680 kDummyDownloadFileSize,
682 "file:2_file_resource_id",
683 ClientContext(BACKGROUND),
684 google_apis::test_util::CreateCopyResultCallback(
685 &download_error, &output_file_path),
686 google_apis::GetContentCallback());
687 // Metadata should still work
688 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
689 scoped_ptr<google_apis::AboutResource> about_resource;
691 // Try to get the metadata
692 scheduler_->GetAboutResource(
693 google_apis::test_util::CreateCopyResultCallback(
694 &metadata_error, &about_resource));
695 base::RunLoop().RunUntilIdle();
697 // Check the metadata
698 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
699 ASSERT_TRUE(about_resource);
701 // Check the download
702 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
704 // Switch to a Wifi connection
707 base::RunLoop().RunUntilIdle();
709 // Check the download again
710 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
712 EXPECT_EQ(output_file_path, kOutputFilePath);
713 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
714 EXPECT_EQ("This is some test content.", content);
717 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
720 // Enable fetching over cellular network.
721 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
723 // Try to get a file in the background
724 base::ScopedTempDir temp_dir;
725 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
727 const base::FilePath kOutputFilePath =
728 temp_dir.path().AppendASCII("whatever.txt");
729 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
730 base::FilePath output_file_path;
731 scheduler_->DownloadFile(
732 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
733 kDummyDownloadFileSize,
735 "file:2_file_resource_id",
736 ClientContext(BACKGROUND),
737 google_apis::test_util::CreateCopyResultCallback(
738 &download_error, &output_file_path),
739 google_apis::GetContentCallback());
740 // Metadata should still work
741 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
742 scoped_ptr<google_apis::AboutResource> about_resource;
744 // Try to get the metadata
745 scheduler_->GetAboutResource(
746 google_apis::test_util::CreateCopyResultCallback(
747 &metadata_error, &about_resource));
748 base::RunLoop().RunUntilIdle();
750 // Check the metadata
751 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
752 ASSERT_TRUE(about_resource);
754 // Check the download
755 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
757 EXPECT_EQ(output_file_path, kOutputFilePath);
758 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
759 EXPECT_EQ("This is some test content.", content);
762 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
765 // Enable fetching over cellular network.
766 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
768 // Try to get a file in the background
769 base::ScopedTempDir temp_dir;
770 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
772 const base::FilePath kOutputFilePath =
773 temp_dir.path().AppendASCII("whatever.txt");
774 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
775 base::FilePath output_file_path;
776 scheduler_->DownloadFile(
777 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
778 kDummyDownloadFileSize,
780 "file:2_file_resource_id",
781 ClientContext(BACKGROUND),
782 google_apis::test_util::CreateCopyResultCallback(
783 &download_error, &output_file_path),
784 google_apis::GetContentCallback());
785 // Metadata should still work
786 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
787 scoped_ptr<google_apis::AboutResource> about_resource;
789 // Try to get the metadata
790 scheduler_->GetAboutResource(
791 google_apis::test_util::CreateCopyResultCallback(
792 &metadata_error, &about_resource));
793 base::RunLoop().RunUntilIdle();
795 // Check the metadata
796 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
797 ASSERT_TRUE(about_resource);
799 // Check the download
800 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
802 EXPECT_EQ(output_file_path, kOutputFilePath);
803 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
804 EXPECT_EQ("This is some test content.", content);
807 TEST_F(JobSchedulerTest, JobInfo) {
808 JobListLogger logger;
809 scheduler_->AddObserver(&logger);
811 // Disable background upload/download.
813 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
815 base::ScopedTempDir temp_dir;
816 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
818 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
819 scoped_ptr<google_apis::ResourceEntry> entry;
820 scoped_ptr<google_apis::AboutResource> about_resource;
823 std::set<JobType> expected_types;
826 expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
827 scheduler_->AddNewDirectory(
828 fake_drive_service_->GetRootResourceId(),
830 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
831 expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
832 scheduler_->GetAboutResource(
833 google_apis::test_util::CreateCopyResultCallback(
834 &error, &about_resource));
835 expected_types.insert(TYPE_RENAME_RESOURCE);
836 scheduler_->RenameResource(
837 "file:2_file_resource_id",
839 google_apis::test_util::CreateCopyResultCallback(&error));
840 expected_types.insert(TYPE_DOWNLOAD_FILE);
841 scheduler_->DownloadFile(
842 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
843 kDummyDownloadFileSize,
844 temp_dir.path().AppendASCII("whatever.txt"),
845 "file:2_file_resource_id",
846 ClientContext(BACKGROUND),
847 google_apis::test_util::CreateCopyResultCallback(&error, &path),
848 google_apis::GetContentCallback());
850 // The number of jobs queued so far.
851 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
852 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
853 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
854 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE));
855 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
856 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
857 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
858 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
859 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
862 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
863 scheduler_->AddResourceToDirectory(
864 "folder:1_folder_resource_id",
865 "file:2_file_resource_id",
866 google_apis::test_util::CreateCopyResultCallback(&error));
867 expected_types.insert(TYPE_COPY_HOSTED_DOCUMENT);
868 scheduler_->CopyHostedDocument(
869 "document:5_document_resource_id",
871 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
873 // 6 jobs in total were queued.
874 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
875 EXPECT_EQ(6U, jobs.size());
876 std::set<JobType> actual_types;
877 std::set<JobID> job_ids;
878 for (size_t i = 0; i < jobs.size(); ++i) {
879 actual_types.insert(jobs[i].job_type);
880 job_ids.insert(jobs[i].job_id);
882 EXPECT_EQ(expected_types, actual_types);
883 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
884 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
885 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_HOSTED_DOCUMENT));
886 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
887 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT));
890 base::RunLoop().RunUntilIdle();
892 // All jobs except the BACKGROUND job should have started running (UPDATED)
893 // and then finished (DONE).
894 jobs = scheduler_->GetJobInfoList();
895 ASSERT_EQ(1U, jobs.size());
896 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
898 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
899 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
900 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE));
901 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
902 TYPE_ADD_RESOURCE_TO_DIRECTORY));
903 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_HOSTED_DOCUMENT));
904 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
906 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
907 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
908 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
909 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
910 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT));
911 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
913 // Run the background downloading job as well.
915 base::RunLoop().RunUntilIdle();
917 // All jobs should have finished.
918 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
919 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
920 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
923 TEST_F(JobSchedulerTest, JobInfoProgress) {
924 JobListLogger logger;
925 scheduler_->AddObserver(&logger);
929 base::ScopedTempDir temp_dir;
930 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
932 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
936 scheduler_->DownloadFile(
937 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
938 kDummyDownloadFileSize,
939 temp_dir.path().AppendASCII("whatever.txt"),
940 "file:2_file_resource_id",
941 ClientContext(BACKGROUND),
942 google_apis::test_util::CreateCopyResultCallback(&error, &path),
943 google_apis::GetContentCallback());
944 base::RunLoop().RunUntilIdle();
946 std::vector<int64> download_progress;
947 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
948 ASSERT_TRUE(!download_progress.empty());
949 EXPECT_TRUE(base::STLIsSorted(download_progress));
950 EXPECT_GE(download_progress.front(), 0);
951 EXPECT_LE(download_progress.back(), 26);
954 path = temp_dir.path().AppendASCII("new_file.txt");
955 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
956 google_apis::GDataErrorCode upload_error =
957 google_apis::GDATA_OTHER_ERROR;
958 scoped_ptr<google_apis::ResourceEntry> entry;
960 scheduler_->UploadNewFile(
961 fake_drive_service_->GetRootResourceId(),
962 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
966 ClientContext(BACKGROUND),
967 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
968 base::RunLoop().RunUntilIdle();
970 std::vector<int64> upload_progress;
971 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
972 ASSERT_TRUE(!upload_progress.empty());
973 EXPECT_TRUE(base::STLIsSorted(upload_progress));
974 EXPECT_GE(upload_progress.front(), 0);
975 EXPECT_LE(upload_progress.back(), 13);
978 TEST_F(JobSchedulerTest, CancelPendingJob) {
979 base::ScopedTempDir temp_dir;
980 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
981 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
982 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
984 // To create a pending job for testing, set the mode to cellular connection
985 // and issue BACKGROUND jobs.
987 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
989 // Start the first job and record its job ID.
990 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
991 scoped_ptr<google_apis::ResourceEntry> entry;
992 scheduler_->UploadNewFile(
993 fake_drive_service_->GetRootResourceId(),
994 base::FilePath::FromUTF8Unsafe("dummy/path"),
998 ClientContext(BACKGROUND),
999 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1001 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1002 ASSERT_EQ(1u, jobs.size());
1003 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet.
1004 JobID first_job_id = jobs[0].job_id;
1006 // Start the second job.
1007 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1008 scheduler_->UploadNewFile(
1009 fake_drive_service_->GetRootResourceId(),
1010 base::FilePath::FromUTF8Unsafe("dummy/path"),
1014 ClientContext(BACKGROUND),
1015 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1017 // Cancel the first one.
1018 scheduler_->CancelJob(first_job_id);
1020 // Only the first job should be cancelled.
1022 base::RunLoop().RunUntilIdle();
1023 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1024 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1025 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1028 TEST_F(JobSchedulerTest, CancelRunningJob) {
1031 base::ScopedTempDir temp_dir;
1032 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1033 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
1034 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
1036 // Run as a cancelable task.
1037 fake_drive_service_->set_upload_new_file_cancelable(true);
1038 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
1039 scoped_ptr<google_apis::ResourceEntry> entry;
1040 scheduler_->UploadNewFile(
1041 fake_drive_service_->GetRootResourceId(),
1042 base::FilePath::FromUTF8Unsafe("dummy/path"),
1046 ClientContext(USER_INITIATED),
1047 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1049 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1050 ASSERT_EQ(1u, jobs.size());
1051 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running.
1052 JobID first_job_id = jobs[0].job_id;
1054 // Start the second job normally.
1055 fake_drive_service_->set_upload_new_file_cancelable(false);
1056 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1057 scheduler_->UploadNewFile(
1058 fake_drive_service_->GetRootResourceId(),
1059 base::FilePath::FromUTF8Unsafe("dummy/path"),
1063 ClientContext(USER_INITIATED),
1064 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1066 // Cancel the first one.
1067 scheduler_->CancelJob(first_job_id);
1069 // Only the first job should be cancelled.
1070 base::RunLoop().RunUntilIdle();
1071 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1072 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1073 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1076 } // namespace drive