Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / frontend_data_type_controller_unittest.cc
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 "testing/gtest/include/gtest/gtest.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/tracked_objects.h"
13 #include "chrome/browser/sync/glue/change_processor_mock.h"
14 #include "chrome/browser/sync/glue/frontend_data_type_controller.h"
15 #include "chrome/browser/sync/glue/frontend_data_type_controller_mock.h"
16 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
17 #include "chrome/browser/sync/profile_sync_service_mock.h"
18 #include "chrome/test/base/profile_mock.h"
19 #include "components/sync_driver/data_type_controller_mock.h"
20 #include "components/sync_driver/model_associator_mock.h"
21 #include "content/public/test/test_browser_thread.h"
22
23 using browser_sync::ChangeProcessorMock;
24 using browser_sync::DataTypeController;
25 using browser_sync::FrontendDataTypeController;
26 using browser_sync::FrontendDataTypeControllerMock;
27 using browser_sync::ModelAssociatorMock;
28 using browser_sync::ModelLoadCallbackMock;
29 using browser_sync::StartCallbackMock;
30 using content::BrowserThread;
31 using testing::_;
32 using testing::DoAll;
33 using testing::InvokeWithoutArgs;
34 using testing::Return;
35 using testing::SetArgumentPointee;
36 using testing::StrictMock;
37
38 class FrontendDataTypeControllerFake : public FrontendDataTypeController {
39  public:
40   FrontendDataTypeControllerFake(
41       ProfileSyncComponentsFactory* profile_sync_factory,
42       Profile* profile,
43       ProfileSyncService* sync_service,
44       FrontendDataTypeControllerMock* mock)
45       : FrontendDataTypeController(base::MessageLoopProxy::current(),
46                                    base::Closure(),
47                                    profile_sync_factory,
48                                    profile,
49                                    sync_service),
50         mock_(mock) {}
51   virtual syncer::ModelType type() const OVERRIDE { return syncer::BOOKMARKS; }
52
53  private:
54   virtual void CreateSyncComponents() OVERRIDE {
55     ProfileSyncComponentsFactory::SyncComponents sync_components =
56         profile_sync_factory_->
57             CreateBookmarkSyncComponents(sync_service_, this);
58     model_associator_.reset(sync_components.model_associator);
59     change_processor_.reset(sync_components.change_processor);
60   }
61
62   // We mock the following methods because their default implementations do
63   // nothing, but we still want to make sure they're called appropriately.
64   virtual bool StartModels() OVERRIDE {
65     return mock_->StartModels();
66   }
67   virtual void CleanUpState() OVERRIDE {
68     mock_->CleanUpState();
69   }
70   virtual void RecordUnrecoverableError(
71       const tracked_objects::Location& from_here,
72       const std::string& message) OVERRIDE {
73     mock_->RecordUnrecoverableError(from_here, message);
74   }
75   virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
76     mock_->RecordAssociationTime(time);
77   }
78   virtual void RecordStartFailure(
79       DataTypeController::StartResult result) OVERRIDE {
80     mock_->RecordStartFailure(result);
81   }
82  private:
83   virtual ~FrontendDataTypeControllerFake() {}
84   FrontendDataTypeControllerMock* mock_;
85 };
86
87 class SyncFrontendDataTypeControllerTest : public testing::Test {
88  public:
89   SyncFrontendDataTypeControllerTest()
90       : ui_thread_(BrowserThread::UI, &message_loop_),
91         service_(&profile_) {}
92
93   virtual void SetUp() {
94     profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
95     dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>();
96     frontend_dtc_ =
97         new FrontendDataTypeControllerFake(profile_sync_factory_.get(),
98                                            &profile_,
99                                            &service_,
100                                            dtc_mock_.get());
101   }
102
103  protected:
104   void SetStartExpectations() {
105     EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
106     EXPECT_CALL(model_load_callback_, Run(_, _));
107     model_associator_ = new ModelAssociatorMock();
108     change_processor_ = new ChangeProcessorMock();
109     EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
110         WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
111             model_associator_, change_processor_)));
112   }
113
114   void SetAssociateExpectations() {
115     EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
116         WillOnce(Return(true));
117     EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
118         WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
119     EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
120         WillOnce(Return(syncer::SyncError()));
121     EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
122   }
123
124   void SetActivateExpectations(DataTypeController::StartResult result) {
125     EXPECT_CALL(service_, ActivateDataType(_, _, _));
126     EXPECT_CALL(start_callback_, Run(result, _, _));
127   }
128
129   void SetStopExpectations() {
130     EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
131     EXPECT_CALL(service_, DeactivateDataType(_));
132     EXPECT_CALL(*model_associator_, DisassociateModels()).
133                 WillOnce(Return(syncer::SyncError()));
134   }
135
136   void SetStartFailExpectations(DataTypeController::StartResult result) {
137     if (DataTypeController::IsUnrecoverableResult(result))
138       EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
139     EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
140     EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
141     EXPECT_CALL(start_callback_, Run(result, _, _));
142   }
143
144   void Start() {
145     frontend_dtc_->LoadModels(
146         base::Bind(&ModelLoadCallbackMock::Run,
147                    base::Unretained(&model_load_callback_)));
148     frontend_dtc_->StartAssociating(
149         base::Bind(&StartCallbackMock::Run,
150                    base::Unretained(&start_callback_)));
151   }
152
153   void PumpLoop() {
154     message_loop_.RunUntilIdle();
155   }
156
157   base::MessageLoopForUI message_loop_;
158   content::TestBrowserThread ui_thread_;
159   scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_;
160   scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
161   scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_;
162   ProfileMock profile_;
163   ProfileSyncServiceMock service_;
164   ModelAssociatorMock* model_associator_;
165   ChangeProcessorMock* change_processor_;
166   StartCallbackMock start_callback_;
167   ModelLoadCallbackMock model_load_callback_;
168 };
169
170 TEST_F(SyncFrontendDataTypeControllerTest, StartOk) {
171   SetStartExpectations();
172   SetAssociateExpectations();
173   SetActivateExpectations(DataTypeController::OK);
174   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
175   Start();
176   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
177 }
178
179 TEST_F(SyncFrontendDataTypeControllerTest, StartFirstRun) {
180   SetStartExpectations();
181   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
182       WillOnce(Return(true));
183   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
184       WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
185   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
186       WillOnce(Return(syncer::SyncError()));
187   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
188   SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
189   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
190   Start();
191   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
192 }
193
194 TEST_F(SyncFrontendDataTypeControllerTest, AbortDuringStartModels) {
195   EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
196   EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
197   EXPECT_CALL(model_load_callback_, Run(_, _));
198   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
199   frontend_dtc_->LoadModels(
200       base::Bind(&ModelLoadCallbackMock::Run,
201                  base::Unretained(&model_load_callback_)));
202   EXPECT_EQ(DataTypeController::MODEL_STARTING, frontend_dtc_->state());
203   frontend_dtc_->Stop();
204   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
205 }
206
207 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationFailed) {
208   SetStartExpectations();
209   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
210       WillOnce(Return(true));
211   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
212       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
213   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
214       WillOnce(Return(syncer::SyncError(FROM_HERE,
215                                         syncer::SyncError::DATATYPE_ERROR,
216                                         "error",
217                                         syncer::BOOKMARKS)));
218
219   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
220   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
221   // Set up association to fail with an association failed error.
222   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
223   Start();
224   EXPECT_EQ(DataTypeController::DISABLED, frontend_dtc_->state());
225 }
226
227 TEST_F(SyncFrontendDataTypeControllerTest,
228        StartAssociationTriggersUnrecoverableError) {
229   SetStartExpectations();
230   SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
231   // Set up association to fail with an unrecoverable error.
232   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
233       WillRepeatedly(Return(true));
234   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
235       WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
236   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
237   Start();
238   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
239 }
240
241 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
242   SetStartExpectations();
243   SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
244   // Set up association to fail with a NEEDS_CRYPTO error.
245   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
246       WillRepeatedly(Return(false));
247   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
248   Start();
249   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
250 }
251
252 TEST_F(SyncFrontendDataTypeControllerTest, Stop) {
253   SetStartExpectations();
254   SetAssociateExpectations();
255   SetActivateExpectations(DataTypeController::OK);
256   SetStopExpectations();
257   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
258   Start();
259   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
260   frontend_dtc_->Stop();
261   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
262 }
263
264 TEST_F(SyncFrontendDataTypeControllerTest, OnSingleDatatypeUnrecoverableError) {
265   SetStartExpectations();
266   SetAssociateExpectations();
267   SetActivateExpectations(DataTypeController::OK);
268   EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, "Test"));
269   EXPECT_CALL(service_, DisableBrokenDatatype(_, _, _))
270       .WillOnce(InvokeWithoutArgs(frontend_dtc_.get(),
271                                   &FrontendDataTypeController::Stop));
272   SetStopExpectations();
273   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
274   Start();
275   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
276   // This should cause frontend_dtc_->Stop() to be called.
277   frontend_dtc_->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Test");
278   PumpLoop();
279   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
280 }