sync_engine_unittest.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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.h"
6
7#include "base/files/scoped_temp_dir.h"
8#include "base/run_loop.h"
9#include "base/strings/stringprintf.h"
10#include "chrome/browser/drive/drive_uploader.h"
11#include "chrome/browser/drive/fake_drive_service.h"
12#include "chrome/browser/extensions/test_extension_service.h"
13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
14#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
15#include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
16#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
17#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
18#include "content/public/test/test_browser_thread_bundle.h"
19#include "extensions/common/extension.h"
20#include "extensions/common/extension_builder.h"
21#include "extensions/common/extension_set.h"
22#include "extensions/common/value_builder.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
25#include "third_party/leveldatabase/src/include/leveldb/env.h"
26
27namespace sync_file_system {
28namespace drive_backend {
29
30namespace {
31
32const char kAppID[] = "app_id";
33
34void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
35  base::MessageLoop::current()->PostTask(
36      FROM_HERE, base::Bind(callback, status));
37}
38
39}  // namespace
40
41class MockSyncTask : public ExclusiveTask {
42 public:
43  explicit MockSyncTask(bool used_network) {
44    set_used_network(used_network);
45  }
46  virtual ~MockSyncTask() {}
47
48  virtual void RunExclusive(const SyncStatusCallback& callback) OVERRIDE {
49    callback.Run(SYNC_STATUS_OK);
50  }
51
52 private:
53  DISALLOW_COPY_AND_ASSIGN(MockSyncTask);
54};
55
56class MockExtensionService : public TestExtensionService {
57 public:
58  MockExtensionService() {}
59  virtual ~MockExtensionService() {}
60
61  virtual const extensions::ExtensionSet* extensions() const OVERRIDE {
62    return &extensions_;
63  }
64
65  virtual void AddExtension(const extensions::Extension* extension) OVERRIDE {
66    extensions_.Insert(make_scoped_refptr(extension));
67  }
68
69  virtual const extensions::Extension* GetInstalledExtension(
70      const std::string& extension_id) const OVERRIDE {
71    return extensions_.GetByID(extension_id);
72  }
73
74  virtual bool IsExtensionEnabled(
75      const std::string& extension_id) const OVERRIDE {
76    return extensions_.Contains(extension_id) &&
77        !disabled_extensions_.Contains(extension_id);
78  }
79
80  void UninstallExtension(const std::string& extension_id) {
81    extensions_.Remove(extension_id);
82    disabled_extensions_.Remove(extension_id);
83  }
84
85  void DisableExtension(const std::string& extension_id) {
86    if (!IsExtensionEnabled(extension_id))
87      return;
88    const extensions::Extension* extension = extensions_.GetByID(extension_id);
89    disabled_extensions_.Insert(make_scoped_refptr(extension));
90  }
91
92 private:
93  extensions::ExtensionSet extensions_;
94  extensions::ExtensionSet disabled_extensions_;
95
96  DISALLOW_COPY_AND_ASSIGN(MockExtensionService);
97};
98
99class SyncEngineTest
100    : public testing::Test,
101      public base::SupportsWeakPtr<SyncEngineTest> {
102 public:
103  SyncEngineTest() {}
104  virtual ~SyncEngineTest() {}
105
106  virtual void SetUp() OVERRIDE {
107    ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
108    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
109
110    extension_service_.reset(new MockExtensionService);
111    scoped_ptr<drive::FakeDriveService> fake_drive_service(
112        new drive::FakeDriveService);
113
114    sync_engine_.reset(new drive_backend::SyncEngine(
115        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
116        scoped_ptr<drive::DriveUploaderInterface>(),
117        NULL /* notification_manager */,
118        extension_service_.get(),
119        NULL /* signin_manager */));
120    sync_engine_->Initialize(profile_dir_.path(),
121                             base::MessageLoopProxy::current(),
122                             in_memory_env_.get());
123    sync_engine_->SetSyncEnabled(true);
124    base::RunLoop().RunUntilIdle();
125  }
126
127  virtual void TearDown() OVERRIDE {
128    sync_engine_.reset();
129    extension_service_.reset();
130    base::RunLoop().RunUntilIdle();
131  }
132
133  MockExtensionService* extension_service() { return extension_service_.get(); }
134  SyncEngine* sync_engine() { return sync_engine_.get(); }
135
136  void UpdateRegisteredApps() {
137    sync_engine_->UpdateRegisteredApps();
138  }
139
140  SyncTaskManager* GetSyncEngineTaskManager() {
141    return sync_engine_->GetSyncTaskManagerForTesting();
142  }
143
144  void CheckServiceState(SyncStatusCode expected_sync_status,
145                         RemoteServiceState expected_service_status,
146                         SyncStatusCode sync_status) {
147    EXPECT_EQ(expected_sync_status, sync_status);
148    EXPECT_EQ(expected_service_status, sync_engine_->GetCurrentState());
149  }
150
151 private:
152  content::TestBrowserThreadBundle browser_threads_;
153  base::ScopedTempDir profile_dir_;
154  scoped_ptr<leveldb::Env> in_memory_env_;
155
156  scoped_ptr<MockExtensionService> extension_service_;
157  scoped_ptr<drive_backend::SyncEngine> sync_engine_;
158
159  DISALLOW_COPY_AND_ASSIGN(SyncEngineTest);
160};
161
162TEST_F(SyncEngineTest, EnableOrigin) {
163  FileTracker tracker;
164  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
165  MetadataDatabase* metadata_database = sync_engine()->GetMetadataDatabase();
166  GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
167
168  sync_engine()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
169  base::RunLoop().RunUntilIdle();
170  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
171  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
172  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
173
174  sync_engine()->DisableOrigin(origin, CreateResultReceiver(&sync_status));
175  base::RunLoop().RunUntilIdle();
176  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
177  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
178  EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
179
180  sync_engine()->EnableOrigin(origin, CreateResultReceiver(&sync_status));
181  base::RunLoop().RunUntilIdle();
182  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
183  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
184  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
185
186  sync_engine()->UninstallOrigin(
187      origin,
188      RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
189      CreateResultReceiver(&sync_status));
190  base::RunLoop().RunUntilIdle();
191  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
192  ASSERT_FALSE(metadata_database->FindAppRootTracker(kAppID, &tracker));
193}
194
195TEST_F(SyncEngineTest, UpdateRegisteredApps) {
196  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
197  for (int i = 0; i < 3; i++) {
198    scoped_refptr<const extensions::Extension> extension =
199        extensions::ExtensionBuilder()
200        .SetManifest(extensions::DictionaryBuilder()
201                     .Set("name", "foo")
202                     .Set("version", "1.0")
203                     .Set("manifest_version", 2))
204        .SetID(base::StringPrintf("app_%d", i))
205        .Build();
206    extension_service()->AddExtension(extension.get());
207    GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
208        extension->id());
209    sync_status = SYNC_STATUS_UNKNOWN;
210    sync_engine()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
211    base::RunLoop().RunUntilIdle();
212    EXPECT_EQ(SYNC_STATUS_OK, sync_status);
213  }
214
215  MetadataDatabase* metadata_database = sync_engine()->GetMetadataDatabase();
216  FileTracker tracker;
217
218  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_0", &tracker));
219  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
220
221  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_1", &tracker));
222  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
223
224  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_2", &tracker));
225  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
226
227  extension_service()->DisableExtension("app_1");
228  extension_service()->UninstallExtension("app_2");
229  ASSERT_FALSE(extension_service()->GetInstalledExtension("app_2"));
230  UpdateRegisteredApps();
231  base::RunLoop().RunUntilIdle();
232
233  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_0", &tracker));
234  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
235
236  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_1", &tracker));
237  EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
238
239  ASSERT_FALSE(metadata_database->FindAppRootTracker("app_2", &tracker));
240}
241
242TEST_F(SyncEngineTest, GetOriginStatusMap) {
243  FileTracker tracker;
244  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
245  GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
246
247  sync_engine()->RegisterOrigin(GURL("chrome-extension://app_0"),
248                                     CreateResultReceiver(&sync_status));
249  base::RunLoop().RunUntilIdle();
250  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
251
252  sync_engine()->RegisterOrigin(GURL("chrome-extension://app_1"),
253                                     CreateResultReceiver(&sync_status));
254  base::RunLoop().RunUntilIdle();
255  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
256
257  RemoteFileSyncService::OriginStatusMap status_map;
258  sync_engine()->GetOriginStatusMap(&status_map);
259  ASSERT_EQ(2u, status_map.size());
260  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_0")]);
261  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_1")]);
262
263  sync_engine()->DisableOrigin(GURL("chrome-extension://app_1"),
264                               CreateResultReceiver(&sync_status));
265  base::RunLoop().RunUntilIdle();
266  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
267
268  sync_engine()->GetOriginStatusMap(&status_map);
269  ASSERT_EQ(2u, status_map.size());
270  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_0")]);
271  EXPECT_EQ("Disabled", status_map[GURL("chrome-extension://app_1")]);
272}
273
274TEST_F(SyncEngineTest, UpdateServiceState) {
275  EXPECT_EQ(REMOTE_SERVICE_OK, sync_engine()->GetCurrentState());
276
277  GetSyncEngineTaskManager()->ScheduleTask(
278      FROM_HERE,
279      base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED),
280      SyncTaskManager::PRIORITY_MED,
281      base::Bind(&SyncEngineTest::CheckServiceState,
282                 AsWeakPtr(),
283                 SYNC_STATUS_AUTHENTICATION_FAILED,
284                 REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
285
286  GetSyncEngineTaskManager()->ScheduleTask(
287      FROM_HERE,
288      base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
289      SyncTaskManager::PRIORITY_MED,
290      base::Bind(&SyncEngineTest::CheckServiceState,
291                 AsWeakPtr(),
292                 SYNC_STATUS_ACCESS_FORBIDDEN,
293                 REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
294
295  GetSyncEngineTaskManager()->ScheduleTask(
296      FROM_HERE,
297      base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
298      SyncTaskManager::PRIORITY_MED,
299      base::Bind(&SyncEngineTest::CheckServiceState,
300                 AsWeakPtr(),
301                 SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
302                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
303
304  GetSyncEngineTaskManager()->ScheduleTask(
305      FROM_HERE,
306      base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
307      SyncTaskManager::PRIORITY_MED,
308      base::Bind(&SyncEngineTest::CheckServiceState,
309                 AsWeakPtr(),
310                 SYNC_STATUS_NETWORK_ERROR,
311                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
312
313  GetSyncEngineTaskManager()->ScheduleTask(
314      FROM_HERE,
315      base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
316      SyncTaskManager::PRIORITY_MED,
317      base::Bind(&SyncEngineTest::CheckServiceState,
318                 AsWeakPtr(),
319                 SYNC_STATUS_ABORT,
320                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
321
322  GetSyncEngineTaskManager()->ScheduleTask(
323      FROM_HERE,
324      base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
325      SyncTaskManager::PRIORITY_MED,
326      base::Bind(&SyncEngineTest::CheckServiceState,
327                 AsWeakPtr(),
328                 SYNC_STATUS_FAILED,
329                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
330
331  GetSyncEngineTaskManager()->ScheduleTask(
332      FROM_HERE,
333      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
334      SyncTaskManager::PRIORITY_MED,
335      base::Bind(&SyncEngineTest::CheckServiceState,
336                 AsWeakPtr(),
337                 SYNC_DATABASE_ERROR_CORRUPTION,
338                 REMOTE_SERVICE_DISABLED));
339
340  GetSyncEngineTaskManager()->ScheduleTask(
341      FROM_HERE,
342      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
343      SyncTaskManager::PRIORITY_MED,
344      base::Bind(&SyncEngineTest::CheckServiceState,
345                 AsWeakPtr(),
346                 SYNC_DATABASE_ERROR_IO_ERROR,
347                 REMOTE_SERVICE_DISABLED));
348
349  GetSyncEngineTaskManager()->ScheduleTask(
350      FROM_HERE,
351      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
352      SyncTaskManager::PRIORITY_MED,
353      base::Bind(&SyncEngineTest::CheckServiceState,
354                 AsWeakPtr(),
355                 SYNC_DATABASE_ERROR_FAILED,
356                 REMOTE_SERVICE_DISABLED));
357
358  GetSyncEngineTaskManager()->ScheduleSyncTask(
359      FROM_HERE,
360      scoped_ptr<SyncTask>(new MockSyncTask(false)),
361      SyncTaskManager::PRIORITY_MED,
362      base::Bind(&SyncEngineTest::CheckServiceState,
363                 AsWeakPtr(),
364                 SYNC_STATUS_OK,
365                 REMOTE_SERVICE_DISABLED));
366
367  GetSyncEngineTaskManager()->ScheduleSyncTask(
368      FROM_HERE,
369      scoped_ptr<SyncTask>(new MockSyncTask(true)),
370      SyncTaskManager::PRIORITY_MED,
371      base::Bind(&SyncEngineTest::CheckServiceState,
372                 AsWeakPtr(),
373                 SYNC_STATUS_OK,
374                 REMOTE_SERVICE_OK));
375
376  base::RunLoop().RunUntilIdle();
377}
378
379}  // namespace drive_backend
380}  // namespace sync_file_system
381