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