Ensure low-memory renderers retry failed loads correctly.
[chromium-blink-merge.git] / components / drive / job_scheduler_unittest.cc
blob9ce647925db023d1079f384aa59e4e7a5f2517cf
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 "components/drive/job_scheduler.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/stl_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "components/drive/drive_pref_names.h"
19 #include "components/drive/drive_test_util.h"
20 #include "components/drive/event_logger.h"
21 #include "components/drive/service/fake_drive_service.h"
22 #include "components/drive/service/test_util.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "google_apis/drive/drive_api_parser.h"
25 #include "google_apis/drive/test_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace drive {
30 namespace {
32 // Dummy value passed for the |expected_file_size| parameter of DownloadFile().
33 const int64 kDummyDownloadFileSize = 0;
35 void CopyTitleFromFileResourceCallback(
36 std::vector<std::string>* title_list_out,
37 google_apis::DriveApiErrorCode error_in,
38 scoped_ptr<google_apis::FileResource> entry_in) {
39 title_list_out->push_back(entry_in->title());
42 class JobListLogger : public JobListObserver {
43 public:
44 enum EventType {
45 ADDED,
46 UPDATED,
47 DONE,
50 struct EventLog {
51 EventType type;
52 JobInfo info;
54 EventLog(EventType type, const JobInfo& info) : type(type), info(info) {
58 // Checks whether the specified type of event has occurred.
59 bool Has(EventType type, JobType job_type) {
60 for (size_t i = 0; i < events.size(); ++i) {
61 if (events[i].type == type && events[i].info.job_type == job_type)
62 return true;
64 return false;
67 // Gets the progress event information of the specified type.
68 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) {
69 for (size_t i = 0; i < events.size(); ++i) {
70 if (events[i].type == UPDATED && events[i].info.job_type == job_type)
71 progress->push_back(events[i].info.num_completed_bytes);
75 // JobListObserver overrides.
76 void OnJobAdded(const JobInfo& info) override {
77 events.push_back(EventLog(ADDED, info));
80 void OnJobUpdated(const JobInfo& info) override {
81 events.push_back(EventLog(UPDATED, info));
84 void OnJobDone(const JobInfo& info, FileError error) override {
85 events.push_back(EventLog(DONE, info));
88 private:
89 std::vector<EventLog> events;
92 // Fake drive service extended for testing cancellation.
93 // When upload_new_file_cancelable is set, this Drive service starts
94 // returning a closure to cancel from InitiateUploadNewFile(). The task will
95 // finish only when the cancel closure is called.
96 class CancelTestableFakeDriveService : public FakeDriveService {
97 public:
98 CancelTestableFakeDriveService()
99 : upload_new_file_cancelable_(false) {
102 void set_upload_new_file_cancelable(bool cancelable) {
103 upload_new_file_cancelable_ = cancelable;
106 google_apis::CancelCallback InitiateUploadNewFile(
107 const std::string& content_type,
108 int64 content_length,
109 const std::string& parent_resource_id,
110 const std::string& title,
111 const UploadNewFileOptions& options,
112 const google_apis::InitiateUploadCallback& callback) override {
113 if (upload_new_file_cancelable_)
114 return base::Bind(callback, google_apis::DRIVE_CANCELLED, GURL());
116 return FakeDriveService::InitiateUploadNewFile(content_type,
117 content_length,
118 parent_resource_id,
119 title,
120 options,
121 callback);
124 private:
125 bool upload_new_file_cancelable_;
128 } // namespace
130 class JobSchedulerTest : public testing::Test {
131 public:
132 JobSchedulerTest()
133 : pref_service_(new TestingPrefServiceSimple) {
134 test_util::RegisterDrivePrefs(pref_service_->registry());
137 void SetUp() override {
138 fake_network_change_notifier_.reset(
139 new test_util::FakeNetworkChangeNotifier);
141 logger_.reset(new EventLogger);
143 fake_drive_service_.reset(new CancelTestableFakeDriveService);
144 test_util::SetUpTestEntries(fake_drive_service_.get());
145 fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
147 scheduler_.reset(new JobScheduler(
148 pref_service_.get(),
149 logger_.get(),
150 fake_drive_service_.get(),
151 base::ThreadTaskRunnerHandle::Get().get()));
152 scheduler_->SetDisableThrottling(true);
155 protected:
156 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
157 // the specified connection type.
158 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
159 fake_network_change_notifier_->SetConnectionType(type);
162 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
163 void ConnectToWifi() {
164 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
167 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
168 void ConnectToCellular() {
169 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
172 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
173 void ConnectToWimax() {
174 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
177 // Sets up FakeNetworkChangeNotifier as if it's disconnected.
178 void ConnectToNone() {
179 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
182 static int GetMetadataQueueMaxJobCount() {
183 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
186 content::TestBrowserThreadBundle thread_bundle_;
187 scoped_ptr<TestingPrefServiceSimple> pref_service_;
188 scoped_ptr<test_util::FakeNetworkChangeNotifier>
189 fake_network_change_notifier_;
190 scoped_ptr<EventLogger> logger_;
191 scoped_ptr<CancelTestableFakeDriveService> fake_drive_service_;
192 scoped_ptr<JobScheduler> scheduler_;
195 TEST_F(JobSchedulerTest, GetAboutResource) {
196 ConnectToWifi();
198 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
199 scoped_ptr<google_apis::AboutResource> about_resource;
200 scheduler_->GetAboutResource(
201 google_apis::test_util::CreateCopyResultCallback(
202 &error, &about_resource));
203 base::RunLoop().RunUntilIdle();
204 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
205 ASSERT_TRUE(about_resource);
208 TEST_F(JobSchedulerTest, GetAppList) {
209 ConnectToWifi();
211 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
212 scoped_ptr<google_apis::AppList> app_list;
214 scheduler_->GetAppList(
215 google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
216 base::RunLoop().RunUntilIdle();
218 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
219 ASSERT_TRUE(app_list);
222 TEST_F(JobSchedulerTest, GetAllFileList) {
223 ConnectToWifi();
225 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
226 scoped_ptr<google_apis::FileList> file_list;
228 scheduler_->GetAllFileList(
229 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
230 base::RunLoop().RunUntilIdle();
232 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
233 ASSERT_TRUE(file_list);
236 TEST_F(JobSchedulerTest, GetFileListInDirectory) {
237 ConnectToWifi();
239 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
240 scoped_ptr<google_apis::FileList> file_list;
242 scheduler_->GetFileListInDirectory(
243 fake_drive_service_->GetRootResourceId(),
244 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
245 base::RunLoop().RunUntilIdle();
247 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
248 ASSERT_TRUE(file_list);
251 TEST_F(JobSchedulerTest, Search) {
252 ConnectToWifi();
254 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
255 scoped_ptr<google_apis::FileList> file_list;
257 scheduler_->Search(
258 "File", // search query
259 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
260 base::RunLoop().RunUntilIdle();
262 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
263 ASSERT_TRUE(file_list);
266 TEST_F(JobSchedulerTest, GetChangeList) {
267 ConnectToWifi();
269 int64 old_largest_change_id =
270 fake_drive_service_->about_resource().largest_change_id();
272 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
274 // Create a new directory.
276 scoped_ptr<google_apis::FileResource> entry;
277 fake_drive_service_->AddNewDirectory(
278 fake_drive_service_->GetRootResourceId(), "new directory",
279 AddNewDirectoryOptions(),
280 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
281 base::RunLoop().RunUntilIdle();
282 ASSERT_EQ(google_apis::HTTP_CREATED, error);
285 error = google_apis::DRIVE_OTHER_ERROR;
286 scoped_ptr<google_apis::ChangeList> change_list;
287 scheduler_->GetChangeList(
288 old_largest_change_id + 1,
289 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
290 base::RunLoop().RunUntilIdle();
292 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
293 ASSERT_TRUE(change_list);
296 TEST_F(JobSchedulerTest, GetRemainingChangeList) {
297 ConnectToWifi();
298 fake_drive_service_->set_default_max_results(2);
300 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
301 scoped_ptr<google_apis::ChangeList> change_list;
303 scheduler_->GetChangeList(
305 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
306 base::RunLoop().RunUntilIdle();
308 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
309 ASSERT_TRUE(change_list);
311 // Keep the next url before releasing the |change_list|.
312 GURL next_url(change_list->next_link());
314 error = google_apis::DRIVE_OTHER_ERROR;
315 change_list.reset();
317 scheduler_->GetRemainingChangeList(
318 next_url,
319 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
320 base::RunLoop().RunUntilIdle();
322 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
323 ASSERT_TRUE(change_list);
326 TEST_F(JobSchedulerTest, GetRemainingFileList) {
327 ConnectToWifi();
328 fake_drive_service_->set_default_max_results(2);
330 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
331 scoped_ptr<google_apis::FileList> file_list;
333 scheduler_->GetFileListInDirectory(
334 fake_drive_service_->GetRootResourceId(),
335 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
336 base::RunLoop().RunUntilIdle();
338 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
339 ASSERT_TRUE(file_list);
341 // Keep the next url before releasing the |file_list|.
342 GURL next_url(file_list->next_link());
344 error = google_apis::DRIVE_OTHER_ERROR;
345 file_list.reset();
347 scheduler_->GetRemainingFileList(
348 next_url,
349 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
350 base::RunLoop().RunUntilIdle();
352 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
353 ASSERT_TRUE(file_list);
356 TEST_F(JobSchedulerTest, GetFileResource) {
357 ConnectToWifi();
359 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
360 scoped_ptr<google_apis::FileResource> entry;
362 scheduler_->GetFileResource(
363 "2_file_resource_id", // resource ID
364 ClientContext(USER_INITIATED),
365 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
366 base::RunLoop().RunUntilIdle();
368 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
369 ASSERT_TRUE(entry);
372 TEST_F(JobSchedulerTest, GetShareUrl) {
373 ConnectToWifi();
375 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
376 GURL share_url;
378 scheduler_->GetShareUrl(
379 "2_file_resource_id", // resource ID
380 GURL("chrome-extension://test-id/"), // embed origin
381 ClientContext(USER_INITIATED),
382 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
383 base::RunLoop().RunUntilIdle();
385 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
386 ASSERT_FALSE(share_url.is_empty());
389 TEST_F(JobSchedulerTest, TrashResource) {
390 ConnectToWifi();
392 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
394 scheduler_->TrashResource(
395 "2_file_resource_id",
396 ClientContext(USER_INITIATED),
397 google_apis::test_util::CreateCopyResultCallback(&error));
398 base::RunLoop().RunUntilIdle();
400 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
403 TEST_F(JobSchedulerTest, CopyResource) {
404 ConnectToWifi();
406 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
407 scoped_ptr<google_apis::FileResource> entry;
409 scheduler_->CopyResource(
410 "2_file_resource_id", // resource ID
411 "1_folder_resource_id", // parent resource ID
412 "New Document", // new title
413 base::Time(),
414 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
415 base::RunLoop().RunUntilIdle();
417 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
418 ASSERT_TRUE(entry);
421 TEST_F(JobSchedulerTest, UpdateResource) {
422 ConnectToWifi();
424 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
425 scoped_ptr<google_apis::FileResource> entry;
427 scheduler_->UpdateResource(
428 "2_file_resource_id", // resource ID
429 "1_folder_resource_id", // parent resource ID
430 "New Document", // new title
431 base::Time(), base::Time(), google_apis::drive::Properties(),
432 ClientContext(USER_INITIATED),
433 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
434 base::RunLoop().RunUntilIdle();
436 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
437 ASSERT_TRUE(entry);
440 TEST_F(JobSchedulerTest, AddResourceToDirectory) {
441 ConnectToWifi();
443 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
445 scheduler_->AddResourceToDirectory(
446 "1_folder_resource_id",
447 "2_file_resource_id",
448 google_apis::test_util::CreateCopyResultCallback(&error));
449 base::RunLoop().RunUntilIdle();
451 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
454 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
455 ConnectToWifi();
457 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
459 scheduler_->RemoveResourceFromDirectory(
460 "1_folder_resource_id",
461 "subdirectory_file_1_id", // resource ID
462 ClientContext(USER_INITIATED),
463 google_apis::test_util::CreateCopyResultCallback(&error));
464 base::RunLoop().RunUntilIdle();
466 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error);
469 TEST_F(JobSchedulerTest, AddNewDirectory) {
470 ConnectToWifi();
472 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
473 scoped_ptr<google_apis::FileResource> entry;
475 scheduler_->AddNewDirectory(
476 fake_drive_service_->GetRootResourceId(), // Root directory.
477 "New Directory", AddNewDirectoryOptions(), ClientContext(USER_INITIATED),
478 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
479 base::RunLoop().RunUntilIdle();
481 ASSERT_EQ(google_apis::HTTP_CREATED, error);
482 ASSERT_TRUE(entry);
485 TEST_F(JobSchedulerTest, PriorityHandling) {
486 // Saturate the metadata job queue with uninteresting jobs to prevent
487 // following jobs from starting.
488 google_apis::DriveApiErrorCode error_dontcare =
489 google_apis::DRIVE_OTHER_ERROR;
490 scoped_ptr<google_apis::FileResource> entry_dontcare;
491 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
492 std::string resource_id("2_file_resource_id");
493 scheduler_->GetFileResource(
494 resource_id,
495 ClientContext(USER_INITIATED),
496 google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
497 &entry_dontcare));
500 // Start jobs with different priorities.
501 std::string title_1("new file 1");
502 std::string title_2("new file 2");
503 std::string title_3("new file 3");
504 std::string title_4("new file 4");
505 std::vector<std::string> titles;
507 scheduler_->AddNewDirectory(
508 fake_drive_service_->GetRootResourceId(), title_1,
509 AddNewDirectoryOptions(), ClientContext(USER_INITIATED),
510 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
511 scheduler_->AddNewDirectory(
512 fake_drive_service_->GetRootResourceId(), title_2,
513 AddNewDirectoryOptions(), ClientContext(BACKGROUND),
514 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
515 scheduler_->AddNewDirectory(
516 fake_drive_service_->GetRootResourceId(), title_3,
517 AddNewDirectoryOptions(), ClientContext(BACKGROUND),
518 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
519 scheduler_->AddNewDirectory(
520 fake_drive_service_->GetRootResourceId(), title_4,
521 AddNewDirectoryOptions(), ClientContext(USER_INITIATED),
522 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
524 base::RunLoop().RunUntilIdle();
526 ASSERT_EQ(4ul, titles.size());
527 EXPECT_EQ(title_1, titles[0]);
528 EXPECT_EQ(title_4, titles[1]);
529 EXPECT_EQ(title_2, titles[2]);
530 EXPECT_EQ(title_3, titles[3]);
533 TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
534 ConnectToNone();
536 std::string resource_id("2_file_resource_id");
538 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
539 scoped_ptr<google_apis::FileResource> entry;
540 scheduler_->GetFileResource(
541 resource_id,
542 ClientContext(USER_INITIATED),
543 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
544 base::RunLoop().RunUntilIdle();
546 EXPECT_EQ(google_apis::DRIVE_NO_CONNECTION, error);
549 TEST_F(JobSchedulerTest, NoConnectionBackground) {
550 ConnectToNone();
552 std::string resource_id("2_file_resource_id");
554 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
555 scoped_ptr<google_apis::FileResource> entry;
556 scheduler_->GetFileResource(
557 resource_id,
558 ClientContext(BACKGROUND),
559 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
560 base::RunLoop().RunUntilIdle();
562 EXPECT_FALSE(entry);
564 // Reconnect to the net.
565 ConnectToWifi();
567 base::RunLoop().RunUntilIdle();
569 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
570 ASSERT_TRUE(entry);
573 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
574 ConnectToCellular();
576 // Disable fetching over cellular network.
577 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
579 // Try to get a file in the background
580 base::ScopedTempDir temp_dir;
581 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
583 const base::FilePath kOutputFilePath =
584 temp_dir.path().AppendASCII("whatever.txt");
585 google_apis::DriveApiErrorCode download_error =
586 google_apis::DRIVE_OTHER_ERROR;
587 base::FilePath output_file_path;
588 scheduler_->DownloadFile(
589 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
590 kDummyDownloadFileSize,
591 kOutputFilePath,
592 "2_file_resource_id",
593 ClientContext(BACKGROUND),
594 google_apis::test_util::CreateCopyResultCallback(
595 &download_error, &output_file_path),
596 google_apis::GetContentCallback());
597 // Metadata should still work
598 google_apis::DriveApiErrorCode metadata_error =
599 google_apis::DRIVE_OTHER_ERROR;
600 scoped_ptr<google_apis::AboutResource> about_resource;
602 // Try to get the metadata
603 scheduler_->GetAboutResource(
604 google_apis::test_util::CreateCopyResultCallback(
605 &metadata_error, &about_resource));
606 base::RunLoop().RunUntilIdle();
608 // Check the metadata
609 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
610 ASSERT_TRUE(about_resource);
612 // Check the download
613 EXPECT_EQ(google_apis::DRIVE_OTHER_ERROR, download_error);
615 // Switch to a Wifi connection
616 ConnectToWifi();
618 base::RunLoop().RunUntilIdle();
620 // Check the download again
621 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
622 std::string content;
623 EXPECT_EQ(output_file_path, kOutputFilePath);
624 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
625 EXPECT_EQ("This is some test content.", content);
628 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
629 ConnectToWimax();
631 // Disable fetching over cellular network.
632 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
634 // Try to get a file in the background
635 base::ScopedTempDir temp_dir;
636 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
638 const base::FilePath kOutputFilePath =
639 temp_dir.path().AppendASCII("whatever.txt");
640 google_apis::DriveApiErrorCode download_error =
641 google_apis::DRIVE_OTHER_ERROR;
642 base::FilePath output_file_path;
643 scheduler_->DownloadFile(
644 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
645 kDummyDownloadFileSize,
646 kOutputFilePath,
647 "2_file_resource_id",
648 ClientContext(BACKGROUND),
649 google_apis::test_util::CreateCopyResultCallback(
650 &download_error, &output_file_path),
651 google_apis::GetContentCallback());
652 // Metadata should still work
653 google_apis::DriveApiErrorCode metadata_error =
654 google_apis::DRIVE_OTHER_ERROR;
655 scoped_ptr<google_apis::AboutResource> about_resource;
657 // Try to get the metadata
658 scheduler_->GetAboutResource(
659 google_apis::test_util::CreateCopyResultCallback(
660 &metadata_error, &about_resource));
661 base::RunLoop().RunUntilIdle();
663 // Check the metadata
664 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
665 ASSERT_TRUE(about_resource);
667 // Check the download
668 EXPECT_EQ(google_apis::DRIVE_OTHER_ERROR, download_error);
670 // Switch to a Wifi connection
671 ConnectToWifi();
673 base::RunLoop().RunUntilIdle();
675 // Check the download again
676 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
677 std::string content;
678 EXPECT_EQ(output_file_path, kOutputFilePath);
679 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
680 EXPECT_EQ("This is some test content.", content);
683 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
684 ConnectToCellular();
686 // Enable fetching over cellular network.
687 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
689 // Try to get a file in the background
690 base::ScopedTempDir temp_dir;
691 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
693 const base::FilePath kOutputFilePath =
694 temp_dir.path().AppendASCII("whatever.txt");
695 google_apis::DriveApiErrorCode download_error =
696 google_apis::DRIVE_OTHER_ERROR;
697 base::FilePath output_file_path;
698 scheduler_->DownloadFile(
699 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
700 kDummyDownloadFileSize,
701 kOutputFilePath,
702 "2_file_resource_id",
703 ClientContext(BACKGROUND),
704 google_apis::test_util::CreateCopyResultCallback(
705 &download_error, &output_file_path),
706 google_apis::GetContentCallback());
707 // Metadata should still work
708 google_apis::DriveApiErrorCode metadata_error =
709 google_apis::DRIVE_OTHER_ERROR;
710 scoped_ptr<google_apis::AboutResource> about_resource;
712 // Try to get the metadata
713 scheduler_->GetAboutResource(
714 google_apis::test_util::CreateCopyResultCallback(
715 &metadata_error, &about_resource));
716 base::RunLoop().RunUntilIdle();
718 // Check the metadata
719 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
720 ASSERT_TRUE(about_resource);
722 // Check the download
723 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
724 std::string content;
725 EXPECT_EQ(output_file_path, kOutputFilePath);
726 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
727 EXPECT_EQ("This is some test content.", content);
730 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
731 ConnectToWimax();
733 // Enable fetching over cellular network.
734 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
736 // Try to get a file in the background
737 base::ScopedTempDir temp_dir;
738 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
740 const base::FilePath kOutputFilePath =
741 temp_dir.path().AppendASCII("whatever.txt");
742 google_apis::DriveApiErrorCode download_error =
743 google_apis::DRIVE_OTHER_ERROR;
744 base::FilePath output_file_path;
745 scheduler_->DownloadFile(
746 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
747 kDummyDownloadFileSize,
748 kOutputFilePath,
749 "2_file_resource_id",
750 ClientContext(BACKGROUND),
751 google_apis::test_util::CreateCopyResultCallback(
752 &download_error, &output_file_path),
753 google_apis::GetContentCallback());
754 // Metadata should still work
755 google_apis::DriveApiErrorCode metadata_error =
756 google_apis::DRIVE_OTHER_ERROR;
757 scoped_ptr<google_apis::AboutResource> about_resource;
759 // Try to get the metadata
760 scheduler_->GetAboutResource(
761 google_apis::test_util::CreateCopyResultCallback(
762 &metadata_error, &about_resource));
763 base::RunLoop().RunUntilIdle();
765 // Check the metadata
766 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
767 ASSERT_TRUE(about_resource);
769 // Check the download
770 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
771 std::string content;
772 EXPECT_EQ(output_file_path, kOutputFilePath);
773 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
774 EXPECT_EQ("This is some test content.", content);
777 TEST_F(JobSchedulerTest, JobInfo) {
778 JobListLogger logger;
779 scheduler_->AddObserver(&logger);
781 // Disable background upload/download.
782 ConnectToWimax();
783 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
785 base::ScopedTempDir temp_dir;
786 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
788 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
789 scoped_ptr<google_apis::FileResource> entry;
790 scoped_ptr<google_apis::AboutResource> about_resource;
791 base::FilePath path;
793 std::set<JobType> expected_types;
795 // Add many jobs.
796 expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
797 scheduler_->AddNewDirectory(
798 fake_drive_service_->GetRootResourceId(), "New Directory",
799 AddNewDirectoryOptions(), ClientContext(USER_INITIATED),
800 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
801 expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
802 scheduler_->GetAboutResource(
803 google_apis::test_util::CreateCopyResultCallback(
804 &error, &about_resource));
805 expected_types.insert(TYPE_UPDATE_RESOURCE);
806 scheduler_->UpdateResource(
807 "2_file_resource_id", std::string(), "New Title", base::Time(),
808 base::Time(), google_apis::drive::Properties(),
809 ClientContext(USER_INITIATED),
810 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
811 expected_types.insert(TYPE_DOWNLOAD_FILE);
812 scheduler_->DownloadFile(
813 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
814 kDummyDownloadFileSize,
815 temp_dir.path().AppendASCII("whatever.txt"),
816 "2_file_resource_id",
817 ClientContext(BACKGROUND),
818 google_apis::test_util::CreateCopyResultCallback(&error, &path),
819 google_apis::GetContentCallback());
821 // The number of jobs queued so far.
822 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
823 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
824 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
825 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_UPDATE_RESOURCE));
826 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
827 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
828 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
829 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE));
830 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
832 // Add more jobs.
833 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
834 scheduler_->AddResourceToDirectory(
835 "1_folder_resource_id",
836 "2_file_resource_id",
837 google_apis::test_util::CreateCopyResultCallback(&error));
838 expected_types.insert(TYPE_COPY_RESOURCE);
839 scheduler_->CopyResource(
840 "5_document_resource_id",
841 fake_drive_service_->GetRootResourceId(),
842 "New Document",
843 base::Time(), // last_modified
844 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
846 // 6 jobs in total were queued.
847 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
848 EXPECT_EQ(6U, jobs.size());
849 std::set<JobType> actual_types;
850 std::set<JobID> job_ids;
851 for (size_t i = 0; i < jobs.size(); ++i) {
852 actual_types.insert(jobs[i].job_type);
853 job_ids.insert(jobs[i].job_id);
855 EXPECT_EQ(expected_types, actual_types);
856 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
857 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
858 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE));
859 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
860 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
862 // Run the jobs.
863 base::RunLoop().RunUntilIdle();
865 // All jobs except the BACKGROUND job should have started running (UPDATED)
866 // and then finished (DONE).
867 jobs = scheduler_->GetJobInfoList();
868 ASSERT_EQ(1U, jobs.size());
869 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
871 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
872 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
873 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_UPDATE_RESOURCE));
874 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
875 TYPE_ADD_RESOURCE_TO_DIRECTORY));
876 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE));
877 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
879 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
880 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
881 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE));
882 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
883 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
884 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
886 // Run the background downloading job as well.
887 ConnectToWifi();
888 base::RunLoop().RunUntilIdle();
890 // All jobs should have finished.
891 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
892 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
893 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
896 TEST_F(JobSchedulerTest, JobInfoProgress) {
897 JobListLogger logger;
898 scheduler_->AddObserver(&logger);
900 ConnectToWifi();
902 base::ScopedTempDir temp_dir;
903 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
905 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
906 base::FilePath path;
908 // Download job.
909 scheduler_->DownloadFile(
910 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
911 kDummyDownloadFileSize,
912 temp_dir.path().AppendASCII("whatever.txt"),
913 "2_file_resource_id",
914 ClientContext(BACKGROUND),
915 google_apis::test_util::CreateCopyResultCallback(&error, &path),
916 google_apis::GetContentCallback());
917 base::RunLoop().RunUntilIdle();
919 std::vector<int64> download_progress;
920 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
921 ASSERT_TRUE(!download_progress.empty());
922 EXPECT_TRUE(base::STLIsSorted(download_progress));
923 EXPECT_GE(download_progress.front(), 0);
924 EXPECT_LE(download_progress.back(), 26);
926 // Upload job.
927 path = temp_dir.path().AppendASCII("new_file.txt");
928 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
929 google_apis::DriveApiErrorCode upload_error =
930 google_apis::DRIVE_OTHER_ERROR;
931 scoped_ptr<google_apis::FileResource> entry;
933 scheduler_->UploadNewFile(
934 fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
935 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), path, "dummy title",
936 "plain/plain", UploadNewFileOptions(), ClientContext(BACKGROUND),
937 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
938 base::RunLoop().RunUntilIdle();
940 std::vector<int64> upload_progress;
941 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
942 ASSERT_TRUE(!upload_progress.empty());
943 EXPECT_TRUE(base::STLIsSorted(upload_progress));
944 EXPECT_GE(upload_progress.front(), 0);
945 EXPECT_LE(upload_progress.back(), 13);
948 TEST_F(JobSchedulerTest, CancelPendingJob) {
949 base::ScopedTempDir temp_dir;
950 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
951 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
952 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
954 // To create a pending job for testing, set the mode to cellular connection
955 // and issue BACKGROUND jobs.
956 ConnectToCellular();
957 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
959 // Start the first job and record its job ID.
960 google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR;
961 scoped_ptr<google_apis::FileResource> entry;
962 scheduler_->UploadNewFile(
963 fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
964 base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
965 "dummy title 1", "text/plain", UploadNewFileOptions(),
966 ClientContext(BACKGROUND),
967 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
969 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
970 ASSERT_EQ(1u, jobs.size());
971 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet.
972 JobID first_job_id = jobs[0].job_id;
974 // Start the second job.
975 google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR;
976 scheduler_->UploadNewFile(
977 fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
978 base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
979 "dummy title 2", "text/plain", UploadNewFileOptions(),
980 ClientContext(BACKGROUND),
981 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
983 // Cancel the first one.
984 scheduler_->CancelJob(first_job_id);
986 // Only the first job should be cancelled.
987 ConnectToWifi();
988 base::RunLoop().RunUntilIdle();
989 EXPECT_EQ(google_apis::DRIVE_CANCELLED, error1);
990 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
991 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
994 TEST_F(JobSchedulerTest, CancelRunningJob) {
995 ConnectToWifi();
997 base::ScopedTempDir temp_dir;
998 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
999 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
1000 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
1002 // Run as a cancelable task.
1003 fake_drive_service_->set_upload_new_file_cancelable(true);
1004 google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR;
1005 scoped_ptr<google_apis::FileResource> entry;
1006 scheduler_->UploadNewFile(
1007 fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
1008 base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
1009 "dummy title 1", "text/plain", UploadNewFileOptions(),
1010 ClientContext(USER_INITIATED),
1011 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1013 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1014 ASSERT_EQ(1u, jobs.size());
1015 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running.
1016 JobID first_job_id = jobs[0].job_id;
1018 // Start the second job normally.
1019 fake_drive_service_->set_upload_new_file_cancelable(false);
1020 google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR;
1021 scheduler_->UploadNewFile(
1022 fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
1023 base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
1024 "dummy title 2", "text/plain", UploadNewFileOptions(),
1025 ClientContext(USER_INITIATED),
1026 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1028 // Cancel the first one.
1029 scheduler_->CancelJob(first_job_id);
1031 // Only the first job should be cancelled.
1032 base::RunLoop().RunUntilIdle();
1033 EXPECT_EQ(google_apis::DRIVE_CANCELLED, error1);
1034 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1035 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1038 } // namespace drive