sync_engine_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 SequentialSyncTask {
40 public:
41  explicit MockSyncTask(bool used_network) {
42    set_used_network(used_network);
43  }
44  virtual ~MockSyncTask() {}
45
46  virtual void RunSequential(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    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
113        "sync_file_system/account_metadata.json"));
114    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
115        "gdata/empty_feed.json"));
116    sync_engine_.reset(new drive_backend::SyncEngine(
117        profile_dir_.path(),
118        base::MessageLoopProxy::current(),
119        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
120        scoped_ptr<drive::DriveUploaderInterface>(),
121        NULL /* notification_manager */,
122        extension_service_.get(),
123        NULL /* signin_manager */,
124        in_memory_env_.get()));
125    sync_engine_->Initialize();
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_->UpdateRegisteredApps();
141  }
142
143  SyncTaskManager* GetSyncEngineTaskManager() {
144    return sync_engine_->task_manager_.get();
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 private:
155  content::TestBrowserThreadBundle browser_threads_;
156  base::ScopedTempDir profile_dir_;
157  scoped_ptr<leveldb::Env> in_memory_env_;
158
159  scoped_ptr<MockExtensionService> extension_service_;
160  scoped_ptr<drive_backend::SyncEngine> sync_engine_;
161
162  DISALLOW_COPY_AND_ASSIGN(SyncEngineTest);
163};
164
165TEST_F(SyncEngineTest, EnableOrigin) {
166  FileTracker tracker;
167  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
168  MetadataDatabase* metadata_database = sync_engine()->GetMetadataDatabase();
169  GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
170
171  sync_engine()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
172  base::RunLoop().RunUntilIdle();
173  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
174  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
175  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
176
177  sync_engine()->DisableOrigin(origin, CreateResultReceiver(&sync_status));
178  base::RunLoop().RunUntilIdle();
179  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
180  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
181  EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
182
183  sync_engine()->EnableOrigin(origin, CreateResultReceiver(&sync_status));
184  base::RunLoop().RunUntilIdle();
185  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
186  ASSERT_TRUE(metadata_database->FindAppRootTracker(kAppID, &tracker));
187  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
188
189  sync_engine()->UninstallOrigin(
190      origin,
191      RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
192      CreateResultReceiver(&sync_status));
193  base::RunLoop().RunUntilIdle();
194  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
195  ASSERT_FALSE(metadata_database->FindAppRootTracker(kAppID, &tracker));
196}
197
198TEST_F(SyncEngineTest, UpdateRegisteredApps) {
199  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
200  for (int i = 0; i < 3; i++) {
201    scoped_refptr<const extensions::Extension> extension =
202        extensions::ExtensionBuilder()
203        .SetManifest(extensions::DictionaryBuilder()
204                     .Set("name", "foo")
205                     .Set("version", "1.0")
206                     .Set("manifest_version", 2))
207        .SetID(base::StringPrintf("app_%d", i))
208        .Build();
209    extension_service()->AddExtension(extension.get());
210    GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
211        extension->id());
212    sync_status = SYNC_STATUS_UNKNOWN;
213    sync_engine()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
214    base::RunLoop().RunUntilIdle();
215    EXPECT_EQ(SYNC_STATUS_OK, sync_status);
216  }
217
218  MetadataDatabase* metadata_database = sync_engine()->GetMetadataDatabase();
219  FileTracker tracker;
220
221  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_0", &tracker));
222  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
223
224  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_1", &tracker));
225  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
226
227  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_2", &tracker));
228  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
229
230  extension_service()->DisableExtension("app_1");
231  extension_service()->UninstallExtension("app_2");
232  ASSERT_FALSE(extension_service()->GetInstalledExtension("app_2"));
233  UpdateRegisteredApps();
234  base::RunLoop().RunUntilIdle();
235
236  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_0", &tracker));
237  EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
238
239  ASSERT_TRUE(metadata_database->FindAppRootTracker("app_1", &tracker));
240  EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
241
242  ASSERT_FALSE(metadata_database->FindAppRootTracker("app_2", &tracker));
243}
244
245TEST_F(SyncEngineTest, GetOriginStatusMap) {
246  FileTracker tracker;
247  SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
248  GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
249
250  sync_engine()->RegisterOrigin(GURL("chrome-extension://app_0"),
251                                     CreateResultReceiver(&sync_status));
252  base::RunLoop().RunUntilIdle();
253  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
254
255  sync_engine()->RegisterOrigin(GURL("chrome-extension://app_1"),
256                                     CreateResultReceiver(&sync_status));
257  base::RunLoop().RunUntilIdle();
258  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
259
260  RemoteFileSyncService::OriginStatusMap status_map;
261  sync_engine()->GetOriginStatusMap(&status_map);
262  ASSERT_EQ(2u, status_map.size());
263  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_0")]);
264  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_1")]);
265
266  sync_engine()->DisableOrigin(GURL("chrome-extension://app_1"),
267                               CreateResultReceiver(&sync_status));
268  base::RunLoop().RunUntilIdle();
269  EXPECT_EQ(SYNC_STATUS_OK, sync_status);
270
271  sync_engine()->GetOriginStatusMap(&status_map);
272  ASSERT_EQ(2u, status_map.size());
273  EXPECT_EQ("Enabled", status_map[GURL("chrome-extension://app_0")]);
274  EXPECT_EQ("Disabled", status_map[GURL("chrome-extension://app_1")]);
275}
276
277TEST_F(SyncEngineTest, UpdateServiceState) {
278  EXPECT_EQ(REMOTE_SERVICE_OK, sync_engine()->GetCurrentState());
279
280  GetSyncEngineTaskManager()->ScheduleTask(
281      FROM_HERE,
282      base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED),
283      SyncTaskManager::PRIORITY_MED,
284      base::Bind(&SyncEngineTest::CheckServiceState,
285                 AsWeakPtr(),
286                 SYNC_STATUS_AUTHENTICATION_FAILED,
287                 REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
288
289  GetSyncEngineTaskManager()->ScheduleTask(
290      FROM_HERE,
291      base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
292      SyncTaskManager::PRIORITY_MED,
293      base::Bind(&SyncEngineTest::CheckServiceState,
294                 AsWeakPtr(),
295                 SYNC_STATUS_ACCESS_FORBIDDEN,
296                 REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
297
298  GetSyncEngineTaskManager()->ScheduleTask(
299      FROM_HERE,
300      base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
301      SyncTaskManager::PRIORITY_MED,
302      base::Bind(&SyncEngineTest::CheckServiceState,
303                 AsWeakPtr(),
304                 SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
305                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
306
307  GetSyncEngineTaskManager()->ScheduleTask(
308      FROM_HERE,
309      base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
310      SyncTaskManager::PRIORITY_MED,
311      base::Bind(&SyncEngineTest::CheckServiceState,
312                 AsWeakPtr(),
313                 SYNC_STATUS_NETWORK_ERROR,
314                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
315
316  GetSyncEngineTaskManager()->ScheduleTask(
317      FROM_HERE,
318      base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
319      SyncTaskManager::PRIORITY_MED,
320      base::Bind(&SyncEngineTest::CheckServiceState,
321                 AsWeakPtr(),
322                 SYNC_STATUS_ABORT,
323                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
324
325  GetSyncEngineTaskManager()->ScheduleTask(
326      FROM_HERE,
327      base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
328      SyncTaskManager::PRIORITY_MED,
329      base::Bind(&SyncEngineTest::CheckServiceState,
330                 AsWeakPtr(),
331                 SYNC_STATUS_FAILED,
332                 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
333
334  GetSyncEngineTaskManager()->ScheduleTask(
335      FROM_HERE,
336      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
337      SyncTaskManager::PRIORITY_MED,
338      base::Bind(&SyncEngineTest::CheckServiceState,
339                 AsWeakPtr(),
340                 SYNC_DATABASE_ERROR_CORRUPTION,
341                 REMOTE_SERVICE_DISABLED));
342
343  GetSyncEngineTaskManager()->ScheduleTask(
344      FROM_HERE,
345      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
346      SyncTaskManager::PRIORITY_MED,
347      base::Bind(&SyncEngineTest::CheckServiceState,
348                 AsWeakPtr(),
349                 SYNC_DATABASE_ERROR_IO_ERROR,
350                 REMOTE_SERVICE_DISABLED));
351
352  GetSyncEngineTaskManager()->ScheduleTask(
353      FROM_HERE,
354      base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
355      SyncTaskManager::PRIORITY_MED,
356      base::Bind(&SyncEngineTest::CheckServiceState,
357                 AsWeakPtr(),
358                 SYNC_DATABASE_ERROR_FAILED,
359                 REMOTE_SERVICE_DISABLED));
360
361  GetSyncEngineTaskManager()->ScheduleSyncTask(
362      FROM_HERE,
363      scoped_ptr<SyncTask>(new MockSyncTask(false)),
364      SyncTaskManager::PRIORITY_MED,
365      base::Bind(&SyncEngineTest::CheckServiceState,
366                 AsWeakPtr(),
367                 SYNC_STATUS_OK,
368                 REMOTE_SERVICE_DISABLED));
369
370  GetSyncEngineTaskManager()->ScheduleSyncTask(
371      FROM_HERE,
372      scoped_ptr<SyncTask>(new MockSyncTask(true)),
373      SyncTaskManager::PRIORITY_MED,
374      base::Bind(&SyncEngineTest::CheckServiceState,
375                 AsWeakPtr(),
376                 SYNC_STATUS_OK,
377                 REMOTE_SERVICE_OK));
378
379  base::RunLoop().RunUntilIdle();
380}
381
382}  // namespace drive_backend
383}  // namespace sync_file_system
384