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