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