1// Copyright (c) 2012 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/glue/shared_change_processor.h"
6
7#include <cstddef>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/compiler_specific.h"
12#include "base/message_loop/message_loop.h"
13#include "chrome/browser/sync/glue/data_type_error_handler_mock.h"
14#include "chrome/browser/sync/profile_sync_components_factory_impl.h"
15#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
16#include "chrome/browser/sync/profile_sync_service_mock.h"
17#include "content/public/test/test_browser_thread.h"
18#include "sync/api/fake_syncable_service.h"
19#include "testing/gmock/include/gmock/gmock.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace browser_sync {
23
24namespace {
25
26using content::BrowserThread;
27using ::testing::NiceMock;
28using ::testing::StrictMock;
29
30ACTION_P(GetWeakPtrToSyncableService, syncable_service) {
31  // Have to do this within an Action to ensure it's not evaluated on the wrong
32  // thread.
33  return syncable_service->AsWeakPtr();
34}
35
36class SyncSharedChangeProcessorTest : public testing::Test {
37 public:
38  SyncSharedChangeProcessorTest()
39      : ui_thread_(BrowserThread::UI, &ui_loop_),
40        db_thread_(BrowserThread::DB) {}
41
42  virtual ~SyncSharedChangeProcessorTest() {
43    EXPECT_FALSE(db_syncable_service_.get());
44  }
45
46 protected:
47  virtual void SetUp() OVERRIDE {
48    shared_change_processor_ = new SharedChangeProcessor();
49    db_thread_.Start();
50    EXPECT_TRUE(BrowserThread::PostTask(
51        BrowserThread::DB,
52        FROM_HERE,
53        base::Bind(&SyncSharedChangeProcessorTest::SetUpDBSyncableService,
54                   base::Unretained(this))));
55  }
56
57  virtual void TearDown() OVERRIDE {
58    EXPECT_TRUE(BrowserThread::PostTask(
59        BrowserThread::DB,
60        FROM_HERE,
61        base::Bind(&SyncSharedChangeProcessorTest::TearDownDBSyncableService,
62                   base::Unretained(this))));
63    // This must happen before the DB thread is stopped since
64    // |shared_change_processor_| may post tasks to delete its members
65    // on the correct thread.
66    //
67    // TODO(akalin): Write deterministic tests for the destruction of
68    // |shared_change_processor_| on the UI and DB threads.
69    shared_change_processor_ = NULL;
70    db_thread_.Stop();
71  }
72
73  // Connect |shared_change_processor_| on the DB thread.
74  void Connect() {
75    EXPECT_TRUE(BrowserThread::PostTask(
76        BrowserThread::DB,
77        FROM_HERE,
78        base::Bind(&SyncSharedChangeProcessorTest::ConnectOnDBThread,
79                   base::Unretained(this),
80                   shared_change_processor_)));
81  }
82
83 private:
84  // Used by SetUp().
85  void SetUpDBSyncableService() {
86    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
87    DCHECK(!db_syncable_service_.get());
88    db_syncable_service_.reset(new syncer::FakeSyncableService());
89  }
90
91  // Used by TearDown().
92  void TearDownDBSyncableService() {
93    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
94    DCHECK(db_syncable_service_.get());
95    db_syncable_service_.reset();
96  }
97
98  // Used by Connect().  The SharedChangeProcessor is passed in
99  // because we modify |shared_change_processor_| on the main thread
100  // (in TearDown()).
101  void ConnectOnDBThread(
102      const scoped_refptr<SharedChangeProcessor>& shared_change_processor) {
103    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
104    EXPECT_CALL(sync_factory_, GetSyncableServiceForType(syncer::AUTOFILL)).
105        WillOnce(GetWeakPtrToSyncableService(db_syncable_service_.get()));
106    EXPECT_TRUE(shared_change_processor->Connect(
107        &sync_factory_,
108        &sync_service_,
109        &error_handler_,
110        syncer::AUTOFILL,
111        base::WeakPtr<syncer::SyncMergeResult>()));
112  }
113
114  base::MessageLoopForUI ui_loop_;
115  content::TestBrowserThread ui_thread_;
116  content::TestBrowserThread db_thread_;
117
118  scoped_refptr<SharedChangeProcessor> shared_change_processor_;
119  NiceMock<ProfileSyncComponentsFactoryMock> sync_factory_;
120  NiceMock<ProfileSyncServiceMock> sync_service_;
121  StrictMock<DataTypeErrorHandlerMock> error_handler_;
122
123  // Used only on DB thread.
124  scoped_ptr<syncer::FakeSyncableService> db_syncable_service_;
125};
126
127// Simply connect the shared change processor.  It should succeed, and
128// nothing further should happen.
129TEST_F(SyncSharedChangeProcessorTest, Basic) {
130  Connect();
131}
132
133}  // namespace
134
135}  // namespace browser_sync
136