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/register_app_task.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/format_macros.h"
     11 #include "base/run_loop.h"
     12 #include "base/strings/string_number_conversions.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/thread_task_runner_handle.h"
     15 #include "chrome/browser/drive/drive_uploader.h"
     16 #include "chrome/browser/drive/fake_drive_service.h"
     17 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
     18 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
     19 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
     20 #include "chrome/browser/sync_file_system/drive_backend/leveldb_wrapper.h"
     21 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
     22 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     23 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
     24 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
     25 #include "content/public/test/test_browser_thread_bundle.h"
     26 #include "google_apis/drive/drive_api_parser.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
     29 #include "third_party/leveldatabase/src/include/leveldb/db.h"
     30 #include "third_party/leveldatabase/src/include/leveldb/env.h"
     31 
     32 namespace sync_file_system {
     33 namespace drive_backend {
     34 
     35 namespace {
     36 const int64 kSyncRootTrackerID = 100;
     37 }  // namespace
     38 
     39 class RegisterAppTaskTest : public testing::Test {
     40  public:
     41   RegisterAppTaskTest()
     42       : next_file_id_(1000),
     43         next_tracker_id_(10000) {}
     44   virtual ~RegisterAppTaskTest() {}
     45 
     46   virtual void SetUp() OVERRIDE {
     47     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     48     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
     49 
     50     scoped_ptr<drive::FakeDriveService>
     51         fake_drive_service(new drive::FakeDriveService);
     52     scoped_ptr<drive::DriveUploaderInterface>
     53         drive_uploader(new drive::DriveUploader(
     54             fake_drive_service.get(),
     55             base::ThreadTaskRunnerHandle::Get()));
     56 
     57     fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
     58         fake_drive_service.get(), drive_uploader.get(),
     59         kSyncRootFolderTitle));
     60 
     61     context_.reset(
     62         new SyncEngineContext(
     63             fake_drive_service.PassAs<drive::DriveServiceInterface>(),
     64             drive_uploader.Pass(),
     65             NULL,
     66             base::ThreadTaskRunnerHandle::Get(),
     67             base::ThreadTaskRunnerHandle::Get()));
     68 
     69     ASSERT_EQ(google_apis::HTTP_CREATED,
     70               fake_drive_service_helper_->AddOrphanedFolder(
     71                   kSyncRootFolderTitle, &sync_root_folder_id_));
     72   }
     73 
     74   virtual void TearDown() OVERRIDE {
     75     context_.reset();
     76     base::RunLoop().RunUntilIdle();
     77   }
     78 
     79  protected:
     80   scoped_ptr<LevelDBWrapper> OpenLevelDB() {
     81     leveldb::DB* db = NULL;
     82     leveldb::Options options;
     83     options.create_if_missing = true;
     84     options.env = in_memory_env_.get();
     85     leveldb::Status status =
     86         leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
     87     EXPECT_TRUE(status.ok());
     88     return make_scoped_ptr(new LevelDBWrapper(make_scoped_ptr(db)));
     89   }
     90 
     91   void SetUpInitialData(LevelDBWrapper* db) {
     92     ServiceMetadata service_metadata;
     93     service_metadata.set_largest_change_id(100);
     94     service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
     95     service_metadata.set_next_tracker_id(next_tracker_id_);
     96 
     97     FileDetails sync_root_details;
     98     sync_root_details.set_title(kSyncRootFolderTitle);
     99     sync_root_details.set_file_kind(FILE_KIND_FOLDER);
    100     sync_root_details.set_change_id(1);
    101 
    102     FileMetadata sync_root_metadata;
    103     sync_root_metadata.set_file_id(sync_root_folder_id_);
    104     *sync_root_metadata.mutable_details() = sync_root_details;
    105 
    106     FileTracker sync_root_tracker;
    107     sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id());
    108     sync_root_tracker.set_parent_tracker_id(0);
    109     sync_root_tracker.set_file_id(sync_root_metadata.file_id());
    110     sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
    111     *sync_root_tracker.mutable_synced_details() = sync_root_details;
    112     sync_root_tracker.set_active(true);
    113 
    114     db->Put(kDatabaseVersionKey,
    115             base::Int64ToString(kCurrentDatabaseVersion));
    116     PutServiceMetadataToDB(service_metadata, db);
    117     PutFileMetadataToDB(sync_root_metadata, db);
    118     PutFileTrackerToDB(sync_root_tracker, db);
    119     EXPECT_TRUE(db->Commit().ok());
    120   }
    121 
    122   void CreateMetadataDatabase(scoped_ptr<LevelDBWrapper> db) {
    123     ASSERT_TRUE(db);
    124     ASSERT_FALSE(context_->GetMetadataDatabase());
    125     scoped_ptr<MetadataDatabase> metadata_db;
    126     ASSERT_EQ(SYNC_STATUS_OK,
    127               MetadataDatabase::CreateForTesting(
    128                   db.Pass(), true /* enable_on_disk_index */, &metadata_db));
    129     context_->SetMetadataDatabase(metadata_db.Pass());
    130   }
    131 
    132   SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
    133     RegisterAppTask task(context_.get(), app_id);
    134     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    135     task.RunExclusive(CreateResultReceiver(&status));
    136     base::RunLoop().RunUntilIdle();
    137     return status;
    138   }
    139 
    140   void SetUpRegisteredAppRoot(
    141       const std::string& app_id,
    142       LevelDBWrapper* db) {
    143     FileDetails details;
    144     details.set_title(app_id);
    145     details.set_file_kind(FILE_KIND_FOLDER);
    146     details.add_parent_folder_ids(sync_root_folder_id_);
    147 
    148     FileMetadata metadata;
    149     metadata.set_file_id(GenerateFileID());
    150     *metadata.mutable_details() = details;
    151 
    152     FileTracker tracker;
    153     tracker.set_parent_tracker_id(kSyncRootTrackerID);
    154     tracker.set_tracker_id(next_tracker_id_++);
    155     tracker.set_file_id(metadata.file_id());
    156     tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    157     tracker.set_app_id(app_id);
    158     *tracker.mutable_synced_details() = details;
    159     tracker.set_active(true);
    160 
    161     PutFileMetadataToDB(metadata, db);
    162     PutFileTrackerToDB(tracker, db);
    163     EXPECT_TRUE(db->Commit().ok());
    164   }
    165 
    166   void SetUpUnregisteredAppRoot(const std::string& app_id,
    167                                 LevelDBWrapper* db) {
    168     FileDetails details;
    169     details.set_title(app_id);
    170     details.set_file_kind(FILE_KIND_FOLDER);
    171     details.add_parent_folder_ids(sync_root_folder_id_);
    172 
    173     FileMetadata metadata;
    174     metadata.set_file_id(GenerateFileID());
    175     *metadata.mutable_details() = details;
    176 
    177     FileTracker tracker;
    178     tracker.set_parent_tracker_id(kSyncRootTrackerID);
    179     tracker.set_tracker_id(next_tracker_id_++);
    180     tracker.set_file_id(metadata.file_id());
    181     tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
    182     *tracker.mutable_synced_details() = details;
    183     tracker.set_active(false);
    184 
    185     PutFileMetadataToDB(metadata, db);
    186     PutFileTrackerToDB(tracker, db);
    187     EXPECT_TRUE(db->Commit().ok());
    188   }
    189 
    190   size_t CountRegisteredAppRoot() {
    191     std::vector<std::string> app_ids;
    192     context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
    193     return app_ids.size();
    194   }
    195 
    196   bool IsAppRegistered(const std::string& app_id) {
    197     TrackerIDSet trackers;
    198     if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
    199             kSyncRootTrackerID, app_id, &trackers))
    200       return false;
    201     return trackers.has_active();
    202   }
    203 
    204   size_t CountRemoteFileInSyncRoot() {
    205     ScopedVector<google_apis::ResourceEntry> files;
    206     EXPECT_EQ(google_apis::HTTP_SUCCESS,
    207               fake_drive_service_helper_->ListFilesInFolder(
    208                   sync_root_folder_id_, &files));
    209     return files.size();
    210   }
    211 
    212   bool HasRemoteAppRoot(const std::string& app_id) {
    213     TrackerIDSet files;
    214     if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
    215             kSyncRootTrackerID, app_id, &files) ||
    216         !files.has_active())
    217       return false;
    218 
    219     FileTracker app_root_tracker;
    220     EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
    221         files.active_tracker(), &app_root_tracker));
    222     std::string app_root_folder_id = app_root_tracker.file_id();
    223     scoped_ptr<google_apis::FileResource> entry;
    224     if (google_apis::HTTP_SUCCESS !=
    225         fake_drive_service_helper_->GetFileResource(app_root_folder_id, &entry))
    226       return false;
    227 
    228     return !entry->labels().is_trashed();
    229   }
    230 
    231  private:
    232   std::string GenerateFileID() {
    233     return base::StringPrintf("file_id_%" PRId64, next_file_id_++);
    234   }
    235 
    236   scoped_ptr<leveldb::Env> in_memory_env_;
    237 
    238   std::string sync_root_folder_id_;
    239 
    240   int64 next_file_id_;
    241   int64 next_tracker_id_;
    242 
    243   content::TestBrowserThreadBundle browser_threads_;
    244   base::ScopedTempDir database_dir_;
    245 
    246   scoped_ptr<SyncEngineContext> context_;
    247   scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
    248 
    249   DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
    250 };
    251 
    252 TEST_F(RegisterAppTaskTest, AlreadyRegistered) {
    253   scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
    254   ASSERT_TRUE(db);
    255   SetUpInitialData(db.get());
    256 
    257   const std::string kAppID = "app_id";
    258   SetUpRegisteredAppRoot(kAppID, db.get());
    259 
    260   CreateMetadataDatabase(db.Pass());
    261   EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID));
    262 
    263   EXPECT_EQ(1u, CountRegisteredAppRoot());
    264   EXPECT_TRUE(IsAppRegistered(kAppID));
    265 }
    266 
    267 TEST_F(RegisterAppTaskTest, CreateAppFolder) {
    268   scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
    269   ASSERT_TRUE(db);
    270   SetUpInitialData(db.get());
    271 
    272   const std::string kAppID = "app_id";
    273   CreateMetadataDatabase(db.Pass());
    274   RunRegisterAppTask(kAppID);
    275 
    276   EXPECT_EQ(1u, CountRegisteredAppRoot());
    277   EXPECT_TRUE(IsAppRegistered(kAppID));
    278 
    279   EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
    280   EXPECT_TRUE(HasRemoteAppRoot(kAppID));
    281 }
    282 
    283 TEST_F(RegisterAppTaskTest, RegisterExistingFolder) {
    284   scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
    285   ASSERT_TRUE(db);
    286   SetUpInitialData(db.get());
    287 
    288   const std::string kAppID = "app_id";
    289   SetUpUnregisteredAppRoot(kAppID, db.get());
    290 
    291   CreateMetadataDatabase(db.Pass());
    292   RunRegisterAppTask(kAppID);
    293 
    294   EXPECT_EQ(1u, CountRegisteredAppRoot());
    295   EXPECT_TRUE(IsAppRegistered(kAppID));
    296 }
    297 
    298 TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) {
    299   scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
    300   ASSERT_TRUE(db);
    301   SetUpInitialData(db.get());
    302 
    303   const std::string kAppID = "app_id";
    304   SetUpUnregisteredAppRoot(kAppID, db.get());
    305   SetUpUnregisteredAppRoot(kAppID, db.get());
    306 
    307   CreateMetadataDatabase(db.Pass());
    308   RunRegisterAppTask(kAppID);
    309 
    310   EXPECT_EQ(1u, CountRegisteredAppRoot());
    311   EXPECT_TRUE(IsAppRegistered(kAppID));
    312 }
    313 
    314 }  // namespace drive_backend
    315 }  // namespace sync_file_system
    316