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