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