job_scheduler_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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/prefs/pref_service.h"
12#include "base/run_loop.h"
13#include "base/stl_util.h"
14#include "chrome/browser/chromeos/drive/test_util.h"
15#include "chrome/browser/drive/fake_drive_service.h"
16#include "chrome/browser/google_apis/drive_api_parser.h"
17#include "chrome/browser/google_apis/gdata_wapi_parser.h"
18#include "chrome/browser/google_apis/test_util.h"
19#include "chrome/common/pref_names.h"
20#include "chrome/test/base/testing_profile.h"
21#include "content/public/test/test_browser_thread_bundle.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24namespace drive {
25
26namespace {
27
28void CopyResourceIdFromGetResourceEntryCallback(
29    std::vector<std::string>* id_list_out,
30    const std::string& requested_id,
31    google_apis::GDataErrorCode error_in,
32    scoped_ptr<google_apis::ResourceEntry> resource_entry_in) {
33  id_list_out->push_back(requested_id);
34}
35
36class JobListLogger : public JobListObserver {
37 public:
38  enum EventType {
39    ADDED,
40    UPDATED,
41    DONE,
42  };
43
44  struct EventLog {
45    EventType type;
46    JobInfo info;
47
48    EventLog(EventType type, const JobInfo& info) : type(type), info(info) {
49    }
50  };
51
52  // Checks whether the specified type of event has occurred.
53  bool Has(EventType type, JobType job_type) {
54    for (size_t i = 0; i < events.size(); ++i) {
55      if (events[i].type == type && events[i].info.job_type == job_type)
56        return true;
57    }
58    return false;
59  }
60
61  // Gets the progress event information of the specified type.
62  void GetProgressInfo(JobType job_type, std::vector<int64>* progress) {
63    for (size_t i = 0; i < events.size(); ++i) {
64      if (events[i].type == UPDATED && events[i].info.job_type == job_type)
65        progress->push_back(events[i].info.num_completed_bytes);
66    }
67  }
68
69  // JobListObserver overrides.
70  virtual void OnJobAdded(const JobInfo& info) OVERRIDE {
71    events.push_back(EventLog(ADDED, info));
72  }
73
74  virtual void OnJobUpdated(const JobInfo& info) OVERRIDE {
75    events.push_back(EventLog(UPDATED, info));
76  }
77
78  virtual void OnJobDone(const JobInfo& info, FileError error) OVERRIDE {
79    events.push_back(EventLog(DONE, info));
80  }
81
82 private:
83  std::vector<EventLog> events;
84};
85
86}  // namespace
87
88class JobSchedulerTest : public testing::Test {
89 public:
90  JobSchedulerTest()
91      : profile_(new TestingProfile) {
92  }
93
94  virtual void SetUp() OVERRIDE {
95    fake_network_change_notifier_.reset(
96        new test_util::FakeNetworkChangeNotifier);
97
98    fake_drive_service_.reset(new FakeDriveService());
99    fake_drive_service_->LoadResourceListForWapi(
100        "gdata/root_feed.json");
101    fake_drive_service_->LoadAccountMetadataForWapi(
102        "gdata/account_metadata.json");
103    fake_drive_service_->LoadAppListForDriveApi(
104        "drive/applist.json");
105
106    scheduler_.reset(new JobScheduler(profile_.get(),
107                                      fake_drive_service_.get(),
108                                      base::MessageLoopProxy::current()));
109    scheduler_->SetDisableThrottling(true);
110  }
111
112 protected:
113  // Sets up FakeNetworkChangeNotifier as if it's connected to a network with
114  // the specified connection type.
115  void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
116    fake_network_change_notifier_->SetConnectionType(type);
117  }
118
119  // Sets up FakeNetworkChangeNotifier as if it's connected to wifi network.
120  void ConnectToWifi() {
121    ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
122  }
123
124  // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
125  void ConnectToCellular() {
126    ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
127  }
128
129  // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
130  void ConnectToWimax() {
131    ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
132  }
133
134  // Sets up FakeNetworkChangeNotifier as if it's disconnected.
135  void ConnectToNone() {
136    ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
137  }
138
139  static int GetMetadataQueueMaxJobCount() {
140    return JobScheduler::kMaxJobCount[JobScheduler::METADATA_QUEUE];
141  }
142
143  content::TestBrowserThreadBundle thread_bundle_;
144  scoped_ptr<TestingProfile> profile_;
145  scoped_ptr<test_util::FakeNetworkChangeNotifier>
146      fake_network_change_notifier_;
147  scoped_ptr<FakeDriveService> fake_drive_service_;
148  scoped_ptr<JobScheduler> scheduler_;
149};
150
151TEST_F(JobSchedulerTest, GetAboutResource) {
152  ConnectToWifi();
153
154  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
155  scoped_ptr<google_apis::AboutResource> about_resource;
156  scheduler_->GetAboutResource(
157      google_apis::test_util::CreateCopyResultCallback(
158          &error, &about_resource));
159  base::RunLoop().RunUntilIdle();
160  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
161  ASSERT_TRUE(about_resource);
162}
163
164TEST_F(JobSchedulerTest, GetAppList) {
165  ConnectToWifi();
166
167  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
168  scoped_ptr<google_apis::AppList> app_list;
169
170  scheduler_->GetAppList(
171      google_apis::test_util::CreateCopyResultCallback(&error, &app_list));
172  base::RunLoop().RunUntilIdle();
173
174  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
175  ASSERT_TRUE(app_list);
176}
177
178TEST_F(JobSchedulerTest, GetAllResourceList) {
179  ConnectToWifi();
180
181  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
182  scoped_ptr<google_apis::ResourceList> resource_list;
183
184  scheduler_->GetAllResourceList(
185      google_apis::test_util::CreateCopyResultCallback(
186          &error, &resource_list));
187  base::RunLoop().RunUntilIdle();
188
189  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
190  ASSERT_TRUE(resource_list);
191}
192
193TEST_F(JobSchedulerTest, GetResourceListInDirectory) {
194  ConnectToWifi();
195
196  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
197  scoped_ptr<google_apis::ResourceList> resource_list;
198
199  scheduler_->GetResourceListInDirectory(
200      fake_drive_service_->GetRootResourceId(),
201      google_apis::test_util::CreateCopyResultCallback(
202          &error, &resource_list));
203  base::RunLoop().RunUntilIdle();
204
205  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
206  ASSERT_TRUE(resource_list);
207}
208
209TEST_F(JobSchedulerTest, Search) {
210  ConnectToWifi();
211
212  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
213  scoped_ptr<google_apis::ResourceList> resource_list;
214
215  scheduler_->Search(
216      "File",  // search query
217      google_apis::test_util::CreateCopyResultCallback(
218          &error, &resource_list));
219  base::RunLoop().RunUntilIdle();
220
221  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
222  ASSERT_TRUE(resource_list);
223}
224
225TEST_F(JobSchedulerTest, GetChangeList) {
226  ConnectToWifi();
227
228  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
229
230  // Create a new directory.
231  // The loaded (initial) changestamp is 654321. Thus, by this operation,
232  // it should become 654322.
233  {
234    scoped_ptr<google_apis::ResourceEntry> resource_entry;
235    fake_drive_service_->AddNewDirectory(
236        fake_drive_service_->GetRootResourceId(),
237        "new directory",
238        google_apis::test_util::CreateCopyResultCallback(
239            &error, &resource_entry));
240    base::RunLoop().RunUntilIdle();
241    ASSERT_EQ(google_apis::HTTP_CREATED, error);
242  }
243
244  error = google_apis::GDATA_OTHER_ERROR;
245  scoped_ptr<google_apis::ResourceList> resource_list;
246  scheduler_->GetChangeList(
247      654321 + 1,  // start_changestamp
248      google_apis::test_util::CreateCopyResultCallback(
249          &error, &resource_list));
250  base::RunLoop().RunUntilIdle();
251
252  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
253  ASSERT_TRUE(resource_list);
254}
255
256TEST_F(JobSchedulerTest, ContinueGetResourceList) {
257  ConnectToWifi();
258  fake_drive_service_->set_default_max_results(2);
259
260  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
261  scoped_ptr<google_apis::ResourceList> resource_list;
262
263  scheduler_->GetAllResourceList(
264      google_apis::test_util::CreateCopyResultCallback(
265          &error, &resource_list));
266  base::RunLoop().RunUntilIdle();
267
268  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
269  ASSERT_TRUE(resource_list);
270
271  const google_apis::Link* next_link =
272      resource_list->GetLinkByType(google_apis::Link::LINK_NEXT);
273  ASSERT_TRUE(next_link);
274  // Keep the next url before releasing the |resource_list|.
275  GURL next_url(next_link->href());
276
277  error = google_apis::GDATA_OTHER_ERROR;
278  resource_list.reset();
279
280  scheduler_->ContinueGetResourceList(
281      next_url,
282      google_apis::test_util::CreateCopyResultCallback(
283          &error, &resource_list));
284  base::RunLoop().RunUntilIdle();
285
286  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
287  ASSERT_TRUE(resource_list);
288}
289
290TEST_F(JobSchedulerTest, GetResourceEntry) {
291  ConnectToWifi();
292
293  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
294  scoped_ptr<google_apis::ResourceEntry> entry;
295
296  scheduler_->GetResourceEntry(
297      "file:2_file_resource_id",  // resource ID
298      ClientContext(USER_INITIATED),
299      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
300  base::RunLoop().RunUntilIdle();
301
302  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
303  ASSERT_TRUE(entry);
304}
305
306TEST_F(JobSchedulerTest, DeleteResource) {
307  ConnectToWifi();
308
309  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
310
311  scheduler_->DeleteResource(
312      "file:2_file_resource_id",
313      google_apis::test_util::CreateCopyResultCallback(&error));
314  base::RunLoop().RunUntilIdle();
315
316  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
317}
318
319TEST_F(JobSchedulerTest, CopyResource) {
320  ConnectToWifi();
321
322  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
323  scoped_ptr<google_apis::ResourceEntry> entry;
324
325  scheduler_->CopyResource(
326      "file:2_file_resource_id",  // resource ID
327      "folder:1_folder_resource_id",  // parent resource ID
328      "New Document",  // new name
329      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
330  base::RunLoop().RunUntilIdle();
331
332  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
333  ASSERT_TRUE(entry);
334}
335
336TEST_F(JobSchedulerTest, CopyHostedDocument) {
337  ConnectToWifi();
338
339  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
340  scoped_ptr<google_apis::ResourceEntry> entry;
341
342  scheduler_->CopyHostedDocument(
343      "document:5_document_resource_id",  // resource ID
344      "New Document",  // new name
345      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
346  base::RunLoop().RunUntilIdle();
347
348  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
349  ASSERT_TRUE(entry);
350}
351
352TEST_F(JobSchedulerTest, RenameResource) {
353  ConnectToWifi();
354
355  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
356
357  scheduler_->RenameResource(
358      "file:2_file_resource_id",
359      "New Name",
360      google_apis::test_util::CreateCopyResultCallback(&error));
361  base::RunLoop().RunUntilIdle();
362
363  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
364}
365
366TEST_F(JobSchedulerTest, AddResourceToDirectory) {
367  ConnectToWifi();
368
369  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
370
371  scheduler_->AddResourceToDirectory(
372      "folder:1_folder_resource_id",
373      "file:2_file_resource_id",
374      google_apis::test_util::CreateCopyResultCallback(&error));
375  base::RunLoop().RunUntilIdle();
376
377  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
378}
379
380TEST_F(JobSchedulerTest, RemoveResourceFromDirectory) {
381  ConnectToWifi();
382
383  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
384
385  scheduler_->RemoveResourceFromDirectory(
386      "folder:1_folder_resource_id",
387      "file:subdirectory_file_1_id",  // resource ID
388      google_apis::test_util::CreateCopyResultCallback(&error));
389  base::RunLoop().RunUntilIdle();
390
391  ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
392}
393
394TEST_F(JobSchedulerTest, AddNewDirectory) {
395  ConnectToWifi();
396
397  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
398  scoped_ptr<google_apis::ResourceEntry> entry;
399
400  scheduler_->AddNewDirectory(
401      fake_drive_service_->GetRootResourceId(),  // Root directory.
402      "New Directory",
403      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
404  base::RunLoop().RunUntilIdle();
405
406  ASSERT_EQ(google_apis::HTTP_CREATED, error);
407  ASSERT_TRUE(entry);
408}
409
410TEST_F(JobSchedulerTest, GetResourceEntryPriority) {
411  // Saturate the metadata job queue with uninteresting jobs to prevent
412  // following jobs from starting.
413  google_apis::GDataErrorCode error_dontcare = google_apis::GDATA_OTHER_ERROR;
414  scoped_ptr<google_apis::ResourceEntry> entry_dontcare;
415  for (int i = 0; i < GetMetadataQueueMaxJobCount(); ++i) {
416    scheduler_->GetResourceEntry(
417        "uninteresting_resource_id",
418        ClientContext(USER_INITIATED),
419        google_apis::test_util::CreateCopyResultCallback(&error_dontcare,
420                                                         &entry_dontcare));
421  }
422
423  // Start jobs with different priorities.
424  std::string resource_1("file:1_file_resource_id");
425  std::string resource_2("file:2_file_resource_id");
426  std::string resource_3("file:3_file_resource_id");
427  std::string resource_4("file:4_file_resource_id");
428  std::vector<std::string> resource_ids;
429
430  scheduler_->GetResourceEntry(
431      resource_1,  // resource ID
432      ClientContext(USER_INITIATED),
433      base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
434                 &resource_ids,
435                 resource_1));
436  scheduler_->GetResourceEntry(
437      resource_2,  // resource ID
438      ClientContext(BACKGROUND),
439      base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
440                 &resource_ids,
441                 resource_2));
442  scheduler_->GetResourceEntry(
443      resource_3,  // resource ID
444      ClientContext(BACKGROUND),
445      base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
446                 &resource_ids,
447                 resource_3));
448  scheduler_->GetResourceEntry(
449      resource_4,  // resource ID
450      ClientContext(USER_INITIATED),
451      base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
452                 &resource_ids,
453                 resource_4));
454
455  base::RunLoop().RunUntilIdle();
456
457  ASSERT_EQ(resource_ids.size(), 4ul);
458  EXPECT_EQ(resource_ids[0], resource_1);
459  EXPECT_EQ(resource_ids[1], resource_4);
460  EXPECT_EQ(resource_ids[2], resource_2);
461  EXPECT_EQ(resource_ids[3], resource_3);
462}
463
464TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionUserInitiated) {
465  ConnectToNone();
466
467  std::string resource_id("file:2_file_resource_id");
468
469  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
470  scoped_ptr<google_apis::ResourceEntry> entry;
471  scheduler_->GetResourceEntry(
472      resource_id,
473      ClientContext(USER_INITIATED),
474      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
475  base::RunLoop().RunUntilIdle();
476
477  EXPECT_EQ(google_apis::GDATA_NO_CONNECTION, error);
478}
479
480TEST_F(JobSchedulerTest, GetResourceEntryNoConnectionBackground) {
481  ConnectToNone();
482
483  std::string resource_id("file:2_file_resource_id");
484
485  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
486  scoped_ptr<google_apis::ResourceEntry> entry;
487  scheduler_->GetResourceEntry(
488      resource_id,
489      ClientContext(BACKGROUND),
490      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
491  base::RunLoop().RunUntilIdle();
492
493  EXPECT_FALSE(entry);
494
495  // Reconnect to the net.
496  ConnectToWifi();
497
498  base::RunLoop().RunUntilIdle();
499
500  EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
501  ASSERT_TRUE(entry);
502  EXPECT_EQ(resource_id, entry->resource_id());
503}
504
505TEST_F(JobSchedulerTest, DownloadFileCellularDisabled) {
506  ConnectToCellular();
507
508  // Disable fetching over cellular network.
509  profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, true);
510
511  // Try to get a file in the background
512  base::ScopedTempDir temp_dir;
513  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
514
515  const base::FilePath kOutputFilePath =
516      temp_dir.path().AppendASCII("whatever.txt");
517  google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
518  base::FilePath output_file_path;
519  scheduler_->DownloadFile(
520      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
521      kOutputFilePath,
522      "file:2_file_resource_id",
523      ClientContext(BACKGROUND),
524      google_apis::test_util::CreateCopyResultCallback(
525          &download_error, &output_file_path),
526      google_apis::GetContentCallback());
527  // Metadata should still work
528  google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
529  scoped_ptr<google_apis::AboutResource> about_resource;
530
531  // Try to get the metadata
532  scheduler_->GetAboutResource(
533      google_apis::test_util::CreateCopyResultCallback(
534          &metadata_error, &about_resource));
535  base::RunLoop().RunUntilIdle();
536
537  // Check the metadata
538  ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
539  ASSERT_TRUE(about_resource);
540
541  // Check the download
542  EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
543
544  // Switch to a Wifi connection
545  ConnectToWifi();
546
547  base::RunLoop().RunUntilIdle();
548
549  // Check the download again
550  EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
551  std::string content;
552  EXPECT_EQ(output_file_path, kOutputFilePath);
553  ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
554  EXPECT_EQ("This is some test content.", content);
555}
556
557TEST_F(JobSchedulerTest, DownloadFileWimaxDisabled) {
558  ConnectToWimax();
559
560  // Disable fetching over cellular network.
561  profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, true);
562
563  // Try to get a file in the background
564  base::ScopedTempDir temp_dir;
565  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
566
567  const base::FilePath kOutputFilePath =
568      temp_dir.path().AppendASCII("whatever.txt");
569  google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
570  base::FilePath output_file_path;
571  scheduler_->DownloadFile(
572      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
573      kOutputFilePath,
574      "file:2_file_resource_id",
575      ClientContext(BACKGROUND),
576      google_apis::test_util::CreateCopyResultCallback(
577          &download_error, &output_file_path),
578      google_apis::GetContentCallback());
579  // Metadata should still work
580  google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
581  scoped_ptr<google_apis::AboutResource> about_resource;
582
583  // Try to get the metadata
584  scheduler_->GetAboutResource(
585      google_apis::test_util::CreateCopyResultCallback(
586          &metadata_error, &about_resource));
587  base::RunLoop().RunUntilIdle();
588
589  // Check the metadata
590  ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
591  ASSERT_TRUE(about_resource);
592
593  // Check the download
594  EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
595
596  // Switch to a Wifi connection
597  ConnectToWifi();
598
599  base::RunLoop().RunUntilIdle();
600
601  // Check the download again
602  EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
603  std::string content;
604  EXPECT_EQ(output_file_path, kOutputFilePath);
605  ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
606  EXPECT_EQ("This is some test content.", content);
607}
608
609TEST_F(JobSchedulerTest, DownloadFileCellularEnabled) {
610  ConnectToCellular();
611
612  // Enable fetching over cellular network.
613  profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, false);
614
615  // Try to get a file in the background
616  base::ScopedTempDir temp_dir;
617  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
618
619  const base::FilePath kOutputFilePath =
620      temp_dir.path().AppendASCII("whatever.txt");
621  google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
622  base::FilePath output_file_path;
623  scheduler_->DownloadFile(
624      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
625      kOutputFilePath,
626      "file:2_file_resource_id",
627      ClientContext(BACKGROUND),
628      google_apis::test_util::CreateCopyResultCallback(
629          &download_error, &output_file_path),
630      google_apis::GetContentCallback());
631  // Metadata should still work
632  google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
633  scoped_ptr<google_apis::AboutResource> about_resource;
634
635  // Try to get the metadata
636  scheduler_->GetAboutResource(
637      google_apis::test_util::CreateCopyResultCallback(
638          &metadata_error, &about_resource));
639  base::RunLoop().RunUntilIdle();
640
641  // Check the metadata
642  ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
643  ASSERT_TRUE(about_resource);
644
645  // Check the download
646  EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
647  std::string content;
648  EXPECT_EQ(output_file_path, kOutputFilePath);
649  ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
650  EXPECT_EQ("This is some test content.", content);
651}
652
653TEST_F(JobSchedulerTest, DownloadFileWimaxEnabled) {
654  ConnectToWimax();
655
656  // Enable fetching over cellular network.
657  profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, false);
658
659  // Try to get a file in the background
660  base::ScopedTempDir temp_dir;
661  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
662
663  const base::FilePath kOutputFilePath =
664      temp_dir.path().AppendASCII("whatever.txt");
665  google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
666  base::FilePath output_file_path;
667  scheduler_->DownloadFile(
668      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
669      kOutputFilePath,
670      "file:2_file_resource_id",
671      ClientContext(BACKGROUND),
672      google_apis::test_util::CreateCopyResultCallback(
673          &download_error, &output_file_path),
674      google_apis::GetContentCallback());
675  // Metadata should still work
676  google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
677  scoped_ptr<google_apis::AboutResource> about_resource;
678
679  // Try to get the metadata
680  scheduler_->GetAboutResource(
681      google_apis::test_util::CreateCopyResultCallback(
682          &metadata_error, &about_resource));
683  base::RunLoop().RunUntilIdle();
684
685  // Check the metadata
686  ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
687  ASSERT_TRUE(about_resource);
688
689  // Check the download
690  EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
691  std::string content;
692  EXPECT_EQ(output_file_path, kOutputFilePath);
693  ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
694  EXPECT_EQ("This is some test content.", content);
695}
696
697TEST_F(JobSchedulerTest, JobInfo) {
698  JobListLogger logger;
699  scheduler_->AddObserver(&logger);
700
701  // Disable background upload/download.
702  ConnectToWimax();
703  profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, true);
704
705  base::ScopedTempDir temp_dir;
706  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
707
708  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
709  scoped_ptr<google_apis::ResourceEntry> entry;
710  scoped_ptr<google_apis::AboutResource> about_resource;
711  base::FilePath path;
712
713  std::set<JobType> expected_types;
714
715  // Add many jobs.
716  expected_types.insert(TYPE_ADD_NEW_DIRECTORY);
717  scheduler_->AddNewDirectory(
718      fake_drive_service_->GetRootResourceId(),
719      "New Directory",
720      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
721  expected_types.insert(TYPE_GET_ABOUT_RESOURCE);
722  scheduler_->GetAboutResource(
723      google_apis::test_util::CreateCopyResultCallback(
724          &error, &about_resource));
725  expected_types.insert(TYPE_RENAME_RESOURCE);
726  scheduler_->RenameResource(
727      "file:2_file_resource_id",
728      "New Name",
729      google_apis::test_util::CreateCopyResultCallback(&error));
730  expected_types.insert(TYPE_DOWNLOAD_FILE);
731  scheduler_->DownloadFile(
732      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
733      temp_dir.path().AppendASCII("whatever.txt"),
734      "file:2_file_resource_id",
735      ClientContext(BACKGROUND),
736      google_apis::test_util::CreateCopyResultCallback(&error, &path),
737      google_apis::GetContentCallback());
738
739  // The number of jobs queued so far.
740  EXPECT_EQ(4U, scheduler_->GetJobInfoList().size());
741  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_NEW_DIRECTORY));
742  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_GET_ABOUT_RESOURCE));
743  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_RENAME_RESOURCE));
744  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_DOWNLOAD_FILE));
745  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
746  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
747  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
748  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
749
750  // Add more jobs.
751  expected_types.insert(TYPE_ADD_RESOURCE_TO_DIRECTORY);
752  scheduler_->AddResourceToDirectory(
753      "folder:1_folder_resource_id",
754      "file:2_file_resource_id",
755      google_apis::test_util::CreateCopyResultCallback(&error));
756  expected_types.insert(TYPE_COPY_HOSTED_DOCUMENT);
757  scheduler_->CopyHostedDocument(
758      "document:5_document_resource_id",
759      "New Document",
760      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
761
762  // 6 jobs in total were queued.
763  std::vector<JobInfo> jobs = scheduler_->GetJobInfoList();
764  EXPECT_EQ(6U, jobs.size());
765  std::set<JobType> actual_types;
766  std::set<JobID> job_ids;
767  for (size_t i = 0; i < jobs.size(); ++i) {
768    actual_types.insert(jobs[i].job_type);
769    job_ids.insert(jobs[i].job_id);
770  }
771  EXPECT_EQ(expected_types, actual_types);
772  EXPECT_EQ(6U, job_ids.size()) << "All job IDs must be unique";
773  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_ADD_RESOURCE_TO_DIRECTORY));
774  EXPECT_TRUE(logger.Has(JobListLogger::ADDED, TYPE_COPY_HOSTED_DOCUMENT));
775  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
776  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT));
777
778  // Run the jobs.
779  base::RunLoop().RunUntilIdle();
780
781  // All jobs except the BACKGROUND job should have started running (UPDATED)
782  // and then finished (DONE).
783  jobs = scheduler_->GetJobInfoList();
784  ASSERT_EQ(1U, jobs.size());
785  EXPECT_EQ(TYPE_DOWNLOAD_FILE, jobs[0].job_type);
786
787  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_ADD_NEW_DIRECTORY));
788  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_GET_ABOUT_RESOURCE));
789  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_RENAME_RESOURCE));
790  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED,
791                         TYPE_ADD_RESOURCE_TO_DIRECTORY));
792  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_COPY_HOSTED_DOCUMENT));
793  EXPECT_FALSE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
794
795  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_NEW_DIRECTORY));
796  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_GET_ABOUT_RESOURCE));
797  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_RENAME_RESOURCE));
798  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_ADD_RESOURCE_TO_DIRECTORY));
799  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_COPY_HOSTED_DOCUMENT));
800  EXPECT_FALSE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
801
802  // Run the background downloading job as well.
803  ConnectToWifi();
804  base::RunLoop().RunUntilIdle();
805
806  // All jobs should have finished.
807  EXPECT_EQ(0U, scheduler_->GetJobInfoList().size());
808  EXPECT_TRUE(logger.Has(JobListLogger::UPDATED, TYPE_DOWNLOAD_FILE));
809  EXPECT_TRUE(logger.Has(JobListLogger::DONE, TYPE_DOWNLOAD_FILE));
810}
811
812
813TEST_F(JobSchedulerTest, JobInfoProgress) {
814  JobListLogger logger;
815  scheduler_->AddObserver(&logger);
816
817  ConnectToWifi();
818
819  base::ScopedTempDir temp_dir;
820  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
821
822  google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
823  base::FilePath path;
824
825  // Download job.
826  scheduler_->DownloadFile(
827      base::FilePath::FromUTF8Unsafe("drive/whatever.txt"),  // virtual path
828      temp_dir.path().AppendASCII("whatever.txt"),
829      "file:2_file_resource_id",
830      ClientContext(BACKGROUND),
831      google_apis::test_util::CreateCopyResultCallback(&error, &path),
832      google_apis::GetContentCallback());
833  base::RunLoop().RunUntilIdle();
834
835  std::vector<int64> download_progress;
836  logger.GetProgressInfo(TYPE_DOWNLOAD_FILE, &download_progress);
837  ASSERT_TRUE(!download_progress.empty());
838  EXPECT_TRUE(base::STLIsSorted(download_progress));
839  EXPECT_GE(download_progress.front(), 0);
840  EXPECT_LE(download_progress.back(), 26);
841
842  // Upload job.
843  path = temp_dir.path().AppendASCII("new_file.txt");
844  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
845  google_apis::GDataErrorCode upload_error =
846      google_apis::GDATA_OTHER_ERROR;
847  scoped_ptr<google_apis::ResourceEntry> entry;
848
849  scheduler_->UploadNewFile(
850      fake_drive_service_->GetRootResourceId(),
851      base::FilePath::FromUTF8Unsafe("drive/new_file.txt"),
852      path,
853      "dummy title",
854      "plain/plain",
855      ClientContext(BACKGROUND),
856      google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
857  base::RunLoop().RunUntilIdle();
858
859  std::vector<int64> upload_progress;
860  logger.GetProgressInfo(TYPE_UPLOAD_NEW_FILE, &upload_progress);
861  ASSERT_TRUE(!upload_progress.empty());
862  EXPECT_TRUE(base::STLIsSorted(upload_progress));
863  EXPECT_GE(upload_progress.front(), 0);
864  EXPECT_LE(upload_progress.back(), 13);
865}
866
867}  // namespace drive
868