Home | History | Annotate | Download | only in drive_backend
      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/sync_engine_initializer.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/scoped_temp_dir.h"
      9 #include "base/run_loop.h"
     10 #include "base/thread_task_runner_handle.h"
     11 #include "chrome/browser/drive/drive_api_util.h"
     12 #include "chrome/browser/drive/drive_uploader.h"
     13 #include "chrome/browser/drive/fake_drive_service.h"
     14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
     15 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
     16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
     17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     18 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
     19 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
     20 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
     21 #include "content/public/test/test_browser_thread_bundle.h"
     22 #include "google_apis/drive/drive_api_parser.h"
     23 #include "google_apis/drive/gdata_wapi_parser.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
     26 #include "third_party/leveldatabase/src/include/leveldb/env.h"
     27 
     28 namespace sync_file_system {
     29 namespace drive_backend {
     30 
     31 namespace {
     32 
     33 const int64 kInitialLargestChangeID = 1234;
     34 
     35 }  // namespace
     36 
     37 class SyncEngineInitializerTest : public testing::Test {
     38  public:
     39   struct TrackedFile {
     40     scoped_ptr<google_apis::FileResource> resource;
     41     FileMetadata metadata;
     42     FileTracker tracker;
     43   };
     44 
     45   SyncEngineInitializerTest() {}
     46   virtual ~SyncEngineInitializerTest() {}
     47 
     48   virtual void SetUp() OVERRIDE {
     49     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     50     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
     51 
     52     scoped_ptr<drive::DriveServiceInterface>
     53         fake_drive_service(new drive::FakeDriveService);
     54 
     55     sync_context_.reset(new SyncEngineContext(
     56         fake_drive_service.Pass(),
     57         scoped_ptr<drive::DriveUploaderInterface>(),
     58         NULL,
     59         base::ThreadTaskRunnerHandle::Get(),
     60         base::ThreadTaskRunnerHandle::Get()));
     61 
     62     sync_task_manager_.reset(new SyncTaskManager(
     63         base::WeakPtr<SyncTaskManager::Client>(),
     64         1 /* maximum_parallel_task */,
     65         base::ThreadTaskRunnerHandle::Get()));
     66     sync_task_manager_->Initialize(SYNC_STATUS_OK);
     67   }
     68 
     69   virtual void TearDown() OVERRIDE {
     70     sync_task_manager_.reset();
     71     metadata_database_.reset();
     72     sync_context_.reset();
     73     base::RunLoop().RunUntilIdle();
     74   }
     75 
     76   base::FilePath database_path() {
     77     return database_dir_.path();
     78   }
     79 
     80   SyncStatusCode RunInitializer() {
     81     SyncEngineInitializer* initializer =
     82         new SyncEngineInitializer(sync_context_.get(),
     83                                   database_path(),
     84                                   in_memory_env_.get());
     85     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
     86 
     87     sync_task_manager_->ScheduleSyncTask(
     88         FROM_HERE,
     89         scoped_ptr<SyncTask>(initializer),
     90         SyncTaskManager::PRIORITY_MED,
     91         base::Bind(&SyncEngineInitializerTest::DidRunInitializer,
     92                    base::Unretained(this), initializer, &status));
     93 
     94     base::RunLoop().RunUntilIdle();
     95     return status;
     96   }
     97 
     98   void DidRunInitializer(SyncEngineInitializer* initializer,
     99                          SyncStatusCode* status_out,
    100                          SyncStatusCode status) {
    101     *status_out = status;
    102     metadata_database_ = initializer->PassMetadataDatabase();
    103   }
    104 
    105   SyncStatusCode PopulateDatabase(
    106       const google_apis::FileResource& sync_root,
    107       const google_apis::FileResource** app_roots,
    108       size_t app_roots_count) {
    109     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    110     scoped_ptr<MetadataDatabase> database = MetadataDatabase::Create(
    111         database_path(), in_memory_env_.get(), &status);
    112     if (status != SYNC_STATUS_OK)
    113       return status;
    114 
    115     // |app_root_list| must not own the resources here. Be sure to call
    116     // weak_clear later.
    117     ScopedVector<google_apis::FileResource> app_root_list;
    118     for (size_t i = 0; i < app_roots_count; ++i) {
    119       app_root_list.push_back(
    120           const_cast<google_apis::FileResource*>(app_roots[i]));
    121     }
    122 
    123     status = database->PopulateInitialData(
    124         kInitialLargestChangeID, sync_root, app_root_list);
    125 
    126     app_root_list.weak_clear();
    127     return status;
    128   }
    129 
    130   scoped_ptr<google_apis::FileResource> CreateRemoteFolder(
    131       const std::string& parent_folder_id,
    132       const std::string& title) {
    133     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
    134     scoped_ptr<google_apis::FileResource> entry;
    135     sync_context_->GetDriveService()->AddNewDirectory(
    136         parent_folder_id, title,
    137         drive::DriveServiceInterface::AddNewDirectoryOptions(),
    138         CreateResultReceiver(&error, &entry));
    139     base::RunLoop().RunUntilIdle();
    140 
    141     EXPECT_EQ(google_apis::HTTP_CREATED, error);
    142     return entry.Pass();
    143   }
    144 
    145   scoped_ptr<google_apis::FileResource> CreateRemoteSyncRoot() {
    146     scoped_ptr<google_apis::FileResource> sync_root(
    147         CreateRemoteFolder(std::string(), kSyncRootFolderTitle));
    148 
    149     for (size_t i = 0; i < sync_root->parents().size(); ++i) {
    150       google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
    151       sync_context_->GetDriveService()->RemoveResourceFromDirectory(
    152           sync_root->parents()[i].file_id(),
    153           sync_root->file_id(),
    154           CreateResultReceiver(&error));
    155       base::RunLoop().RunUntilIdle();
    156       EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error);
    157     }
    158 
    159     return sync_root.Pass();
    160   }
    161 
    162   std::string GetSyncRootFolderID() {
    163     int64 sync_root_tracker_id = metadata_database_->GetSyncRootTrackerID();
    164     FileTracker sync_root_tracker;
    165     EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID(
    166         sync_root_tracker_id, &sync_root_tracker));
    167     return sync_root_tracker.file_id();
    168   }
    169 
    170   size_t CountTrackersForFile(const std::string& file_id) {
    171     TrackerIDSet trackers;
    172     metadata_database_->FindTrackersByFileID(file_id, &trackers);
    173     return trackers.size();
    174   }
    175 
    176   bool HasActiveTracker(const std::string& file_id) {
    177     TrackerIDSet trackers;
    178     return metadata_database_->FindTrackersByFileID(file_id, &trackers) &&
    179         trackers.has_active();
    180   }
    181 
    182   bool HasNoParent(const std::string& file_id) {
    183     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
    184     scoped_ptr<google_apis::FileResource> entry;
    185     sync_context_->GetDriveService()->GetFileResource(
    186         file_id,
    187         CreateResultReceiver(&error, &entry));
    188     base::RunLoop().RunUntilIdle();
    189     EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
    190     return entry->parents().empty();
    191   }
    192 
    193   size_t CountFileMetadata() {
    194     return metadata_database_->CountFileMetadata();
    195   }
    196 
    197   size_t CountFileTracker() {
    198     return metadata_database_->CountFileTracker();
    199   }
    200 
    201   google_apis::GDataErrorCode AddParentFolder(
    202       const std::string& new_parent_folder_id,
    203       const std::string& file_id) {
    204     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
    205     sync_context_->GetDriveService()->AddResourceToDirectory(
    206         new_parent_folder_id, file_id,
    207         CreateResultReceiver(&error));
    208     base::RunLoop().RunUntilIdle();
    209     return error;
    210   }
    211 
    212  private:
    213   content::TestBrowserThreadBundle browser_threads_;
    214   base::ScopedTempDir database_dir_;
    215   scoped_ptr<leveldb::Env> in_memory_env_;
    216 
    217   scoped_ptr<MetadataDatabase> metadata_database_;
    218   scoped_ptr<SyncTaskManager> sync_task_manager_;
    219   scoped_ptr<SyncEngineContext> sync_context_;
    220 
    221   DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest);
    222 };
    223 
    224 TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) {
    225   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    226 
    227   std::string sync_root_folder_id = GetSyncRootFolderID();
    228   EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id));
    229 
    230   EXPECT_TRUE(HasActiveTracker(sync_root_folder_id));
    231 
    232   EXPECT_EQ(1u, CountFileMetadata());
    233   EXPECT_EQ(1u, CountFileTracker());
    234 }
    235 
    236 TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) {
    237   scoped_ptr<google_apis::FileResource> sync_root(
    238       CreateRemoteSyncRoot());
    239   scoped_ptr<google_apis::FileResource> app_root_1(
    240       CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
    241   scoped_ptr<google_apis::FileResource> app_root_2(
    242       CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
    243 
    244   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    245 
    246   EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
    247   EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
    248   EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
    249 
    250   EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
    251   EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
    252   EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
    253 
    254   EXPECT_EQ(3u, CountFileMetadata());
    255   EXPECT_EQ(3u, CountFileTracker());
    256 }
    257 
    258 TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) {
    259   scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot());
    260   scoped_ptr<google_apis::FileResource> app_root_1(
    261       CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
    262   scoped_ptr<google_apis::FileResource> app_root_2(
    263       CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
    264 
    265   const google_apis::FileResource* app_roots[] = {
    266     app_root_1.get(), app_root_2.get()
    267   };
    268   EXPECT_EQ(SYNC_STATUS_OK,
    269             PopulateDatabase(*sync_root, app_roots, arraysize(app_roots)));
    270 
    271   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    272 
    273   EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
    274   EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
    275   EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
    276 
    277   EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
    278   EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
    279   EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
    280 
    281   EXPECT_EQ(3u, CountFileMetadata());
    282   EXPECT_EQ(3u, CountFileTracker());
    283 }
    284 
    285 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) {
    286   scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot());
    287   scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot());
    288 
    289   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    290 
    291   EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id()));
    292   EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id()));
    293 
    294   EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id()));
    295   EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id()));
    296 
    297   EXPECT_EQ(1u, CountFileMetadata());
    298   EXPECT_EQ(1u, CountFileTracker());
    299 }
    300 
    301 TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) {
    302   scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
    303       std::string(), kSyncRootFolderTitle));
    304   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    305 
    306   EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
    307   EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
    308 
    309   EXPECT_TRUE(HasNoParent(sync_root->file_id()));
    310 
    311   EXPECT_EQ(1u, CountFileMetadata());
    312   EXPECT_EQ(1u, CountFileTracker());
    313 }
    314 
    315 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) {
    316   scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
    317       std::string(), "folder"));
    318   scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
    319       std::string(), kSyncRootFolderTitle));
    320   AddParentFolder(sync_root->file_id(), folder->file_id());
    321 
    322   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    323 
    324   EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
    325   EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
    326 
    327   EXPECT_TRUE(HasNoParent(sync_root->file_id()));
    328 
    329   EXPECT_EQ(1u, CountFileMetadata());
    330   EXPECT_EQ(1u, CountFileTracker());
    331 }
    332 
    333 TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) {
    334   scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
    335       std::string(), "folder"));
    336   scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
    337       folder->file_id(), kSyncRootFolderTitle));
    338 
    339   EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
    340 
    341   EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id()));
    342   EXPECT_FALSE(HasNoParent(sync_root->file_id()));
    343 
    344   EXPECT_EQ(1u, CountFileMetadata());
    345   EXPECT_EQ(1u, CountFileTracker());
    346 }
    347 
    348 }  // namespace drive_backend
    349 }  // namespace sync_file_system
    350