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.
4
5 #include "chrome/browser/chromeos/drive/job_scheduler.h"
6
7 #include <set>
8
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/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/browser/chromeos/drive/test_util.h"
17 #include "chrome/browser/drive/event_logger.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/drive/test_util.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "google_apis/drive/drive_api_parser.h"
23 #include "google_apis/drive/test_util.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace drive {
27
28 namespace {
29
30 // Dummy value passed for the |expected_file_size| parameter of DownloadFile().
31 const int64 kDummyDownloadFileSize = 0;
32
CopyTitleFromFileResourceCallback(std::vector<std::string> * title_list_out,google_apis::GDataErrorCode error_in,scoped_ptr<google_apis::FileResource> entry_in)33 void CopyTitleFromFileResourceCallback(
34 std::vector<std::string>* title_list_out,
35 google_apis::GDataErrorCode error_in,
36 scoped_ptr<google_apis::FileResource> entry_in) {
37 title_list_out->push_back(entry_in->title());
38 }
39
40 class JobListLogger : public JobListObserver {
41 public:
42 enum EventType {
43 ADDED,
44 UPDATED,
45 DONE,
46 };
47
48 struct EventLog {
49 EventType type;
50 JobInfo info;
51
EventLogdrive::__anoncd87f3860111::JobListLogger::EventLog52 EventLog(EventType type, const JobInfo& info) : type(type), info(info) {
53 }
54 };
55
56 // Checks whether the specified type of event has occurred.
Has(EventType type,JobType job_type)57 bool Has(EventType type, JobType job_type) {
58 for (size_t i = 0; i < events.size(); ++i) {
59 if (events[i].type == type && events[i].info.job_type == job_type)
60 return true;
61 }
62 return false;
63 }
64
65 // Gets the progress event information of the specified type.
GetProgressInfo(JobType job_type,std::vector<int64> * progress)66 void GetProgressInfo(JobType job_type, std::vector<int64>* progress) {
67 for (size_t i = 0; i < events.size(); ++i) {
68 if (events[i].type == UPDATED && events[i].info.job_type == job_type)
69 progress->push_back(events[i].info.num_completed_bytes);
70 }
71 }
72
73 // JobListObserver overrides.
OnJobAdded(const JobInfo & info)74 virtual void OnJobAdded(const JobInfo& info) OVERRIDE {
75 events.push_back(EventLog(ADDED, info));
76 }
77
OnJobUpdated(const JobInfo & info)78 virtual void OnJobUpdated(const JobInfo& info) OVERRIDE {
79 events.push_back(EventLog(UPDATED, info));
80 }
81
OnJobDone(const JobInfo & info,FileError error)82 virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE {
83 events.push_back(EventLog(DONE, info));
84 }
85
86 private:
87 std::vector<EventLog> events;
88 };
89
90 // Fake drive service extended for testing cancellation.
91 // When upload_new_file_cancelable is set, this Drive service starts
92 // returning a closure to cancel from InitiateUploadNewFile(). The task will
93 // finish only when the cancel closure is called.
94 class CancelTestableFakeDriveService : public FakeDriveService {
95 public:
CancelTestableFakeDriveService()96 CancelTestableFakeDriveService()
97 : upload_new_file_cancelable_(false) {
98 }
99
set_upload_new_file_cancelable(bool cancelable)100 void set_upload_new_file_cancelable(bool cancelable) {
101 upload_new_file_cancelable_ = cancelable;
102 }
103
InitiateUploadNewFile(const std::string & content_type,int64 content_length,const std::string & parent_resource_id,const std::string & title,const InitiateUploadNewFileOptions & options,const google_apis::InitiateUploadCallback & callback)104 virtual google_apis::CancelCallback InitiateUploadNewFile(
105 const std::string& content_type,
106 int64 content_length,
107 const std::string& parent_resource_id,
108 const std::string& title,
109 const InitiateUploadNewFileOptions& options,
110 const google_apis::InitiateUploadCallback& callback) OVERRIDE {
111 if (upload_new_file_cancelable_)
112 return base::Bind(callback, google_apis::GDATA_CANCELLED, GURL());
113
114 return FakeDriveService::InitiateUploadNewFile(content_type,
115 content_length,
116 parent_resource_id,
117 title,
118 options,
119 callback);
120 }
121
122 private:
123 bool upload_new_file_cancelable_;
124 };
125
126 } // namespace
127
128 class JobSchedulerTest : public testing::Test {
129 public:
JobSchedulerTest()130 JobSchedulerTest()
131 : pref_service_(new TestingPrefServiceSimple) {
132 test_util::RegisterDrivePrefs(pref_service_->registry());
133 }
134
SetUp()135 virtual void SetUp() OVERRIDE {
136 fake_network_change_notifier_.reset(
137 new test_util::FakeNetworkChangeNotifier);
138
139 logger_.reset(new EventLogger);
140
141 fake_drive_service_.reset(new CancelTestableFakeDriveService);
142 test_util::SetUpTestEntries(fake_drive_service_.get());
143 fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
144
145 scheduler_.reset(new JobScheduler(pref_service_.get(),
146 logger_.get(),
147 fake_drive_service_.get(),
148 base::MessageLoopProxy::current().get()));
149 scheduler_->SetDisableThrottling(true);
150 }
151
152 protected:
153 // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
154 // the specified connection type.
ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type)155 void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
156 fake_network_change_notifier_->SetConnectionType(type);
157 }
158
159 // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
ConnectToWifi()160 void ConnectToWifi() {
161 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
162 }
163
164 // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
ConnectToCellular()165 void ConnectToCellular() {
166 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
167 }
168
169 // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
ConnectToWimax()170 void ConnectToWimax() {
171 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
172 }
173
174 // Sets up FakeNetworkChangeNotifier as if it's disconnected.
ConnectToNone()175 void ConnectToNone() {
176 ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
177 }
178
GetMetadataQueueMaxJobCount()179 static int GetMetadataQueueMaxJobCount() {
180 return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
181 }
182
183 content::TestBrowserThreadBundle thread_bundle_;
184 scoped_ptr<TestingPrefServiceSimple> pref_service_;
185 scoped_ptr<test_util::FakeNetworkChangeNotifier>
186 fake_network_change_notifier_;
187 scoped_ptr<EventLogger> logger_;
188 scoped_ptr<CancelTestableFakeDriveService> fake_drive_service_;
189 scoped_ptr<JobScheduler> scheduler_;
190 };
191
TEST_F(JobSchedulerTest,GetAboutResource)192 TEST_F(JobSchedulerTest, GetAboutResource) {
193 ConnectToWifi();
194
195 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
196 scoped_ptr<google_apis::AboutResource> about_resource;
197 scheduler_->GetAboutResource(
198 google_apis::test_util::CreateCopyResultCallback(
199 &error, &about_resource));
200 base::RunLoop().RunUntilIdle();
201 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
202 ASSERT_TRUE(about_resource);
203 }
204
TEST_F(JobSchedulerTest,GetAppList)205 TEST_F(JobSchedulerTest, GetAppList) {
206 ConnectToWifi();
207
208 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
209 scoped_ptr<google_apis::AppList> app_list;
210
211 scheduler_->GetAppList(
212 google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
213 base::RunLoop().RunUntilIdle();
214
215 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
216 ASSERT_TRUE(app_list);
217 }
218
TEST_F(JobSchedulerTest,GetAllFileList)219 TEST_F(JobSchedulerTest, GetAllFileList) {
220 ConnectToWifi();
221
222 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
223 scoped_ptr<google_apis::FileList> file_list;
224
225 scheduler_->GetAllFileList(
226 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
227 base::RunLoop().RunUntilIdle();
228
229 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
230 ASSERT_TRUE(file_list);
231 }
232
TEST_F(JobSchedulerTest,GetFileListInDirectory)233 TEST_F(JobSchedulerTest, GetFileListInDirectory) {
234 ConnectToWifi();
235
236 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
237 scoped_ptr<google_apis::FileList> file_list;
238
239 scheduler_->GetFileListInDirectory(
240 fake_drive_service_->GetRootResourceId(),
241 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
242 base::RunLoop().RunUntilIdle();
243
244 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
245 ASSERT_TRUE(file_list);
246 }
247
TEST_F(JobSchedulerTest,Search)248 TEST_F(JobSchedulerTest, Search) {
249 ConnectToWifi();
250
251 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
252 scoped_ptr<google_apis::FileList> file_list;
253
254 scheduler_->Search(
255 "File", // search query
256 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
257 base::RunLoop().RunUntilIdle();
258
259 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
260 ASSERT_TRUE(file_list);
261 }
262
TEST_F(JobSchedulerTest,GetChangeList)263 TEST_F(JobSchedulerTest, GetChangeList) {
264 ConnectToWifi();
265
266 int64 old_largest_change_id =
267 fake_drive_service_->about_resource().largest_change_id();
268
269 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
270
271 // Create a new directory.
272 {
273 scoped_ptr<google_apis::FileResource> entry;
274 fake_drive_service_->AddNewDirectory(
275 fake_drive_service_->GetRootResourceId(),
276 "new directory",
277 DriveServiceInterface::AddNewDirectoryOptions(),
278 google_apis::test_util::CreateCopyResultCallback(
279 &error, &entry));
280 base::RunLoop().RunUntilIdle();
281 ASSERT_EQ(google_apis::HTTP_CREATED, error);
282 }
283
284 error = google_apis::GDATA_OTHER_ERROR;
285 scoped_ptr<google_apis::ChangeList> change_list;
286 scheduler_->GetChangeList(
287 old_largest_change_id + 1,
288 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
289 base::RunLoop().RunUntilIdle();
290
291 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
292 ASSERT_TRUE(change_list);
293 }
294
TEST_F(JobSchedulerTest,GetRemainingChangeList)295 TEST_F(JobSchedulerTest, GetRemainingChangeList) {
296 ConnectToWifi();
297 fake_drive_service_->set_default_max_results(2);
298
299 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
300 scoped_ptr<google_apis::ChangeList> change_list;
301
302 scheduler_->GetChangeList(
303 0,
304 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
305 base::RunLoop().RunUntilIdle();
306
307 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
308 ASSERT_TRUE(change_list);
309
310 // Keep the next url before releasing the |change_list|.
311 GURL next_url(change_list->next_link());
312
313 error = google_apis::GDATA_OTHER_ERROR;
314 change_list.reset();
315
316 scheduler_->GetRemainingChangeList(
317 next_url,
318 google_apis::test_util::CreateCopyResultCallback(&error, &change_list));
319 base::RunLoop().RunUntilIdle();
320
321 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
322 ASSERT_TRUE(change_list);
323 }
324
TEST_F(JobSchedulerTest,GetRemainingFileList)325 TEST_F(JobSchedulerTest, GetRemainingFileList) {
326 ConnectToWifi();
327 fake_drive_service_->set_default_max_results(2);
328
329 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
330 scoped_ptr<google_apis::FileList> file_list;
331
332 scheduler_->GetFileListInDirectory(
333 fake_drive_service_->GetRootResourceId(),
334 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
335 base::RunLoop().RunUntilIdle();
336
337 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
338 ASSERT_TRUE(file_list);
339
340 // Keep the next url before releasing the |file_list|.
341 GURL next_url(file_list->next_link());
342
343 error = google_apis::GDATA_OTHER_ERROR;
344 file_list.reset();
345
346 scheduler_->GetRemainingFileList(
347 next_url,
348 google_apis::test_util::CreateCopyResultCallback(&error, &file_list));
349 base::RunLoop().RunUntilIdle();
350
351 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
352 ASSERT_TRUE(file_list);
353 }
354
TEST_F(JobSchedulerTest,GetFileResource)355 TEST_F(JobSchedulerTest, GetFileResource) {
356 ConnectToWifi();
357
358 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
359 scoped_ptr<google_apis::FileResource> entry;
360
361 scheduler_->GetFileResource(
362 "2_file_resource_id", // resource ID
363 ClientContext(USER_INITIATED),
364 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
365 base::RunLoop().RunUntilIdle();
366
367 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
368 ASSERT_TRUE(entry);
369 }
370
TEST_F(JobSchedulerTest,GetShareUrl)371 TEST_F(JobSchedulerTest, GetShareUrl) {
372 ConnectToWifi();
373
374 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
375 GURL share_url;
376
377 scheduler_->GetShareUrl(
378 "2_file_resource_id", // resource ID
379 GURL("chrome-extension://test-id/"), // embed origin
380 ClientContext(USER_INITIATED),
381 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
382 base::RunLoop().RunUntilIdle();
383
384 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
385 ASSERT_FALSE(share_url.is_empty());
386 }
387
TEST_F(JobSchedulerTest,TrashResource)388 TEST_F(JobSchedulerTest, TrashResource) {
389 ConnectToWifi();
390
391 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
392
393 scheduler_->TrashResource(
394 "2_file_resource_id",
395 ClientContext(USER_INITIATED),
396 google_apis::test_util::CreateCopyResultCallback(&error));
397 base::RunLoop().RunUntilIdle();
398
399 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
400 }
401
TEST_F(JobSchedulerTest,CopyResource)402 TEST_F(JobSchedulerTest, CopyResource) {
403 ConnectToWifi();
404
405 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
406 scoped_ptr<google_apis::FileResource> entry;
407
408 scheduler_->CopyResource(
409 "2_file_resource_id", // resource ID
410 "1_folder_resource_id", // parent resource ID
411 "New Document", // new title
412 base::Time(),
413 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
414 base::RunLoop().RunUntilIdle();
415
416 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
417 ASSERT_TRUE(entry);
418 }
419
TEST_F(JobSchedulerTest,UpdateResource)420 TEST_F(JobSchedulerTest, UpdateResource) {
421 ConnectToWifi();
422
423 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
424 scoped_ptr<google_apis::FileResource> entry;
425
426 scheduler_->UpdateResource(
427 "2_file_resource_id", // resource ID
428 "1_folder_resource_id", // parent resource ID
429 "New Document", // new title
430 base::Time(),
431 base::Time(),
432 ClientContext(USER_INITIATED),
433 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
434 base::RunLoop().RunUntilIdle();
435
436 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
437 ASSERT_TRUE(entry);
438 }
439
TEST_F(JobSchedulerTest,AddResourceToDirectory)440 TEST_F(JobSchedulerTest, AddResourceToDirectory) {
441 ConnectToWifi();
442
443 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
444
445 scheduler_->AddResourceToDirectory(
446 "1_folder_resource_id",
447 "2_file_resource_id",
448 google_apis::test_util::CreateCopyResultCallback(&error));
449 base::RunLoop().RunUntilIdle();
450
451 ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
452 }
453
TEST_F(JobSchedulerTest,RemoveResourceFromDirectory)454 TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
455 ConnectToWifi();
456
457 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
458
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();
465
466 ASSERT_EQ(google_apis::HTTP_NO_CONTENT, error);
467 }
468
TEST_F(JobSchedulerTest,AddNewDirectory)469 TEST_F(JobSchedulerTest, AddNewDirectory) {
470 ConnectToWifi();
471
472 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
473 scoped_ptr<google_apis::FileResource> entry;
474
475 scheduler_->AddNewDirectory(
476 fake_drive_service_->GetRootResourceId(), // Root directory.
477 "New Directory",
478 DriveServiceInterface::AddNewDirectoryOptions(),
479 ClientContext(USER_INITIATED),
480 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
481 base::RunLoop().RunUntilIdle();
482
483 ASSERT_EQ(google_apis::HTTP_CREATED, error);
484 ASSERT_TRUE(entry);
485 }
486
TEST_F(JobSchedulerTest,PriorityHandling)487 TEST_F(JobSchedulerTest, PriorityHandling) {
488 // Saturate the metadata job queue with uninteresting jobs to prevent
489 // following jobs from starting.
490 google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
491 scoped_ptr<google_apis::FileResource> entry_dontcare;
492 for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
493 std::string resource_id("2_file_resource_id");
494 scheduler_->GetFileResource(
495 resource_id,
496 ClientContext(USER_INITIATED),
497 google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
498 &entry_dontcare));
499 }
500
501 // Start jobs with different priorities.
502 std::string title_1("new file 1");
503 std::string title_2("new file 2");
504 std::string title_3("new file 3");
505 std::string title_4("new file 4");
506 std::vector<std::string> titles;
507
508 scheduler_->AddNewDirectory(
509 fake_drive_service_->GetRootResourceId(),
510 title_1,
511 DriveServiceInterface::AddNewDirectoryOptions(),
512 ClientContext(USER_INITIATED),
513 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
514 scheduler_->AddNewDirectory(
515 fake_drive_service_->GetRootResourceId(),
516 title_2,
517 DriveServiceInterface::AddNewDirectoryOptions(),
518 ClientContext(BACKGROUND),
519 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
520 scheduler_->AddNewDirectory(
521 fake_drive_service_->GetRootResourceId(),
522 title_3,
523 DriveServiceInterface::AddNewDirectoryOptions(),
524 ClientContext(BACKGROUND),
525 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
526 scheduler_->AddNewDirectory(
527 fake_drive_service_->GetRootResourceId(),
528 title_4,
529 DriveServiceInterface::AddNewDirectoryOptions(),
530 ClientContext(USER_INITIATED),
531 base::Bind(&CopyTitleFromFileResourceCallback, &titles));
532
533 base::RunLoop().RunUntilIdle();
534
535 ASSERT_EQ(4ul, titles.size());
536 EXPECT_EQ(title_1, titles[0]);
537 EXPECT_EQ(title_4, titles[1]);
538 EXPECT_EQ(title_2, titles[2]);
539 EXPECT_EQ(title_3, titles[3]);
540 }
541
TEST_F(JobSchedulerTest,NoConnectionUserInitiated)542 TEST_F(JobSchedulerTest, NoConnectionUserInitiated) {
543 ConnectToNone();
544
545 std::string resource_id("2_file_resource_id");
546
547 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
548 scoped_ptr<google_apis::FileResource> entry;
549 scheduler_->GetFileResource(
550 resource_id,
551 ClientContext(USER_INITIATED),
552 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
553 base::RunLoop().RunUntilIdle();
554
555 EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
556 }
557
TEST_F(JobSchedulerTest,NoConnectionBackground)558 TEST_F(JobSchedulerTest, NoConnectionBackground) {
559 ConnectToNone();
560
561 std::string resource_id("2_file_resource_id");
562
563 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
564 scoped_ptr<google_apis::FileResource> entry;
565 scheduler_->GetFileResource(
566 resource_id,
567 ClientContext(BACKGROUND),
568 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
569 base::RunLoop().RunUntilIdle();
570
571 EXPECT_FALSE(entry);
572
573 // Reconnect to the net.
574 ConnectToWifi();
575
576 base::RunLoop().RunUntilIdle();
577
578 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
579 ASSERT_TRUE(entry);
580 }
581
TEST_F(JobSchedulerTest,DownloadFileCellularDisabled)582 TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
583 ConnectToCellular();
584
585 // Disable fetching over cellular network.
586 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
587
588 // Try to get a file in the background
589 base::ScopedTempDir temp_dir;
590 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
591
592 const base::FilePath kOutputFilePath =
593 temp_dir.path().AppendASCII("whatever.txt");
594 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
595 base::FilePath output_file_path;
596 scheduler_->DownloadFile(
597 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
598 kDummyDownloadFileSize,
599 kOutputFilePath,
600 "2_file_resource_id",
601 ClientContext(BACKGROUND),
602 google_apis::test_util::CreateCopyResultCallback(
603 &download_error, &output_file_path),
604 google_apis::GetContentCallback());
605 // Metadata should still work
606 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
607 scoped_ptr<google_apis::AboutResource> about_resource;
608
609 // Try to get the metadata
610 scheduler_->GetAboutResource(
611 google_apis::test_util::CreateCopyResultCallback(
612 &metadata_error, &about_resource));
613 base::RunLoop().RunUntilIdle();
614
615 // Check the metadata
616 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
617 ASSERT_TRUE(about_resource);
618
619 // Check the download
620 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
621
622 // Switch to a Wifi connection
623 ConnectToWifi();
624
625 base::RunLoop().RunUntilIdle();
626
627 // Check the download again
628 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
629 std::string content;
630 EXPECT_EQ(output_file_path, kOutputFilePath);
631 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
632 EXPECT_EQ("This is some test content.", content);
633 }
634
TEST_F(JobSchedulerTest,DownloadFileWimaxDisabled)635 TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
636 ConnectToWimax();
637
638 // Disable fetching over cellular network.
639 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
640
641 // Try to get a file in the background
642 base::ScopedTempDir temp_dir;
643 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
644
645 const base::FilePath kOutputFilePath =
646 temp_dir.path().AppendASCII("whatever.txt");
647 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
648 base::FilePath output_file_path;
649 scheduler_->DownloadFile(
650 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
651 kDummyDownloadFileSize,
652 kOutputFilePath,
653 "2_file_resource_id",
654 ClientContext(BACKGROUND),
655 google_apis::test_util::CreateCopyResultCallback(
656 &download_error, &output_file_path),
657 google_apis::GetContentCallback());
658 // Metadata should still work
659 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
660 scoped_ptr<google_apis::AboutResource> about_resource;
661
662 // Try to get the metadata
663 scheduler_->GetAboutResource(
664 google_apis::test_util::CreateCopyResultCallback(
665 &metadata_error, &about_resource));
666 base::RunLoop().RunUntilIdle();
667
668 // Check the metadata
669 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
670 ASSERT_TRUE(about_resource);
671
672 // Check the download
673 EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
674
675 // Switch to a Wifi connection
676 ConnectToWifi();
677
678 base::RunLoop().RunUntilIdle();
679
680 // Check the download again
681 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
682 std::string content;
683 EXPECT_EQ(output_file_path, kOutputFilePath);
684 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
685 EXPECT_EQ("This is some test content.", content);
686 }
687
TEST_F(JobSchedulerTest,DownloadFileCellularEnabled)688 TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
689 ConnectToCellular();
690
691 // Enable fetching over cellular network.
692 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
693
694 // Try to get a file in the background
695 base::ScopedTempDir temp_dir;
696 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
697
698 const base::FilePath kOutputFilePath =
699 temp_dir.path().AppendASCII("whatever.txt");
700 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
701 base::FilePath output_file_path;
702 scheduler_->DownloadFile(
703 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
704 kDummyDownloadFileSize,
705 kOutputFilePath,
706 "2_file_resource_id",
707 ClientContext(BACKGROUND),
708 google_apis::test_util::CreateCopyResultCallback(
709 &download_error, &output_file_path),
710 google_apis::GetContentCallback());
711 // Metadata should still work
712 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
713 scoped_ptr<google_apis::AboutResource> about_resource;
714
715 // Try to get the metadata
716 scheduler_->GetAboutResource(
717 google_apis::test_util::CreateCopyResultCallback(
718 &metadata_error, &about_resource));
719 base::RunLoop().RunUntilIdle();
720
721 // Check the metadata
722 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
723 ASSERT_TRUE(about_resource);
724
725 // Check the download
726 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
727 std::string content;
728 EXPECT_EQ(output_file_path, kOutputFilePath);
729 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
730 EXPECT_EQ("This is some test content.", content);
731 }
732
TEST_F(JobSchedulerTest,DownloadFileWimaxEnabled)733 TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
734 ConnectToWimax();
735
736 // Enable fetching over cellular network.
737 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, false);
738
739 // Try to get a file in the background
740 base::ScopedTempDir temp_dir;
741 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
742
743 const base::FilePath kOutputFilePath =
744 temp_dir.path().AppendASCII("whatever.txt");
745 google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
746 base::FilePath output_file_path;
747 scheduler_->DownloadFile(
748 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
749 kDummyDownloadFileSize,
750 kOutputFilePath,
751 "2_file_resource_id",
752 ClientContext(BACKGROUND),
753 google_apis::test_util::CreateCopyResultCallback(
754 &download_error, &output_file_path),
755 google_apis::GetContentCallback());
756 // Metadata should still work
757 google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
758 scoped_ptr<google_apis::AboutResource> about_resource;
759
760 // Try to get the metadata
761 scheduler_->GetAboutResource(
762 google_apis::test_util::CreateCopyResultCallback(
763 &metadata_error, &about_resource));
764 base::RunLoop().RunUntilIdle();
765
766 // Check the metadata
767 ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
768 ASSERT_TRUE(about_resource);
769
770 // Check the download
771 EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
772 std::string content;
773 EXPECT_EQ(output_file_path, kOutputFilePath);
774 ASSERT_TRUE(base::ReadFileToString(output_file_path, &content));
775 EXPECT_EQ("This is some test content.", content);
776 }
777
TEST_F(JobSchedulerTest,JobInfo)778 TEST_F(JobSchedulerTest, JobInfo) {
779 JobListLogger logger;
780 scheduler_->AddObserver(&logger);
781
782 // Disable background upload/download.
783 ConnectToWimax();
784 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
785
786 base::ScopedTempDir temp_dir;
787 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
788
789 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
790 scoped_ptr<google_apis::FileResource> entry;
791 scoped_ptr<google_apis::AboutResource> about_resource;
792 base::FilePath path;
793
794 std::set<JobType> expected_types;
795
796 // Add many jobs.
797 expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
798 scheduler_->AddNewDirectory(
799 fake_drive_service_->GetRootResourceId(),
800 "New Directory",
801 DriveServiceInterface::AddNewDirectoryOptions(),
802 ClientContext(USER_INITIATED),
803 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
804 expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
805 scheduler_->GetAboutResource(
806 google_apis::test_util::CreateCopyResultCallback(
807 &error, &about_resource));
808 expected_types.insert(TYPE_UPDATE_RESOURCE);
809 scheduler_->UpdateResource(
810 "2_file_resource_id",
811 std::string(),
812 "New Title",
813 base::Time(),
814 base::Time(),
815 ClientContext(USER_INITIATED),
816 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
817 expected_types.insert(TYPE_DOWNLOAD_FILE);
818 scheduler_->DownloadFile(
819 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
820 kDummyDownloadFileSize,
821 temp_dir.path().AppendASCII("whatever.txt"),
822 "2_file_resource_id",
823 ClientContext(BACKGROUND),
824 google_apis::test_util::CreateCopyResultCallback(&error, &path),
825 google_apis::GetContentCallback());
826
827 // The number of jobs queued so far.
828 EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
829 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
830 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
831 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_UPDATE_RESOURCE));
832 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
833 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
834 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
835 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE));
836 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
837
838 // Add more jobs.
839 expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
840 scheduler_->AddResourceToDirectory(
841 "1_folder_resource_id",
842 "2_file_resource_id",
843 google_apis::test_util::CreateCopyResultCallback(&error));
844 expected_types.insert(TYPE_COPY_RESOURCE);
845 scheduler_->CopyResource(
846 "5_document_resource_id",
847 fake_drive_service_->GetRootResourceId(),
848 "New Document",
849 base::Time(), // last_modified
850 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
851
852 // 6 jobs in total were queued.
853 std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
854 EXPECT_EQ(6U, jobs.size());
855 std::set<JobType> actual_types;
856 std::set<JobID> job_ids;
857 for (size_t i = 0; i < jobs.size(); ++i) {
858 actual_types.insert(jobs[i].job_type);
859 job_ids.insert(jobs[i].job_id);
860 }
861 EXPECT_EQ(expected_types, actual_types);
862 EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
863 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
864 EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_RESOURCE));
865 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
866 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
867
868 // Run the jobs.
869 base::RunLoop().RunUntilIdle();
870
871 // All jobs except the BACKGROUND job should have started running (UPDATED)
872 // and then finished (DONE).
873 jobs = scheduler_->GetJobInfoList();
874 ASSERT_EQ(1U, jobs.size());
875 EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
876
877 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
878 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
879 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_UPDATE_RESOURCE));
880 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
881 TYPE_ADD_RESOURCE_TO_DIRECTORY));
882 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_RESOURCE));
883 EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
884
885 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
886 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
887 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_UPDATE_RESOURCE));
888 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
889 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_RESOURCE));
890 EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
891
892 // Run the background downloading job as well.
893 ConnectToWifi();
894 base::RunLoop().RunUntilIdle();
895
896 // All jobs should have finished.
897 EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
898 EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
899 EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
900 }
901
TEST_F(JobSchedulerTest,JobInfoProgress)902 TEST_F(JobSchedulerTest, JobInfoProgress) {
903 JobListLogger logger;
904 scheduler_->AddObserver(&logger);
905
906 ConnectToWifi();
907
908 base::ScopedTempDir temp_dir;
909 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
910
911 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
912 base::FilePath path;
913
914 // Download job.
915 scheduler_->DownloadFile(
916 base::FilePath::FromUTF8Unsafe("drive/whatever.txt"), // virtual path
917 kDummyDownloadFileSize,
918 temp_dir.path().AppendASCII("whatever.txt"),
919 "2_file_resource_id",
920 ClientContext(BACKGROUND),
921 google_apis::test_util::CreateCopyResultCallback(&error, &path),
922 google_apis::GetContentCallback());
923 base::RunLoop().RunUntilIdle();
924
925 std::vector<int64> download_progress;
926 logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
927 ASSERT_TRUE(!download_progress.empty());
928 EXPECT_TRUE(base::STLIsSorted(download_progress));
929 EXPECT_GE(download_progress.front(), 0);
930 EXPECT_LE(download_progress.back(), 26);
931
932 // Upload job.
933 path = temp_dir.path().AppendASCII("new_file.txt");
934 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
935 google_apis::GDataErrorCode upload_error =
936 google_apis::GDATA_OTHER_ERROR;
937 scoped_ptr<google_apis::FileResource> entry;
938
939 scheduler_->UploadNewFile(
940 fake_drive_service_->GetRootResourceId(),
941 base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
942 path,
943 "dummy title",
944 "plain/plain",
945 DriveUploader::UploadNewFileOptions(),
946 ClientContext(BACKGROUND),
947 google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
948 base::RunLoop().RunUntilIdle();
949
950 std::vector<int64> upload_progress;
951 logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
952 ASSERT_TRUE(!upload_progress.empty());
953 EXPECT_TRUE(base::STLIsSorted(upload_progress));
954 EXPECT_GE(upload_progress.front(), 0);
955 EXPECT_LE(upload_progress.back(), 13);
956 }
957
TEST_F(JobSchedulerTest,CancelPendingJob)958 TEST_F(JobSchedulerTest, CancelPendingJob) {
959 base::ScopedTempDir temp_dir;
960 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
961 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
962 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
963
964 // To create a pending job for testing, set the mode to cellular connection
965 // and issue BACKGROUND jobs.
966 ConnectToCellular();
967 pref_service_->SetBoolean(prefs::kDisableDriveOverCellular, true);
968
969 // Start the first job and record its job ID.
970 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
971 scoped_ptr<google_apis::FileResource> entry;
972 scheduler_->UploadNewFile(
973 fake_drive_service_->GetRootResourceId(),
974 base::FilePath::FromUTF8Unsafe("dummy/path"),
975 upload_path,
976 "dummy title 1",
977 "text/plain",
978 DriveUploader::UploadNewFileOptions(),
979 ClientContext(BACKGROUND),
980 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
981
982 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
983 ASSERT_EQ(1u, jobs.size());
984 ASSERT_EQ(STATE_NONE, jobs[0].state); // Not started yet.
985 JobID first_job_id = jobs[0].job_id;
986
987 // Start the second job.
988 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
989 scheduler_->UploadNewFile(
990 fake_drive_service_->GetRootResourceId(),
991 base::FilePath::FromUTF8Unsafe("dummy/path"),
992 upload_path,
993 "dummy title 2",
994 "text/plain",
995 DriveUploader::UploadNewFileOptions(),
996 ClientContext(BACKGROUND),
997 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
998
999 // Cancel the first one.
1000 scheduler_->CancelJob(first_job_id);
1001
1002 // Only the first job should be cancelled.
1003 ConnectToWifi();
1004 base::RunLoop().RunUntilIdle();
1005 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1006 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1007 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1008 }
1009
TEST_F(JobSchedulerTest,CancelRunningJob)1010 TEST_F(JobSchedulerTest, CancelRunningJob) {
1011 ConnectToWifi();
1012
1013 base::ScopedTempDir temp_dir;
1014 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1015 base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
1016 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
1017
1018 // Run as a cancelable task.
1019 fake_drive_service_->set_upload_new_file_cancelable(true);
1020 google_apis::GDataErrorCode error1 = google_apis::GDATA_OTHER_ERROR;
1021 scoped_ptr<google_apis::FileResource> entry;
1022 scheduler_->UploadNewFile(
1023 fake_drive_service_->GetRootResourceId(),
1024 base::FilePath::FromUTF8Unsafe("dummy/path"),
1025 upload_path,
1026 "dummy title 1",
1027 "text/plain",
1028 DriveUploader::UploadNewFileOptions(),
1029 ClientContext(USER_INITIATED),
1030 google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
1031
1032 const std::vector<JobInfo>& jobs = scheduler_->GetJobInfoList();
1033 ASSERT_EQ(1u, jobs.size());
1034 ASSERT_EQ(STATE_RUNNING, jobs[0].state); // It's running.
1035 JobID first_job_id = jobs[0].job_id;
1036
1037 // Start the second job normally.
1038 fake_drive_service_->set_upload_new_file_cancelable(false);
1039 google_apis::GDataErrorCode error2 = google_apis::GDATA_OTHER_ERROR;
1040 scheduler_->UploadNewFile(
1041 fake_drive_service_->GetRootResourceId(),
1042 base::FilePath::FromUTF8Unsafe("dummy/path"),
1043 upload_path,
1044 "dummy title 2",
1045 "text/plain",
1046 DriveUploader::UploadNewFileOptions(),
1047 ClientContext(USER_INITIATED),
1048 google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
1049
1050 // Cancel the first one.
1051 scheduler_->CancelJob(first_job_id);
1052
1053 // Only the first job should be cancelled.
1054 base::RunLoop().RunUntilIdle();
1055 EXPECT_EQ(google_apis::GDATA_CANCELLED, error1);
1056 EXPECT_EQ(google_apis::HTTP_SUCCESS, error2);
1057 EXPECT_TRUE(scheduler_->GetJobInfoList().empty());
1058 }
1059
1060 } // namespace drive
1061