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