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