[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 1 | // Copyright (c) 2010 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 | #ifndef CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_ |
| 6 | #define CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_ |
[email protected] | 32b76ef | 2010-07-26 23:08:24 | [diff] [blame] | 7 | #pragma once |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 8 | |
| 9 | #include <string> |
| 10 | |
| 11 | #include "base/message_loop.h" |
| 12 | #include "chrome/browser/profile.h" |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 13 | #include "chrome/browser/sync/engine/syncapi.h" |
[email protected] | e3e43d9 | 2010-02-26 22:02:38 | [diff] [blame] | 14 | #include "chrome/browser/sync/profile_sync_factory.h" |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 15 | #include "chrome/browser/sync/profile_sync_service.h" |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 16 | #include "chrome/browser/sync/glue/data_type_controller.h" |
| 17 | #include "chrome/browser/sync/glue/data_type_manager_impl.h" |
| 18 | #include "chrome/browser/sync/glue/sync_backend_host.h" |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 19 | #include "chrome/browser/sync/sessions/session_state.h" |
| 20 | #include "chrome/browser/sync/syncable/directory_manager.h" |
| 21 | #include "chrome/browser/sync/syncable/syncable.h" |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 22 | #include "chrome/common/notification_service.h" |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 23 | #include "chrome/test/profile_mock.h" |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 24 | #include "chrome/test/sync/test_http_bridge_factory.h" |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 25 | #include "testing/gmock/include/gmock/gmock.h" |
| 26 | |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 27 | using browser_sync::ModelSafeRoutingInfo; |
| 28 | using browser_sync::sessions::ErrorCounters; |
| 29 | using browser_sync::sessions::SyncerStatus; |
| 30 | using browser_sync::sessions::SyncSessionSnapshot; |
| 31 | using sync_api::UserShare; |
| 32 | using syncable::DirectoryManager; |
| 33 | using syncable::ModelType; |
| 34 | using syncable::ScopedDirLookup; |
| 35 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 36 | ACTION_P(CallOnPaused, core) { |
| 37 | core->OnPaused(); |
| 38 | }; |
| 39 | |
| 40 | ACTION_P(CallOnResumed, core) { |
| 41 | core->OnResumed(); |
| 42 | } |
| 43 | |
| 44 | ACTION(ReturnNewDataTypeManager) { |
| 45 | return new browser_sync::DataTypeManagerImpl(arg0, arg1); |
| 46 | } |
| 47 | |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 48 | namespace browser_sync { |
| 49 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 50 | // Mocks out the SyncerThread operations (Pause/Resume) since no thread is |
| 51 | // running in these tests, and allows tests to provide a task on construction |
| 52 | // to set up initial nodes to mock out an actual server initial sync |
| 53 | // download. |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 54 | class SyncBackendHostForProfileSyncTest : public SyncBackendHost { |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 55 | public: |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 56 | // |initial_condition_setup_task| can be used to populate nodes before the |
| 57 | // OnBackendInitialized callback fires. |
| 58 | // |set_initial_sync_ended_on_init| determines whether we pretend that a full |
| 59 | // initial download has occurred and set bits for enabled data types. If |
| 60 | // this is false, configuring data types will require a syncer nudge. |
| 61 | // |synchronous_init| causes initialization to block until the syncapi has |
| 62 | // completed setting itself up and called us back. |
| 63 | SyncBackendHostForProfileSyncTest(SyncFrontend* frontend, |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 64 | Profile* profile, |
| 65 | const FilePath& profile_path, |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 66 | const DataTypeController::TypeMap& data_type_controllers, |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 67 | Task* initial_condition_setup_task, |
| 68 | int num_expected_resumes, |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 69 | int num_expected_pauses, |
| 70 | bool set_initial_sync_ended_on_init, |
| 71 | bool synchronous_init) |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 72 | : browser_sync::SyncBackendHost(frontend, profile, profile_path, |
| 73 | data_type_controllers), |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 74 | initial_condition_setup_task_(initial_condition_setup_task), |
| 75 | set_initial_sync_ended_on_init_(set_initial_sync_ended_on_init), |
| 76 | synchronous_init_(synchronous_init) { |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 77 | // By default, the RequestPause and RequestResume methods will |
| 78 | // send the confirmation notification and return true. |
| 79 | ON_CALL(*this, RequestPause()). |
| 80 | WillByDefault(testing::DoAll(CallOnPaused(core_), |
| 81 | testing::Return(true))); |
| 82 | ON_CALL(*this, RequestResume()). |
| 83 | WillByDefault(testing::DoAll(CallOnResumed(core_), |
| 84 | testing::Return(true))); |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 85 | ON_CALL(*this, RequestNudge()).WillByDefault(testing::Invoke(this, |
| 86 | &SyncBackendHostForProfileSyncTest:: |
| 87 | SimulateSyncCycleCompletedInitialSyncEnded)); |
| 88 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 89 | EXPECT_CALL(*this, RequestPause()).Times(num_expected_pauses); |
| 90 | EXPECT_CALL(*this, RequestResume()).Times(num_expected_resumes); |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 91 | EXPECT_CALL(*this, RequestNudge()). |
| 92 | Times(set_initial_sync_ended_on_init ? 0 : 1); |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | MOCK_METHOD0(RequestPause, bool()); |
| 96 | MOCK_METHOD0(RequestResume, bool()); |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 97 | MOCK_METHOD0(RequestNudge, void()); |
| 98 | |
| 99 | void SetInitialSyncEndedForEnabledTypes() { |
| 100 | UserShare* user_share = core_->syncapi()->GetUserShare(); |
| 101 | DirectoryManager* dir_manager = user_share->dir_manager.get(); |
| 102 | |
[email protected] | e8234d3 | 2010-09-09 20:36:39 | [diff] [blame^] | 103 | ScopedDirLookup dir(dir_manager, user_share->name); |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 104 | if (!dir.good()) |
| 105 | FAIL(); |
| 106 | |
| 107 | ModelSafeRoutingInfo enabled_types; |
| 108 | GetModelSafeRoutingInfo(&enabled_types); |
| 109 | for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); |
| 110 | i != enabled_types.end(); ++i) { |
| 111 | dir->set_initial_sync_ended_for_type(i->first, true); |
| 112 | } |
| 113 | } |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 114 | |
| 115 | virtual void HandleInitializationCompletedOnFrontendLoop() { |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 116 | set_syncapi_initialized(); // Need to do this asap so task below works. |
| 117 | |
| 118 | // Set up any nodes the test wants around before model association. |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 119 | if (initial_condition_setup_task_) { |
| 120 | initial_condition_setup_task_->Run(); |
| 121 | } |
| 122 | |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 123 | // Pretend we downloaded initial updates and set initial sync ended bits |
| 124 | // if we were asked to. |
| 125 | if (set_initial_sync_ended_on_init_) |
| 126 | SetInitialSyncEndedForEnabledTypes(); |
| 127 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 128 | SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(); |
| 129 | } |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 130 | |
| 131 | // Called when a nudge comes in. |
| 132 | void SimulateSyncCycleCompletedInitialSyncEnded() { |
| 133 | syncable::ModelTypeBitSet sync_ended; |
| 134 | ModelSafeRoutingInfo enabled_types; |
| 135 | GetModelSafeRoutingInfo(&enabled_types); |
| 136 | for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); |
| 137 | i != enabled_types.end(); ++i) { |
| 138 | sync_ended.set(i->first); |
| 139 | } |
| 140 | core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot( |
| 141 | SyncerStatus(), ErrorCounters(), 0, 0, false, |
| 142 | sync_ended, false, false, 0, 0, false)); |
| 143 | } |
| 144 | |
| 145 | virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory( |
| 146 | URLRequestContextGetter* getter) { |
| 147 | return new browser_sync::TestHttpBridgeFactory; |
| 148 | } |
| 149 | |
| 150 | virtual void InitCore(const Core::DoInitializeOptions& options) { |
| 151 | std::wstring user = L"testuser"; |
| 152 | core_loop()->PostTask(FROM_HERE, |
| 153 | NewRunnableMethod(core_.get(), |
| 154 | &SyncBackendHost::Core::DoInitializeForTest, |
| 155 | user, |
| 156 | options.http_bridge_factory, |
[email protected] | 33cd004 | 2010-09-08 19:25:28 | [diff] [blame] | 157 | options.delete_sync_data_folder)); |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 158 | |
| 159 | // TODO(akalin): Figure out a better way to do this. |
| 160 | if (synchronous_init_) { |
| 161 | // The SyncBackend posts a task to the current loop when |
| 162 | // initialization completes. |
| 163 | MessageLoop::current()->Run(); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | static void SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) { |
| 168 | EXPECT_CALL(*profile, GetPasswordStore(testing::_)). |
| 169 | WillOnce(testing::Return((PasswordStore*)NULL)); |
| 170 | EXPECT_CALL(*profile, GetHistoryService(testing::_)). |
| 171 | WillOnce(testing::Return((HistoryService*)NULL)); |
| 172 | } |
| 173 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 174 | private: |
| 175 | Task* initial_condition_setup_task_; |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 176 | bool set_initial_sync_ended_on_init_; |
| 177 | bool synchronous_init_; |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 178 | |
| 179 | }; |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 180 | |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 181 | } // namespace browser_sync |
| 182 | |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 183 | class TestProfileSyncService : public ProfileSyncService { |
| 184 | public: |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 185 | TestProfileSyncService(ProfileSyncFactory* factory, |
| 186 | Profile* profile, |
[email protected] | e8234d3 | 2010-09-09 20:36:39 | [diff] [blame^] | 187 | const std::string& test_user, |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 188 | bool synchronous_backend_initialization, |
| 189 | Task* initial_condition_setup_task) |
[email protected] | e8234d3 | 2010-09-09 20:36:39 | [diff] [blame^] | 190 | : ProfileSyncService(factory, profile, |
| 191 | !test_user.empty() ? |
| 192 | test_user : ""), |
[email protected] | 4c21758 | 2010-05-13 21:37:14 | [diff] [blame] | 193 | synchronous_backend_initialization_( |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 194 | synchronous_backend_initialization), |
| 195 | synchronous_sync_configuration_(false), |
| 196 | num_expected_resumes_(1), |
| 197 | num_expected_pauses_(1), |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 198 | initial_condition_setup_task_(initial_condition_setup_task), |
| 199 | set_initial_sync_ended_on_init_(true) { |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 200 | RegisterPreferences(); |
| 201 | SetSyncSetupCompleted(); |
| 202 | } |
[email protected] | 66761b95 | 2010-06-25 21:30:38 | [diff] [blame] | 203 | virtual ~TestProfileSyncService() { } |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 204 | |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 205 | virtual void CreateBackend() { |
| 206 | backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( |
| 207 | this, profile(), |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 208 | profile()->GetPath(), data_type_controllers(), |
| 209 | initial_condition_setup_task_.release(), |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 210 | num_expected_resumes_, num_expected_pauses_, |
| 211 | set_initial_sync_ended_on_init_, |
| 212 | synchronous_backend_initialization_)); |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | virtual void OnBackendInitialized() { |
| 216 | ProfileSyncService::OnBackendInitialized(); |
[email protected] | 4c21758 | 2010-05-13 21:37:14 | [diff] [blame] | 217 | // TODO(akalin): Figure out a better way to do this. |
| 218 | if (synchronous_backend_initialization_) { |
| 219 | MessageLoop::current()->Quit(); |
| 220 | } |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 221 | } |
| 222 | |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 223 | virtual void Observe(NotificationType type, |
| 224 | const NotificationSource& source, |
| 225 | const NotificationDetails& details) { |
| 226 | ProfileSyncService::Observe(type, source, details); |
| 227 | if (type == NotificationType::SYNC_CONFIGURE_DONE && |
| 228 | !synchronous_sync_configuration_) { |
| 229 | MessageLoop::current()->Quit(); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | void set_num_expected_resumes(int times) { |
| 234 | num_expected_resumes_ = times; |
| 235 | } |
| 236 | void set_num_expected_pauses(int num) { |
| 237 | num_expected_pauses_ = num; |
| 238 | } |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 239 | void dont_set_initial_sync_ended_on_init() { |
| 240 | set_initial_sync_ended_on_init_ = false; |
| 241 | } |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 242 | void set_synchronous_sync_configuration() { |
| 243 | synchronous_sync_configuration_ = true; |
| 244 | } |
| 245 | |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 246 | private: |
| 247 | // When testing under ChromiumOS, this method must not return an empty |
| 248 | // value value in order for the profile sync service to start. |
| 249 | virtual std::string GetLsidForAuthBootstraping() { |
| 250 | return "foo"; |
| 251 | } |
[email protected] | 4c21758 | 2010-05-13 21:37:14 | [diff] [blame] | 252 | |
| 253 | bool synchronous_backend_initialization_; |
[email protected] | 7cef1c44 | 2010-07-07 17:05:22 | [diff] [blame] | 254 | |
| 255 | // Set to true when a mock data type manager is being used and the configure |
| 256 | // step is performed synchronously. |
| 257 | bool synchronous_sync_configuration_; |
| 258 | bool set_expect_resume_expectations_; |
| 259 | int num_expected_resumes_; |
| 260 | int num_expected_pauses_; |
| 261 | |
| 262 | scoped_ptr<Task> initial_condition_setup_task_; |
[email protected] | 18af9a2 | 2010-08-11 00:47:19 | [diff] [blame] | 263 | bool set_initial_sync_ended_on_init_; |
[email protected] | 72a31b4 | 2010-02-17 22:26:33 | [diff] [blame] | 264 | }; |
| 265 | |
| 266 | #endif // CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_ |