test_profile_sync_service.h revision 3f50c38dc070f4bb515c1b64450dae14f316474e
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_ 7#pragma once 8 9#include <string> 10 11#include "base/message_loop.h" 12#include "chrome/browser/sync/engine/syncapi.h" 13#include "chrome/browser/sync/profile_sync_factory.h" 14#include "chrome/browser/sync/profile_sync_service.h" 15#include "chrome/browser/sync/glue/data_type_controller.h" 16#include "chrome/browser/sync/glue/data_type_manager_impl.h" 17#include "chrome/browser/sync/glue/sync_backend_host.h" 18#include "chrome/browser/sync/sessions/session_state.h" 19#include "chrome/browser/sync/syncable/directory_manager.h" 20#include "chrome/browser/sync/syncable/syncable.h" 21#include "chrome/test/profile_mock.h" 22#include "chrome/test/sync/test_http_bridge_factory.h" 23#include "testing/gmock/include/gmock/gmock.h" 24 25class Profile; 26 27using browser_sync::ModelSafeRoutingInfo; 28using browser_sync::sessions::ErrorCounters; 29using browser_sync::sessions::SyncerStatus; 30using browser_sync::sessions::SyncSessionSnapshot; 31using sync_api::UserShare; 32using syncable::DirectoryManager; 33using syncable::ModelType; 34using syncable::ScopedDirLookup; 35 36ACTION_P(CallOnPaused, core) { 37 core->OnPaused(); 38}; 39 40ACTION_P(CallOnResumed, core) { 41 core->OnResumed(); 42} 43 44ACTION(ReturnNewDataTypeManager) { 45 return new browser_sync::DataTypeManagerImpl(arg0, arg1); 46} 47 48namespace browser_sync { 49 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. 54class SyncBackendHostForProfileSyncTest : public SyncBackendHost { 55 public: 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, 64 Profile* profile, 65 const FilePath& profile_path, 66 const DataTypeController::TypeMap& data_type_controllers, 67 Task* initial_condition_setup_task, 68 int num_expected_resumes, 69 int num_expected_pauses, 70 bool set_initial_sync_ended_on_init, 71 bool synchronous_init) 72 : browser_sync::SyncBackendHost(frontend, profile, profile_path, 73 data_type_controllers), 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) { 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))); 85 ON_CALL(*this, RequestNudge()).WillByDefault(testing::Invoke(this, 86 &SyncBackendHostForProfileSyncTest:: 87 SimulateSyncCycleCompletedInitialSyncEnded)); 88 89 EXPECT_CALL(*this, RequestPause()).Times(num_expected_pauses); 90 EXPECT_CALL(*this, RequestResume()).Times(num_expected_resumes); 91 EXPECT_CALL(*this, RequestNudge()). 92 Times(set_initial_sync_ended_on_init ? 0 : 1); 93 } 94 95 MOCK_METHOD0(RequestPause, bool()); 96 MOCK_METHOD0(RequestResume, bool()); 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 103 ScopedDirLookup dir(dir_manager, user_share->name); 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 } 114 115 virtual void ConfigureDataTypes(const syncable::ModelTypeSet& types, 116 CancelableTask* ready_task) { 117 SetAutofillMigrationState(syncable::MIGRATED); 118 SyncBackendHost::ConfigureDataTypes(types, ready_task); 119 } 120 121 virtual void HandleInitializationCompletedOnFrontendLoop() { 122 set_syncapi_initialized(); // Need to do this asap so task below works. 123 124 // Set up any nodes the test wants around before model association. 125 if (initial_condition_setup_task_) { 126 initial_condition_setup_task_->Run(); 127 } 128 129 // Pretend we downloaded initial updates and set initial sync ended bits 130 // if we were asked to. 131 if (set_initial_sync_ended_on_init_) 132 SetInitialSyncEndedForEnabledTypes(); 133 134 SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(); 135 } 136 137 // Called when a nudge comes in. 138 void SimulateSyncCycleCompletedInitialSyncEnded() { 139 syncable::ModelTypeBitSet sync_ended; 140 ModelSafeRoutingInfo enabled_types; 141 GetModelSafeRoutingInfo(&enabled_types); 142 for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); 143 i != enabled_types.end(); ++i) { 144 sync_ended.set(i->first); 145 } 146 core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot( 147 SyncerStatus(), ErrorCounters(), 0, 0, false, 148 sync_ended, false, false, 0, 0, false)); 149 } 150 151 virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory( 152 URLRequestContextGetter* getter) { 153 return new browser_sync::TestHttpBridgeFactory; 154 } 155 156 virtual void InitCore(const Core::DoInitializeOptions& options) { 157 std::wstring user = L"testuser"; 158 core_loop()->PostTask(FROM_HERE, 159 NewRunnableMethod(core_.get(), 160 &SyncBackendHost::Core::DoInitializeForTest, 161 user, 162 options.http_bridge_factory, 163 options.delete_sync_data_folder)); 164 165 // TODO(akalin): Figure out a better way to do this. 166 if (synchronous_init_) { 167 // The SyncBackend posts a task to the current loop when 168 // initialization completes. 169 MessageLoop::current()->Run(); 170 } 171 } 172 173 static void SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) { 174 EXPECT_CALL(*profile, GetPasswordStore(testing::_)). 175 WillOnce(testing::Return((PasswordStore*)NULL)); 176 EXPECT_CALL(*profile, GetHistoryService(testing::_)). 177 WillOnce(testing::Return((HistoryService*)NULL)); 178 } 179 180 private: 181 Task* initial_condition_setup_task_; 182 bool set_initial_sync_ended_on_init_; 183 bool synchronous_init_; 184}; 185 186} // namespace browser_sync 187 188class TestProfileSyncService : public ProfileSyncService { 189 public: 190 TestProfileSyncService(ProfileSyncFactory* factory, 191 Profile* profile, 192 const std::string& test_user, 193 bool synchronous_backend_initialization, 194 Task* initial_condition_setup_task) 195 : ProfileSyncService(factory, profile, 196 !test_user.empty() ? 197 test_user : ""), 198 synchronous_backend_initialization_( 199 synchronous_backend_initialization), 200 synchronous_sync_configuration_(false), 201 num_expected_resumes_(1), 202 num_expected_pauses_(1), 203 initial_condition_setup_task_(initial_condition_setup_task), 204 set_initial_sync_ended_on_init_(true) { 205 RegisterPreferences(); 206 SetSyncSetupCompleted(); 207 } 208 virtual ~TestProfileSyncService() { } 209 210 virtual void CreateBackend() { 211 backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( 212 this, profile(), 213 profile()->GetPath(), data_type_controllers(), 214 initial_condition_setup_task_.release(), 215 num_expected_resumes_, num_expected_pauses_, 216 set_initial_sync_ended_on_init_, 217 synchronous_backend_initialization_)); 218 } 219 220 virtual void OnBackendInitialized() { 221 ProfileSyncService::OnBackendInitialized(); 222 // TODO(akalin): Figure out a better way to do this. 223 if (synchronous_backend_initialization_) { 224 MessageLoop::current()->Quit(); 225 } 226 } 227 228 virtual void Observe(NotificationType type, 229 const NotificationSource& source, 230 const NotificationDetails& details) { 231 ProfileSyncService::Observe(type, source, details); 232 if (type == NotificationType::SYNC_CONFIGURE_DONE && 233 !synchronous_sync_configuration_) { 234 MessageLoop::current()->Quit(); 235 } 236 } 237 238 void set_num_expected_resumes(int times) { 239 num_expected_resumes_ = times; 240 } 241 void set_num_expected_pauses(int num) { 242 num_expected_pauses_ = num; 243 } 244 void dont_set_initial_sync_ended_on_init() { 245 set_initial_sync_ended_on_init_ = false; 246 } 247 void set_synchronous_sync_configuration() { 248 synchronous_sync_configuration_ = true; 249 } 250 251 private: 252 // When testing under ChromiumOS, this method must not return an empty 253 // value value in order for the profile sync service to start. 254 virtual std::string GetLsidForAuthBootstraping() { 255 return "foo"; 256 } 257 258 bool synchronous_backend_initialization_; 259 260 // Set to true when a mock data type manager is being used and the configure 261 // step is performed synchronously. 262 bool synchronous_sync_configuration_; 263 bool set_expect_resume_expectations_; 264 int num_expected_resumes_; 265 int num_expected_pauses_; 266 267 scoped_ptr<Task> initial_condition_setup_task_; 268 bool set_initial_sync_ended_on_init_; 269}; 270 271#endif // CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_ 272