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 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
, GetResourceEntry
) {
366 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
367 scoped_ptr
<google_apis::ResourceEntry
> entry
;
369 scheduler_
->GetResourceEntry(
370 "file:2_file_resource_id", // resource ID
371 ClientContext(USER_INITIATED
),
372 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
373 base::RunLoop().RunUntilIdle();
375 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
379 TEST_F(JobSchedulerTest
, GetShareUrl
) {
382 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
385 scheduler_
->GetShareUrl(
386 "file:2_file_resource_id", // resource ID
387 GURL("chrome-extension://test-id/"), // embed origin
388 ClientContext(USER_INITIATED
),
389 google_apis::test_util::CreateCopyResultCallback(&error
, &share_url
));
390 base::RunLoop().RunUntilIdle();
392 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
393 ASSERT_FALSE(share_url
.is_empty());
396 TEST_F(JobSchedulerTest
, TrashResource
) {
399 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
401 scheduler_
->TrashResource(
402 "file:2_file_resource_id",
403 ClientContext(USER_INITIATED
),
404 google_apis::test_util::CreateCopyResultCallback(&error
));
405 base::RunLoop().RunUntilIdle();
407 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
410 TEST_F(JobSchedulerTest
, CopyResource
) {
413 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
414 scoped_ptr
<google_apis::ResourceEntry
> entry
;
416 scheduler_
->CopyResource(
417 "file:2_file_resource_id", // resource ID
418 "folder:1_folder_resource_id", // parent resource ID
419 "New Document", // new title
421 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
422 base::RunLoop().RunUntilIdle();
424 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
428 TEST_F(JobSchedulerTest
, UpdateResource
) {
431 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
432 scoped_ptr
<google_apis::ResourceEntry
> entry
;
434 scheduler_
->UpdateResource(
435 "file:2_file_resource_id", // resource ID
436 "folder:1_folder_resource_id", // parent resource ID
437 "New Document", // new title
440 ClientContext(USER_INITIATED
),
441 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
442 base::RunLoop().RunUntilIdle();
444 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
448 TEST_F(JobSchedulerTest
, RenameResource
) {
451 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
453 scheduler_
->RenameResource(
454 "file:2_file_resource_id",
456 google_apis::test_util::CreateCopyResultCallback(&error
));
457 base::RunLoop().RunUntilIdle();
459 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
462 TEST_F(JobSchedulerTest
, AddResourceToDirectory
) {
465 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
467 scheduler_
->AddResourceToDirectory(
468 "folder:1_folder_resource_id",
469 "file:2_file_resource_id",
470 google_apis::test_util::CreateCopyResultCallback(&error
));
471 base::RunLoop().RunUntilIdle();
473 ASSERT_EQ(google_apis::HTTP_SUCCESS
, error
);
476 TEST_F(JobSchedulerTest
, RemoveResourceFromDirectory
) {
479 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
481 scheduler_
->RemoveResourceFromDirectory(
482 "folder:1_folder_resource_id",
483 "file:subdirectory_file_1_id", // resource ID
484 ClientContext(USER_INITIATED
),
485 google_apis::test_util::CreateCopyResultCallback(&error
));
486 base::RunLoop().RunUntilIdle();
488 ASSERT_EQ(google_apis::HTTP_NO_CONTENT
, error
);
491 TEST_F(JobSchedulerTest
, AddNewDirectory
) {
494 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
495 scoped_ptr
<google_apis::ResourceEntry
> entry
;
497 scheduler_
->AddNewDirectory(
498 fake_drive_service_
->GetRootResourceId(), // Root directory.
500 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
501 base::RunLoop().RunUntilIdle();
503 ASSERT_EQ(google_apis::HTTP_CREATED
, error
);
507 TEST_F(JobSchedulerTest
, PriorityHandling
) {
508 const base::FilePath
kDummyFilePath(FILE_PATH_LITERAL("dummy"));
510 // Saturate the metadata job queue with uninteresting jobs to prevent
511 // following jobs from starting.
512 google_apis::GDataErrorCode error_dontcare
= google_apis::GDATA_OTHER_ERROR
;
513 scoped_ptr
<google_apis::ResourceEntry
> entry_dontcare
;
514 for (int i
= 0; i
< GetMetadataQueueMaxJobCount(); ++i
) {
515 scheduler_
->CreateFile(
516 fake_drive_service_
->GetRootResourceId(),
518 base::StringPrintf("uninteresting file %d", i
),
520 ClientContext(USER_INITIATED
),
521 google_apis::test_util::CreateCopyResultCallback(&error_dontcare
,
525 // Start jobs with different priorities.
526 std::string
title_1("new file 1");
527 std::string
title_2("new file 2");
528 std::string
title_3("new file 3");
529 std::string
title_4("new file 4");
530 std::vector
<std::string
> titles
;
532 scheduler_
->CreateFile(
533 fake_drive_service_
->GetRootResourceId(),
537 ClientContext(USER_INITIATED
),
538 base::Bind(&CopyTitleFromGetResourceEntryCallback
, &titles
));
539 scheduler_
->CreateFile(
540 fake_drive_service_
->GetRootResourceId(),
544 ClientContext(BACKGROUND
),
545 base::Bind(&CopyTitleFromGetResourceEntryCallback
, &titles
));
546 scheduler_
->CreateFile(
547 fake_drive_service_
->GetRootResourceId(),
551 ClientContext(BACKGROUND
),
552 base::Bind(&CopyTitleFromGetResourceEntryCallback
, &titles
));
553 scheduler_
->CreateFile(
554 fake_drive_service_
->GetRootResourceId(),
558 ClientContext(USER_INITIATED
),
559 base::Bind(&CopyTitleFromGetResourceEntryCallback
, &titles
));
561 base::RunLoop().RunUntilIdle();
563 ASSERT_EQ(4ul, titles
.size());
564 EXPECT_EQ(title_1
, titles
[0]);
565 EXPECT_EQ(title_4
, titles
[1]);
566 EXPECT_EQ(title_2
, titles
[2]);
567 EXPECT_EQ(title_3
, titles
[3]);
570 TEST_F(JobSchedulerTest
, NoConnectionUserInitiated
) {
573 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
574 scoped_ptr
<google_apis::ResourceEntry
> entry
;
575 scheduler_
->CreateFile(
576 fake_drive_service_
->GetRootResourceId(),
577 base::FilePath(FILE_PATH_LITERAL("dummy")),
580 ClientContext(USER_INITIATED
),
581 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
582 base::RunLoop().RunUntilIdle();
584 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION
, error
);
587 TEST_F(JobSchedulerTest
, NoConnectionBackground
) {
590 std::string
resource_id("file:2_file_resource_id");
592 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
593 scoped_ptr
<google_apis::ResourceEntry
> entry
;
594 scheduler_
->CreateFile(
595 fake_drive_service_
->GetRootResourceId(),
596 base::FilePath(FILE_PATH_LITERAL("dummy")),
599 ClientContext(BACKGROUND
),
600 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
601 base::RunLoop().RunUntilIdle();
605 // Reconnect to the net.
608 base::RunLoop().RunUntilIdle();
610 EXPECT_EQ(google_apis::HTTP_SUCCESS
, error
);
612 EXPECT_EQ("title", entry
->title());
615 TEST_F(JobSchedulerTest
, DownloadFileCellularDisabled
) {
618 // Disable fetching over cellular network.
619 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, true);
621 // Try to get a file in the background
622 base::ScopedTempDir temp_dir
;
623 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
625 const base::FilePath kOutputFilePath
=
626 temp_dir
.path().AppendASCII("whatever.txt");
627 google_apis::GDataErrorCode download_error
= google_apis::GDATA_OTHER_ERROR
;
628 base::FilePath output_file_path
;
629 scheduler_
->DownloadFile(
630 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
631 kDummyDownloadFileSize
,
633 "file:2_file_resource_id",
634 ClientContext(BACKGROUND
),
635 google_apis::test_util::CreateCopyResultCallback(
636 &download_error
, &output_file_path
),
637 google_apis::GetContentCallback());
638 // Metadata should still work
639 google_apis::GDataErrorCode metadata_error
= google_apis::GDATA_OTHER_ERROR
;
640 scoped_ptr
<google_apis::AboutResource
> about_resource
;
642 // Try to get the metadata
643 scheduler_
->GetAboutResource(
644 google_apis::test_util::CreateCopyResultCallback(
645 &metadata_error
, &about_resource
));
646 base::RunLoop().RunUntilIdle();
648 // Check the metadata
649 ASSERT_EQ(google_apis::HTTP_SUCCESS
, metadata_error
);
650 ASSERT_TRUE(about_resource
);
652 // Check the download
653 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR
, download_error
);
655 // Switch to a Wifi connection
658 base::RunLoop().RunUntilIdle();
660 // Check the download again
661 EXPECT_EQ(google_apis::HTTP_SUCCESS
, download_error
);
663 EXPECT_EQ(output_file_path
, kOutputFilePath
);
664 ASSERT_TRUE(base::ReadFileToString(output_file_path
, &content
));
665 EXPECT_EQ("This is some test content.", content
);
668 TEST_F(JobSchedulerTest
, DownloadFileWimaxDisabled
) {
671 // Disable fetching over cellular network.
672 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, true);
674 // Try to get a file in the background
675 base::ScopedTempDir temp_dir
;
676 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
678 const base::FilePath kOutputFilePath
=
679 temp_dir
.path().AppendASCII("whatever.txt");
680 google_apis::GDataErrorCode download_error
= google_apis::GDATA_OTHER_ERROR
;
681 base::FilePath output_file_path
;
682 scheduler_
->DownloadFile(
683 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
684 kDummyDownloadFileSize
,
686 "file:2_file_resource_id",
687 ClientContext(BACKGROUND
),
688 google_apis::test_util::CreateCopyResultCallback(
689 &download_error
, &output_file_path
),
690 google_apis::GetContentCallback());
691 // Metadata should still work
692 google_apis::GDataErrorCode metadata_error
= google_apis::GDATA_OTHER_ERROR
;
693 scoped_ptr
<google_apis::AboutResource
> about_resource
;
695 // Try to get the metadata
696 scheduler_
->GetAboutResource(
697 google_apis::test_util::CreateCopyResultCallback(
698 &metadata_error
, &about_resource
));
699 base::RunLoop().RunUntilIdle();
701 // Check the metadata
702 ASSERT_EQ(google_apis::HTTP_SUCCESS
, metadata_error
);
703 ASSERT_TRUE(about_resource
);
705 // Check the download
706 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR
, download_error
);
708 // Switch to a Wifi connection
711 base::RunLoop().RunUntilIdle();
713 // Check the download again
714 EXPECT_EQ(google_apis::HTTP_SUCCESS
, download_error
);
716 EXPECT_EQ(output_file_path
, kOutputFilePath
);
717 ASSERT_TRUE(base::ReadFileToString(output_file_path
, &content
));
718 EXPECT_EQ("This is some test content.", content
);
721 TEST_F(JobSchedulerTest
, DownloadFileCellularEnabled
) {
724 // Enable fetching over cellular network.
725 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, false);
727 // Try to get a file in the background
728 base::ScopedTempDir temp_dir
;
729 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
731 const base::FilePath kOutputFilePath
=
732 temp_dir
.path().AppendASCII("whatever.txt");
733 google_apis::GDataErrorCode download_error
= google_apis::GDATA_OTHER_ERROR
;
734 base::FilePath output_file_path
;
735 scheduler_
->DownloadFile(
736 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
737 kDummyDownloadFileSize
,
739 "file:2_file_resource_id",
740 ClientContext(BACKGROUND
),
741 google_apis::test_util::CreateCopyResultCallback(
742 &download_error
, &output_file_path
),
743 google_apis::GetContentCallback());
744 // Metadata should still work
745 google_apis::GDataErrorCode metadata_error
= google_apis::GDATA_OTHER_ERROR
;
746 scoped_ptr
<google_apis::AboutResource
> about_resource
;
748 // Try to get the metadata
749 scheduler_
->GetAboutResource(
750 google_apis::test_util::CreateCopyResultCallback(
751 &metadata_error
, &about_resource
));
752 base::RunLoop().RunUntilIdle();
754 // Check the metadata
755 ASSERT_EQ(google_apis::HTTP_SUCCESS
, metadata_error
);
756 ASSERT_TRUE(about_resource
);
758 // Check the download
759 EXPECT_EQ(google_apis::HTTP_SUCCESS
, download_error
);
761 EXPECT_EQ(output_file_path
, kOutputFilePath
);
762 ASSERT_TRUE(base::ReadFileToString(output_file_path
, &content
));
763 EXPECT_EQ("This is some test content.", content
);
766 TEST_F(JobSchedulerTest
, DownloadFileWimaxEnabled
) {
769 // Enable fetching over cellular network.
770 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, false);
772 // Try to get a file in the background
773 base::ScopedTempDir temp_dir
;
774 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
776 const base::FilePath kOutputFilePath
=
777 temp_dir
.path().AppendASCII("whatever.txt");
778 google_apis::GDataErrorCode download_error
= google_apis::GDATA_OTHER_ERROR
;
779 base::FilePath output_file_path
;
780 scheduler_
->DownloadFile(
781 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
782 kDummyDownloadFileSize
,
784 "file:2_file_resource_id",
785 ClientContext(BACKGROUND
),
786 google_apis::test_util::CreateCopyResultCallback(
787 &download_error
, &output_file_path
),
788 google_apis::GetContentCallback());
789 // Metadata should still work
790 google_apis::GDataErrorCode metadata_error
= google_apis::GDATA_OTHER_ERROR
;
791 scoped_ptr
<google_apis::AboutResource
> about_resource
;
793 // Try to get the metadata
794 scheduler_
->GetAboutResource(
795 google_apis::test_util::CreateCopyResultCallback(
796 &metadata_error
, &about_resource
));
797 base::RunLoop().RunUntilIdle();
799 // Check the metadata
800 ASSERT_EQ(google_apis::HTTP_SUCCESS
, metadata_error
);
801 ASSERT_TRUE(about_resource
);
803 // Check the download
804 EXPECT_EQ(google_apis::HTTP_SUCCESS
, download_error
);
806 EXPECT_EQ(output_file_path
, kOutputFilePath
);
807 ASSERT_TRUE(base::ReadFileToString(output_file_path
, &content
));
808 EXPECT_EQ("This is some test content.", content
);
811 TEST_F(JobSchedulerTest
, JobInfo
) {
812 JobListLogger logger
;
813 scheduler_
->AddObserver(&logger
);
815 // Disable background upload/download.
817 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, true);
819 base::ScopedTempDir temp_dir
;
820 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
822 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
823 scoped_ptr
<google_apis::ResourceEntry
> entry
;
824 scoped_ptr
<google_apis::AboutResource
> about_resource
;
827 std::set
<JobType
> expected_types
;
830 expected_types
.insert(TYPE_ADD_NEW_DIRECTORY
);
831 scheduler_
->AddNewDirectory(
832 fake_drive_service_
->GetRootResourceId(),
834 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
835 expected_types
.insert(TYPE_GET_ABOUT_RESOURCE
);
836 scheduler_
->GetAboutResource(
837 google_apis::test_util::CreateCopyResultCallback(
838 &error
, &about_resource
));
839 expected_types
.insert(TYPE_RENAME_RESOURCE
);
840 scheduler_
->RenameResource(
841 "file:2_file_resource_id",
843 google_apis::test_util::CreateCopyResultCallback(&error
));
844 expected_types
.insert(TYPE_DOWNLOAD_FILE
);
845 scheduler_
->DownloadFile(
846 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
847 kDummyDownloadFileSize
,
848 temp_dir
.path().AppendASCII("whatever.txt"),
849 "file:2_file_resource_id",
850 ClientContext(BACKGROUND
),
851 google_apis::test_util::CreateCopyResultCallback(&error
, &path
),
852 google_apis::GetContentCallback());
854 // The number of jobs queued so far.
855 EXPECT_EQ(4U, scheduler_
->GetJobInfoList().size());
856 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_ADD_NEW_DIRECTORY
));
857 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_GET_ABOUT_RESOURCE
));
858 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_RENAME_RESOURCE
));
859 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_DOWNLOAD_FILE
));
860 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_ADD_NEW_DIRECTORY
));
861 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_GET_ABOUT_RESOURCE
));
862 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_RENAME_RESOURCE
));
863 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_DOWNLOAD_FILE
));
866 expected_types
.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY
);
867 scheduler_
->AddResourceToDirectory(
868 "folder:1_folder_resource_id",
869 "file:2_file_resource_id",
870 google_apis::test_util::CreateCopyResultCallback(&error
));
871 expected_types
.insert(TYPE_COPY_RESOURCE
);
872 scheduler_
->CopyResource(
873 "document:5_document_resource_id",
874 fake_drive_service_
->GetRootResourceId(),
876 base::Time(), // last_modified
877 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
879 // 6 jobs in total were queued.
880 std::vector
<JobInfo
> jobs
= scheduler_
->GetJobInfoList();
881 EXPECT_EQ(6U, jobs
.size());
882 std::set
<JobType
> actual_types
;
883 std::set
<JobID
> job_ids
;
884 for (size_t i
= 0; i
< jobs
.size(); ++i
) {
885 actual_types
.insert(jobs
[i
].job_type
);
886 job_ids
.insert(jobs
[i
].job_id
);
888 EXPECT_EQ(expected_types
, actual_types
);
889 EXPECT_EQ(6U, job_ids
.size()) << "All job IDs must be unique";
890 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_ADD_RESOURCE_TO_DIRECTORY
));
891 EXPECT_TRUE(logger
.Has(JobListLogger::ADDED
, TYPE_COPY_RESOURCE
));
892 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_ADD_RESOURCE_TO_DIRECTORY
));
893 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_COPY_RESOURCE
));
896 base::RunLoop().RunUntilIdle();
898 // All jobs except the BACKGROUND job should have started running (UPDATED)
899 // and then finished (DONE).
900 jobs
= scheduler_
->GetJobInfoList();
901 ASSERT_EQ(1U, jobs
.size());
902 EXPECT_EQ(TYPE_DOWNLOAD_FILE
, jobs
[0].job_type
);
904 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
, TYPE_ADD_NEW_DIRECTORY
));
905 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
, TYPE_GET_ABOUT_RESOURCE
));
906 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
, TYPE_RENAME_RESOURCE
));
907 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
,
908 TYPE_ADD_RESOURCE_TO_DIRECTORY
));
909 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
, TYPE_COPY_RESOURCE
));
910 EXPECT_FALSE(logger
.Has(JobListLogger::UPDATED
, TYPE_DOWNLOAD_FILE
));
912 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_ADD_NEW_DIRECTORY
));
913 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_GET_ABOUT_RESOURCE
));
914 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_RENAME_RESOURCE
));
915 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_ADD_RESOURCE_TO_DIRECTORY
));
916 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_COPY_RESOURCE
));
917 EXPECT_FALSE(logger
.Has(JobListLogger::DONE
, TYPE_DOWNLOAD_FILE
));
919 // Run the background downloading job as well.
921 base::RunLoop().RunUntilIdle();
923 // All jobs should have finished.
924 EXPECT_EQ(0U, scheduler_
->GetJobInfoList().size());
925 EXPECT_TRUE(logger
.Has(JobListLogger::UPDATED
, TYPE_DOWNLOAD_FILE
));
926 EXPECT_TRUE(logger
.Has(JobListLogger::DONE
, TYPE_DOWNLOAD_FILE
));
929 TEST_F(JobSchedulerTest
, JobInfoProgress
) {
930 JobListLogger logger
;
931 scheduler_
->AddObserver(&logger
);
935 base::ScopedTempDir temp_dir
;
936 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
938 google_apis::GDataErrorCode error
= google_apis::GDATA_OTHER_ERROR
;
942 scheduler_
->DownloadFile(
943 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
944 kDummyDownloadFileSize
,
945 temp_dir
.path().AppendASCII("whatever.txt"),
946 "file:2_file_resource_id",
947 ClientContext(BACKGROUND
),
948 google_apis::test_util::CreateCopyResultCallback(&error
, &path
),
949 google_apis::GetContentCallback());
950 base::RunLoop().RunUntilIdle();
952 std::vector
<int64
> download_progress
;
953 logger
.GetProgressInfo(TYPE_DOWNLOAD_FILE
, &download_progress
);
954 ASSERT_TRUE(!download_progress
.empty());
955 EXPECT_TRUE(base::STLIsSorted(download_progress
));
956 EXPECT_GE(download_progress
.front(), 0);
957 EXPECT_LE(download_progress
.back(), 26);
960 path
= temp_dir
.path().AppendASCII("new_file.txt");
961 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path
, "Hello"));
962 google_apis::GDataErrorCode upload_error
=
963 google_apis::GDATA_OTHER_ERROR
;
964 scoped_ptr
<google_apis::ResourceEntry
> entry
;
966 scheduler_
->UploadNewFile(
967 fake_drive_service_
->GetRootResourceId(),
968 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
972 ClientContext(BACKGROUND
),
973 google_apis::test_util::CreateCopyResultCallback(&upload_error
, &entry
));
974 base::RunLoop().RunUntilIdle();
976 std::vector
<int64
> upload_progress
;
977 logger
.GetProgressInfo(TYPE_UPLOAD_NEW_FILE
, &upload_progress
);
978 ASSERT_TRUE(!upload_progress
.empty());
979 EXPECT_TRUE(base::STLIsSorted(upload_progress
));
980 EXPECT_GE(upload_progress
.front(), 0);
981 EXPECT_LE(upload_progress
.back(), 13);
984 TEST_F(JobSchedulerTest
, CancelPendingJob
) {
985 base::ScopedTempDir temp_dir
;
986 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
987 base::FilePath upload_path
= temp_dir
.path().AppendASCII("new_file.txt");
988 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path
, "Hello"));
990 // To create a pending job for testing, set the mode to cellular connection
991 // and issue BACKGROUND jobs.
993 pref_service_
->SetBoolean(prefs::kDisableDriveOverCellular
, true);
995 // Start the first job and record its job ID.
996 google_apis::GDataErrorCode error1
= google_apis::GDATA_OTHER_ERROR
;
997 scoped_ptr
<google_apis::ResourceEntry
> entry
;
998 scheduler_
->UploadNewFile(
999 fake_drive_service_
->GetRootResourceId(),
1000 base::FilePath::FromUTF8Unsafe("dummy/path"),
1004 ClientContext(BACKGROUND
),
1005 google_apis::test_util::CreateCopyResultCallback(&error1
, &entry
));
1007 const std::vector
<JobInfo
>& jobs
= scheduler_
->GetJobInfoList();
1008 ASSERT_EQ(1u, jobs
.size());
1009 ASSERT_EQ(STATE_NONE
, jobs
[0].state
); // Not started yet.
1010 JobID first_job_id
= jobs
[0].job_id
;
1012 // Start the second job.
1013 google_apis::GDataErrorCode error2
= google_apis::GDATA_OTHER_ERROR
;
1014 scheduler_
->UploadNewFile(
1015 fake_drive_service_
->GetRootResourceId(),
1016 base::FilePath::FromUTF8Unsafe("dummy/path"),
1020 ClientContext(BACKGROUND
),
1021 google_apis::test_util::CreateCopyResultCallback(&error2
, &entry
));
1023 // Cancel the first one.
1024 scheduler_
->CancelJob(first_job_id
);
1026 // Only the first job should be cancelled.
1028 base::RunLoop().RunUntilIdle();
1029 EXPECT_EQ(google_apis::GDATA_CANCELLED
, error1
);
1030 EXPECT_EQ(google_apis::HTTP_SUCCESS
, error2
);
1031 EXPECT_TRUE(scheduler_
->GetJobInfoList().empty());
1034 TEST_F(JobSchedulerTest
, CancelRunningJob
) {
1037 base::ScopedTempDir temp_dir
;
1038 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
1039 base::FilePath upload_path
= temp_dir
.path().AppendASCII("new_file.txt");
1040 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path
, "Hello"));
1042 // Run as a cancelable task.
1043 fake_drive_service_
->set_upload_new_file_cancelable(true);
1044 google_apis::GDataErrorCode error1
= google_apis::GDATA_OTHER_ERROR
;
1045 scoped_ptr
<google_apis::ResourceEntry
> entry
;
1046 scheduler_
->UploadNewFile(
1047 fake_drive_service_
->GetRootResourceId(),
1048 base::FilePath::FromUTF8Unsafe("dummy/path"),
1052 ClientContext(USER_INITIATED
),
1053 google_apis::test_util::CreateCopyResultCallback(&error1
, &entry
));
1055 const std::vector
<JobInfo
>& jobs
= scheduler_
->GetJobInfoList();
1056 ASSERT_EQ(1u, jobs
.size());
1057 ASSERT_EQ(STATE_RUNNING
, jobs
[0].state
); // It's running.
1058 JobID first_job_id
= jobs
[0].job_id
;
1060 // Start the second job normally.
1061 fake_drive_service_
->set_upload_new_file_cancelable(false);
1062 google_apis::GDataErrorCode error2
= google_apis::GDATA_OTHER_ERROR
;
1063 scheduler_
->UploadNewFile(
1064 fake_drive_service_
->GetRootResourceId(),
1065 base::FilePath::FromUTF8Unsafe("dummy/path"),
1069 ClientContext(USER_INITIATED
),
1070 google_apis::test_util::CreateCopyResultCallback(&error2
, &entry
));
1072 // Cancel the first one.
1073 scheduler_
->CancelJob(first_job_id
);
1075 // Only the first job should be cancelled.
1076 base::RunLoop().RunUntilIdle();
1077 EXPECT_EQ(google_apis::GDATA_CANCELLED
, error1
);
1078 EXPECT_EQ(google_apis::HTTP_SUCCESS
, error2
);
1079 EXPECT_TRUE(scheduler_
->GetJobInfoList().empty());
1082 } // namespace drive