Home | History | Annotate | Download | only in drive
      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 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:
    127   JobSchedulerTest()
    128       : pref_service_(new TestingPrefServiceSimple) {
    129     test_util::RegisterDrivePrefs(pref_service_->registry());
    130   }
    131 
    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.
    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.
    158   void ConnectToWifi() {
    159     ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
    160   }
    161 
    162   // Sets up FakeNetworkChangeNotifier as if it's connected to cellular network.
    163   void ConnectToCellular() {
    164     ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
    165   }
    166 
    167   // Sets up FakeNetworkChangeNotifier as if it's connected to wimax network.
    168   void ConnectToWimax() {
    169     ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
    170   }
    171 
    172   // Sets up FakeNetworkChangeNotifier as if it's disconnected.
    173   void ConnectToNone() {
    174     ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
    175   }
    176 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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