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