Home | History | Annotate | Download | only in drive_backend_v1
      1 // Copyright 2013 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/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop_proxy.h"
      9 #include "base/run_loop.h"
     10 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
     11 #include "chrome/browser/sync_file_system/drive_backend_v1/fake_api_util.h"
     12 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
     13 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     14 #include "chrome/test/base/testing_profile.h"
     15 #include "content/public/test/test_browser_thread_bundle.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace sync_file_system {
     19 
     20 using drive_backend::APIUtilInterface;
     21 using drive_backend::FakeAPIUtil;
     22 
     23 namespace {
     24 
     25 const char kSyncRootResourceId[] = "folder:sync_root_resource_id";
     26 
     27 void DidInitialize(bool* done, SyncStatusCode status, bool created) {
     28   EXPECT_EQ(SYNC_STATUS_OK, status);
     29   *done = true;
     30 }
     31 
     32 void ExpectEqStatus(bool* done,
     33                     SyncStatusCode expected,
     34                     SyncStatusCode actual) {
     35   EXPECT_FALSE(*done);
     36   *done = true;
     37   EXPECT_EQ(expected, actual);
     38 }
     39 
     40 void ExpectOkStatus(SyncStatusCode status) {
     41   EXPECT_EQ(SYNC_STATUS_OK, status);
     42 }
     43 
     44 }  // namespace
     45 
     46 class DriveFileSyncServiceTest : public testing::Test {
     47  public:
     48   DriveFileSyncServiceTest()
     49       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
     50         fake_api_util_(NULL),
     51         metadata_store_(NULL) {}
     52 
     53   virtual void SetUp() OVERRIDE {
     54     RegisterSyncableFileSystem();
     55     fake_api_util_ = new FakeAPIUtil;
     56 
     57     ASSERT_TRUE(scoped_base_dir_.CreateUniqueTempDir());
     58     base_dir_ = scoped_base_dir_.path();
     59     metadata_store_ = new DriveMetadataStore(
     60         base_dir_, base::MessageLoopProxy::current().get());
     61     bool done = false;
     62     metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
     63     base::RunLoop().RunUntilIdle();
     64     metadata_store_->SetSyncRootDirectory(kSyncRootResourceId);
     65     EXPECT_TRUE(done);
     66 
     67     sync_service_ = DriveFileSyncService::CreateForTesting(
     68         &profile_,
     69         base_dir_,
     70         scoped_ptr<APIUtilInterface>(fake_api_util_),
     71         scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
     72     base::RunLoop().RunUntilIdle();
     73   }
     74 
     75   virtual void TearDown() OVERRIDE {
     76     metadata_store_ = NULL;
     77     fake_api_util_ = NULL;
     78     sync_service_.reset();
     79     base::RunLoop().RunUntilIdle();
     80 
     81     base_dir_ = base::FilePath();
     82     RevokeSyncableFileSystem();
     83   }
     84 
     85   virtual ~DriveFileSyncServiceTest() {
     86   }
     87 
     88  protected:
     89   FakeAPIUtil* fake_api_util() { return fake_api_util_; }
     90   DriveMetadataStore* metadata_store() { return metadata_store_; }
     91   DriveFileSyncService* sync_service() { return sync_service_.get(); }
     92   std::map<GURL, std::string>* pending_batch_sync_origins() {
     93     return &(sync_service()->pending_batch_sync_origins_);
     94   }
     95 
     96   // Helper function to add an origin to the given origin sync status. To make
     97   // naming easier, each origin, resourceID, etc. will all share the same
     98   // prefixes and only be distinguished by the given suffix ID which could be a
     99   // number (1, 2, 3, etc.) or a letter (A, B, C, etc.).
    100   // e.g. originA, originB, folder:resource_idA, folder:resource_idB, etc.
    101   void AddOrigin(std::string status, const char* suffix) {
    102     const GURL origin(std::string("chrome-extension://app_") + suffix);
    103     const std::string resource_id(std::string("folder:resource_id") + suffix);
    104 
    105     if (status == "Pending") {
    106       pending_batch_sync_origins()->insert(std::make_pair(origin, resource_id));
    107     } else if (status == "Enabled") {
    108       metadata_store()->AddIncrementalSyncOrigin(origin, resource_id);
    109     } else if (status == "Disabled") {
    110       metadata_store()->AddIncrementalSyncOrigin(origin, resource_id);
    111       metadata_store()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
    112     } else {
    113       NOTREACHED();
    114     }
    115   }
    116 
    117   bool VerifyOriginStatusCount(size_t expected_pending,
    118                                size_t expected_enabled,
    119                                size_t expected_disabled) {
    120     size_t actual_pending = pending_batch_sync_origins()->size();
    121     size_t actual_enabled = metadata_store()->incremental_sync_origins().size();
    122     size_t actual_disabled = metadata_store()->disabled_origins().size();
    123 
    124     // Prints which counts don't match up if any.
    125     EXPECT_EQ(expected_pending, actual_pending);
    126     EXPECT_EQ(expected_enabled, actual_enabled);
    127     EXPECT_EQ(expected_disabled, actual_disabled);
    128 
    129     // If any count doesn't match, the original line number can be printed by
    130     // simply adding ASSERT_TRUE on the call to this function.
    131     if (expected_pending == actual_pending &&
    132         expected_enabled == actual_enabled &&
    133         expected_disabled == actual_disabled)
    134       return true;
    135 
    136     return false;
    137   }
    138 
    139  private:
    140   base::ScopedTempDir scoped_base_dir_;
    141   content::TestBrowserThreadBundle thread_bundle_;
    142 
    143   TestingProfile profile_;
    144   base::FilePath base_dir_;
    145 
    146   FakeAPIUtil* fake_api_util_;          // Owned by |sync_service_|.
    147   DriveMetadataStore* metadata_store_;  // Owned by |sync_service_|.
    148 
    149   scoped_ptr<DriveFileSyncService> sync_service_;
    150 
    151   DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceTest);
    152 };
    153 
    154 TEST_F(DriveFileSyncServiceTest, UninstallOrigin) {
    155   // Add fake app origin directory using fake drive_sync_client.
    156   std::string origin_dir_resource_id = "uninstalledappresourceid";
    157   fake_api_util()->PushRemoteChange("parent_id",
    158                                     "parent_title",
    159                                     "uninstall_me_folder",
    160                                     origin_dir_resource_id,
    161                                     "resource_md5",
    162                                     SYNC_FILE_TYPE_FILE,
    163                                     false);
    164 
    165   // Add meta_data entry so GURL->resourse_id mapping is there.
    166   const GURL origin_gurl("chrome-extension://uninstallme");
    167   metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
    168                                              origin_dir_resource_id);
    169 
    170   // Delete the origin directory.
    171   bool done = false;
    172   sync_service()->UninstallOrigin(
    173       origin_gurl,
    174       RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
    175       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
    176   base::RunLoop().RunUntilIdle();
    177   EXPECT_TRUE(done);
    178 
    179   // Assert the App's origin folder was marked as deleted.
    180   EXPECT_TRUE(fake_api_util()->remote_resources().find(
    181       origin_dir_resource_id)->second.deleted);
    182 }
    183 
    184 TEST_F(DriveFileSyncServiceTest, UninstallUnpackedOrigin) {
    185   // Add fake app origin directory using fake drive_sync_client.
    186   std::string origin_dir_resource_id = "uninstalledappresourceid";
    187   fake_api_util()->PushRemoteChange("parent_id",
    188                                     "parent_title",
    189                                     "uninstall_me_folder",
    190                                     origin_dir_resource_id,
    191                                     "resource_md5",
    192                                     SYNC_FILE_TYPE_FILE,
    193                                     false);
    194 
    195   // Add meta_data entry so GURL->resourse_id mapping is there.
    196   const GURL origin_gurl("chrome-extension://uninstallme");
    197   metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
    198                                              origin_dir_resource_id);
    199 
    200   // Uninstall the origin.
    201   bool done = false;
    202   sync_service()->UninstallOrigin(
    203       origin_gurl,
    204       RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
    205       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
    206   base::RunLoop().RunUntilIdle();
    207   EXPECT_TRUE(done);
    208 
    209   // Assert the App's origin folder has not been deleted.
    210   EXPECT_FALSE(fake_api_util()->remote_resources().find(
    211       origin_dir_resource_id)->second.deleted);
    212 }
    213 
    214 TEST_F(DriveFileSyncServiceTest, UninstallOriginWithoutOriginDirectory) {
    215   // Not add fake app origin directory.
    216   std::string origin_dir_resource_id = "uninstalledappresourceid";
    217 
    218   // Add meta_data entry so GURL->resourse_id mapping is there.
    219   const GURL origin_gurl("chrome-extension://uninstallme");
    220   metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
    221                                              origin_dir_resource_id);
    222 
    223   // Delete the origin directory (but not found).
    224   bool done = false;
    225   sync_service()->UninstallOrigin(
    226       origin_gurl,
    227       RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
    228       base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
    229   base::RunLoop().RunUntilIdle();
    230   EXPECT_TRUE(done);
    231 
    232   // Assert the App's origin folder does not exist.
    233   const FakeAPIUtil::RemoteResourceByResourceId& remote_resources =
    234       fake_api_util()->remote_resources();
    235   EXPECT_TRUE(remote_resources.find(origin_dir_resource_id) ==
    236               remote_resources.end());
    237 }
    238 
    239 TEST_F(DriveFileSyncServiceTest, DisableOriginPendingOrigin) {
    240   // Disable a pending origin after DriveFileSystemService has already started.
    241   const GURL origin("chrome-extension://app");
    242   std::string origin_resource_id = "app_resource_id";
    243   pending_batch_sync_origins()->insert(std::make_pair(origin,
    244                                                       origin_resource_id));
    245   ASSERT_TRUE(VerifyOriginStatusCount(1u, 0u, 0u));
    246 
    247   // Pending origins that are disabled are dropped and do not go to disabled.
    248   sync_service()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
    249   base::RunLoop().RunUntilIdle();
    250   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 0u));
    251 }
    252 
    253 TEST_F(DriveFileSyncServiceTest,
    254        DisableOriginIncrementalOrigin) {
    255   // Disable a pending origin after DriveFileSystemService has already started.
    256   const GURL origin("chrome-extension://app");
    257   std::string origin_resource_id = "app_resource_id";
    258   metadata_store()->AddIncrementalSyncOrigin(origin, origin_resource_id);
    259   ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
    260 
    261   sync_service()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
    262   base::RunLoop().RunUntilIdle();
    263   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
    264 }
    265 
    266 TEST_F(DriveFileSyncServiceTest, EnableOrigin) {
    267   const GURL origin("chrome-extension://app");
    268   std::string origin_resource_id = "app_resource_id";
    269   metadata_store()->AddIncrementalSyncOrigin(origin, origin_resource_id);
    270   metadata_store()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
    271   ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
    272 
    273   // Re-enable the previously disabled origin. It initially goes to pending
    274   // status and then to enabled (incremental) again when NotifyTasksDone() in
    275   // SyncTaskManager invokes MaybeStartFetchChanges() and pending
    276   // origins > 0.
    277   sync_service()->EnableOrigin(origin, base::Bind(&ExpectOkStatus));
    278   base::RunLoop().RunUntilIdle();
    279   ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
    280 }
    281 
    282 TEST_F(DriveFileSyncServiceTest, GetOriginStatusMap) {
    283   RemoteFileSyncService::OriginStatusMap origin_status_map;
    284   sync_service()->GetOriginStatusMap(&origin_status_map);
    285   ASSERT_EQ(0u, origin_status_map.size());
    286 
    287   // Add 3 pending, 2 enabled and 1 disabled sync origin.
    288   AddOrigin("Pending", "p0");
    289   AddOrigin("Pending", "p1");
    290   AddOrigin("Pending", "p2");
    291   AddOrigin("Enabled", "e0");
    292   AddOrigin("Enabled", "e1");
    293   AddOrigin("Disabled", "d0");
    294 
    295   sync_service()->GetOriginStatusMap(&origin_status_map);
    296   ASSERT_EQ(6u, origin_status_map.size());
    297   EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p0")]);
    298   EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p1")]);
    299   EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p2")]);
    300   EXPECT_EQ("Enabled", origin_status_map[GURL("chrome-extension://app_e0")]);
    301   EXPECT_EQ("Enabled", origin_status_map[GURL("chrome-extension://app_e1")]);
    302   EXPECT_EQ("Disabled", origin_status_map[GURL("chrome-extension://app_d0")]);
    303 }
    304 
    305 }  // namespace sync_file_system
    306