1// Copyright (c) 2011 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/memory/scoped_ptr.h"
8#include "base/message_loop.h"
9#include "chrome/browser/net/gaia/token_service.h"
10#include "chrome/browser/prefs/pref_service.h"
11#include "chrome/browser/sync/glue/data_type_manager.h"
12#include "chrome/browser/sync/glue/data_type_manager_mock.h"
13#include "chrome/browser/sync/profile_sync_factory_mock.h"
14#include "chrome/browser/sync/profile_sync_test_util.h"
15#include "chrome/browser/sync/test_profile_sync_service.h"
16#include "chrome/common/net/gaia/gaia_auth_consumer.h"
17#include "chrome/common/net/gaia/gaia_constants.h"
18#include "chrome/common/pref_names.h"
19#include "chrome/test/testing_profile.h"
20#include "content/browser/browser_thread.h"
21#include "content/common/notification_type.h"
22#include "testing/gmock/include/gmock/gmock.h"
23
24using browser_sync::DataTypeManager;
25using browser_sync::DataTypeManagerMock;
26using testing::_;
27using testing::AnyNumber;
28using testing::DoAll;
29using testing::InvokeArgument;
30using testing::Mock;
31using testing::Return;
32
33ACTION_P(InvokeCallback, callback_result) {
34  arg0->Run(callback_result);
35  delete arg0;
36}
37
38// TODO(skrul) This test fails on the mac. See http://crbug.com/33443
39#if defined(OS_MACOSX)
40#define SKIP_MACOSX(test) DISABLED_##test
41#else
42#define SKIP_MACOSX(test) test
43#endif
44
45// TODO(chron): Test not using cros_user flag and use signin_
46class ProfileSyncServiceStartupTest : public testing::Test {
47 public:
48  ProfileSyncServiceStartupTest()
49      : ui_thread_(BrowserThread::UI, &message_loop_) {}
50
51  virtual ~ProfileSyncServiceStartupTest() {
52    // The PSS has some deletes that are scheduled on the main thread
53    // so we must delete the service and run the message loop.
54    service_.reset();
55    MessageLoop::current()->RunAllPending();
56  }
57
58  virtual void SetUp() {
59    profile_.CreateRequestContext();
60    service_.reset(new TestProfileSyncService(&factory_, &profile_,
61                                              "test", true, NULL));
62    service_->AddObserver(&observer_);
63    service_->set_synchronous_sync_configuration();
64  }
65
66  virtual void TearDown() {
67    service_->RemoveObserver(&observer_);
68    {
69      // The request context gets deleted on the I/O thread. To prevent a leak
70      // supply one here.
71      BrowserThread io_thread(BrowserThread::IO, MessageLoop::current());
72      profile_.ResetRequestContext();
73    }
74    MessageLoop::current()->RunAllPending();
75  }
76
77 protected:
78  DataTypeManagerMock* SetUpDataTypeManager() {
79    DataTypeManagerMock* data_type_manager = new DataTypeManagerMock();
80    EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
81        WillOnce(Return(data_type_manager));
82    return data_type_manager;
83  }
84
85  MessageLoop message_loop_;
86  BrowserThread ui_thread_;
87  TestingProfile profile_;
88  ProfileSyncFactoryMock factory_;
89  scoped_ptr<TestProfileSyncService> service_;
90  ProfileSyncServiceObserverMock observer_;
91};
92
93TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFirstTime)) {
94  DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
95  EXPECT_CALL(*data_type_manager, Configure(_)).Times(0);
96
97  // We've never completed startup.
98  profile_.GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
99
100  // Should not actually start, rather just clean things up and wait
101  // to be enabled.
102  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
103  service_->Initialize();
104
105  // Preferences should be back to defaults.
106  EXPECT_EQ(0, profile_.GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
107  EXPECT_FALSE(profile_.GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted));
108  Mock::VerifyAndClearExpectations(data_type_manager);
109
110  // Then start things up.
111  EXPECT_CALL(*data_type_manager, Configure(_)).Times(3);
112  EXPECT_CALL(*data_type_manager, state()).
113      WillOnce(Return(DataTypeManager::CONFIGURED));
114  EXPECT_CALL(*data_type_manager, Stop()).Times(1);
115  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
116
117  // Create some tokens in the token service; the service will startup when
118  // it is notified that tokens are available.
119  profile_.GetTokenService()->IssueAuthTokenForTest(
120      GaiaConstants::kSyncService, "sync_token");
121
122  syncable::ModelTypeSet set;
123  set.insert(syncable::BOOKMARKS);
124  service_->OnUserChoseDatatypes(false, set);
125}
126
127TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartNormal)) {
128  DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
129  EXPECT_CALL(*data_type_manager, Configure(_)).Times(2);
130  EXPECT_CALL(*data_type_manager, state()).
131      WillOnce(Return(DataTypeManager::CONFIGURED));
132  EXPECT_CALL(*data_type_manager, Stop()).Times(1);
133
134  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
135
136  // Pre load the tokens
137  profile_.GetTokenService()->IssueAuthTokenForTest(
138      GaiaConstants::kSyncService, "sync_token");
139  service_->Initialize();
140}
141
142TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(ManagedStartup)) {
143  // Disable sync through policy.
144  profile_.GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
145
146  EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
147  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
148
149  // Service should not be started by Initialize() since it's managed.
150  profile_.GetTokenService()->IssueAuthTokenForTest(
151      GaiaConstants::kSyncService, "sync_token");
152  service_->Initialize();
153}
154
155TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(SwitchManaged)) {
156  DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
157  EXPECT_CALL(*data_type_manager, Configure(_)).Times(2);
158  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
159
160  profile_.GetTokenService()->IssueAuthTokenForTest(
161      GaiaConstants::kSyncService, "sync_token");
162  service_->Initialize();
163
164  // The service should stop when switching to managed mode.
165  Mock::VerifyAndClearExpectations(data_type_manager);
166  EXPECT_CALL(*data_type_manager, state()).
167      WillOnce(Return(DataTypeManager::CONFIGURED));
168  EXPECT_CALL(*data_type_manager, Stop()).Times(1);
169  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
170  profile_.GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
171
172  // When switching back to unmanaged, the state should change, but the service
173  // should not start up automatically (kSyncSetupCompleted will be false).
174  Mock::VerifyAndClearExpectations(data_type_manager);
175  EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
176  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
177  profile_.GetPrefs()->ClearPref(prefs::kSyncManaged);
178}
179
180TEST_F(ProfileSyncServiceStartupTest, ClearServerData) {
181  DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
182  EXPECT_CALL(*data_type_manager, Configure(_)).Times(2);
183  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
184
185  profile_.GetTokenService()->IssueAuthTokenForTest(
186      GaiaConstants::kSyncService, "sync_token");
187  service_->Initialize();
188  Mock::VerifyAndClearExpectations(data_type_manager);
189
190  // Success can overwrite failure, failure cannot overwrite success.  We want
191  // this behavior because once clear has succeeded, sync gets disabled, and
192  // we don't care about any subsequent failures (e.g. timeouts)
193  service_->ResetClearServerDataState();
194  EXPECT_TRUE(ProfileSyncService::CLEAR_NOT_STARTED ==
195      service_->GetClearServerDataState());
196
197  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
198  service_->OnClearServerDataFailed();
199  EXPECT_TRUE(ProfileSyncService::CLEAR_FAILED ==
200      service_->GetClearServerDataState());
201
202  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
203  service_->OnClearServerDataSucceeded();
204  EXPECT_TRUE(ProfileSyncService::CLEAR_SUCCEEDED ==
205      service_->GetClearServerDataState());
206
207  service_->OnClearServerDataFailed();
208  EXPECT_TRUE(ProfileSyncService::CLEAR_SUCCEEDED ==
209      service_->GetClearServerDataState());
210
211  // Now test the timeout states
212  service_->ResetClearServerDataState();
213  EXPECT_TRUE(ProfileSyncService::CLEAR_NOT_STARTED ==
214      service_->GetClearServerDataState());
215
216  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
217  service_->OnClearServerDataTimeout();
218  EXPECT_TRUE(ProfileSyncService::CLEAR_FAILED ==
219      service_->GetClearServerDataState());
220
221  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
222  service_->OnClearServerDataSucceeded();
223  EXPECT_TRUE(ProfileSyncService::CLEAR_SUCCEEDED ==
224      service_->GetClearServerDataState());
225
226  service_->OnClearServerDataFailed();
227  EXPECT_TRUE(ProfileSyncService::CLEAR_SUCCEEDED ==
228      service_->GetClearServerDataState());
229
230  // Test the pending state, doesn't matter what state
231  // the back end syncmgr returns
232  EXPECT_CALL(*data_type_manager, state()).
233    WillOnce(Return(DataTypeManager::STOPPED));
234  service_->ResetClearServerDataState();
235  service_->ClearServerData();
236  EXPECT_TRUE(ProfileSyncService::CLEAR_CLEARING ==
237      service_->GetClearServerDataState());
238
239  // Stop the timer and reset the state
240  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
241  service_->OnClearServerDataSucceeded();
242  service_->ResetClearServerDataState();
243}
244
245TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFailure)) {
246  DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
247  DataTypeManager::ConfigureResult configure_result =
248      DataTypeManager::ASSOCIATION_FAILED;
249  browser_sync::DataTypeManager::ConfigureResultWithErrorLocation result(
250      configure_result, FROM_HERE, syncable::ModelTypeSet());
251  EXPECT_CALL(*data_type_manager, Configure(_)).
252      WillRepeatedly(DoAll(NotifyFromDataTypeManager(data_type_manager,
253                         NotificationType::SYNC_CONFIGURE_START),
254                     NotifyFromDataTypeManagerWithResult(data_type_manager,
255                         NotificationType::SYNC_CONFIGURE_DONE,
256                         &result)));
257  EXPECT_CALL(*data_type_manager, state()).
258      WillOnce(Return(DataTypeManager::STOPPED));
259
260  EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
261
262  profile_.GetTokenService()->IssueAuthTokenForTest(
263      GaiaConstants::kSyncService, "sync_token");
264  service_->Initialize();
265  EXPECT_TRUE(service_->unrecoverable_error_detected());
266}
267