1// Copyright 2014 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 <vector> 6 7#include "base/deferred_sequenced_task_runner.h" 8#include "base/message_loop/message_loop.h" 9#include "base/thread_task_runner_handle.h" 10#include "sync/engine/model_type_sync_proxy_impl.h" 11#include "sync/internal_api/public/base/model_type.h" 12#include "sync/sessions/model_type_registry.h" 13#include "sync/test/engine/fake_model_worker.h" 14#include "sync/test/engine/mock_nudge_handler.h" 15#include "sync/test/engine/test_directory_setter_upper.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace syncer { 19 20class ModelTypeRegistryTest : public ::testing::Test { 21 public: 22 ModelTypeRegistryTest(); 23 virtual void SetUp() OVERRIDE; 24 virtual void TearDown() OVERRIDE; 25 26 ModelTypeRegistry* registry(); 27 28 static DataTypeState MakeInitialDataTypeState(ModelType type) { 29 DataTypeState state; 30 state.progress_marker.set_data_type_id( 31 GetSpecificsFieldNumberFromModelType(type)); 32 state.next_client_id = 0; 33 return state; 34 } 35 36 private: 37 syncable::Directory* directory(); 38 39 base::MessageLoop message_loop_; 40 41 TestDirectorySetterUpper dir_maker_; 42 std::vector<scoped_refptr<ModelSafeWorker> > workers_; 43 scoped_ptr<ModelTypeRegistry> registry_; 44 MockNudgeHandler mock_nudge_handler_; 45}; 46 47ModelTypeRegistryTest::ModelTypeRegistryTest() {} 48 49void ModelTypeRegistryTest::SetUp() { 50 dir_maker_.SetUp(); 51 scoped_refptr<ModelSafeWorker> passive_worker( 52 new FakeModelWorker(GROUP_PASSIVE)); 53 scoped_refptr<ModelSafeWorker> ui_worker( 54 new FakeModelWorker(GROUP_UI)); 55 scoped_refptr<ModelSafeWorker> db_worker( 56 new FakeModelWorker(GROUP_DB)); 57 workers_.push_back(passive_worker); 58 workers_.push_back(ui_worker); 59 workers_.push_back(db_worker); 60 61 registry_.reset( 62 new ModelTypeRegistry(workers_, directory(), &mock_nudge_handler_)); 63} 64 65void ModelTypeRegistryTest::TearDown() { 66 registry_.reset(); 67 workers_.clear(); 68 dir_maker_.TearDown(); 69} 70 71ModelTypeRegistry* ModelTypeRegistryTest::registry() { 72 return registry_.get(); 73} 74 75syncable::Directory* ModelTypeRegistryTest::directory() { 76 return dir_maker_.directory(); 77} 78 79// Create some directory update handlers and commit contributors. 80// 81// We don't get to inspect any of the state we're modifying. This test is 82// useful only for detecting crashes or memory leaks. 83TEST_F(ModelTypeRegistryTest, SetEnabledDirectoryTypes_Once) { 84 ModelSafeRoutingInfo routing_info; 85 routing_info.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 86 routing_info.insert(std::make_pair(BOOKMARKS, GROUP_UI)); 87 routing_info.insert(std::make_pair(AUTOFILL, GROUP_DB)); 88 89 registry()->SetEnabledDirectoryTypes(routing_info); 90} 91 92// Try two different routing info settings. 93// 94// We don't get to inspect any of the state we're modifying. This test is 95// useful only for detecting crashes or memory leaks. 96TEST_F(ModelTypeRegistryTest, SetEnabledDirectoryTypes_Repeatedly) { 97 ModelSafeRoutingInfo routing_info1; 98 routing_info1.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 99 routing_info1.insert(std::make_pair(BOOKMARKS, GROUP_PASSIVE)); 100 routing_info1.insert(std::make_pair(AUTOFILL, GROUP_PASSIVE)); 101 102 registry()->SetEnabledDirectoryTypes(routing_info1); 103 104 ModelSafeRoutingInfo routing_info2; 105 routing_info2.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 106 routing_info2.insert(std::make_pair(BOOKMARKS, GROUP_UI)); 107 routing_info2.insert(std::make_pair(AUTOFILL, GROUP_DB)); 108 109 registry()->SetEnabledDirectoryTypes(routing_info2); 110} 111 112// Test removing all types from the list. 113// 114// We don't get to inspect any of the state we're modifying. This test is 115// useful only for detecting crashes or memory leaks. 116TEST_F(ModelTypeRegistryTest, SetEnabledDirectoryTypes_Clear) { 117 ModelSafeRoutingInfo routing_info1; 118 routing_info1.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 119 routing_info1.insert(std::make_pair(BOOKMARKS, GROUP_UI)); 120 routing_info1.insert(std::make_pair(AUTOFILL, GROUP_DB)); 121 122 registry()->SetEnabledDirectoryTypes(routing_info1); 123 124 ModelSafeRoutingInfo routing_info2; 125 registry()->SetEnabledDirectoryTypes(routing_info2); 126} 127 128// Test disabling then re-enabling some directory types. 129// 130// We don't get to inspect any of the state we're modifying. This test is 131// useful only for detecting crashes or memory leaks. 132TEST_F(ModelTypeRegistryTest, SetEnabledDirectoryTypes_OffAndOn) { 133 ModelSafeRoutingInfo routing_info1; 134 routing_info1.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 135 routing_info1.insert(std::make_pair(BOOKMARKS, GROUP_UI)); 136 routing_info1.insert(std::make_pair(AUTOFILL, GROUP_DB)); 137 138 registry()->SetEnabledDirectoryTypes(routing_info1); 139 140 ModelSafeRoutingInfo routing_info2; 141 registry()->SetEnabledDirectoryTypes(routing_info2); 142 143 registry()->SetEnabledDirectoryTypes(routing_info1); 144} 145 146TEST_F(ModelTypeRegistryTest, NonBlockingTypes) { 147 ModelTypeSyncProxyImpl themes_sync_proxy(syncer::THEMES); 148 ModelTypeSyncProxyImpl sessions_sync_proxy(syncer::SESSIONS); 149 scoped_refptr<base::DeferredSequencedTaskRunner> task_runner = 150 new base::DeferredSequencedTaskRunner( 151 base::ThreadTaskRunnerHandle::Get()); 152 153 EXPECT_TRUE(registry()->GetEnabledTypes().Empty()); 154 155 registry()->ConnectSyncTypeToWorker(syncer::THEMES, 156 MakeInitialDataTypeState(THEMES), 157 UpdateResponseDataList(), 158 task_runner, 159 themes_sync_proxy.AsWeakPtrForUI()); 160 EXPECT_TRUE(registry()->GetEnabledTypes().Equals( 161 ModelTypeSet(syncer::THEMES))); 162 163 registry()->ConnectSyncTypeToWorker(syncer::SESSIONS, 164 MakeInitialDataTypeState(SESSIONS), 165 UpdateResponseDataList(), 166 task_runner, 167 sessions_sync_proxy.AsWeakPtrForUI()); 168 EXPECT_TRUE(registry()->GetEnabledTypes().Equals( 169 ModelTypeSet(syncer::THEMES, syncer::SESSIONS))); 170 171 registry()->DisconnectSyncWorker(syncer::THEMES); 172 EXPECT_TRUE(registry()->GetEnabledTypes().Equals( 173 ModelTypeSet(syncer::SESSIONS))); 174 175 // Allow ModelTypeRegistry destruction to delete the 176 // Sessions' ModelTypeSyncWorker. 177} 178 179TEST_F(ModelTypeRegistryTest, NonBlockingTypesWithDirectoryTypes) { 180 ModelTypeSyncProxyImpl themes_sync_proxy(syncer::THEMES); 181 ModelTypeSyncProxyImpl sessions_sync_proxy(syncer::SESSIONS); 182 scoped_refptr<base::DeferredSequencedTaskRunner> task_runner = 183 new base::DeferredSequencedTaskRunner( 184 base::ThreadTaskRunnerHandle::Get()); 185 186 ModelSafeRoutingInfo routing_info1; 187 routing_info1.insert(std::make_pair(NIGORI, GROUP_PASSIVE)); 188 routing_info1.insert(std::make_pair(BOOKMARKS, GROUP_UI)); 189 routing_info1.insert(std::make_pair(AUTOFILL, GROUP_DB)); 190 191 ModelTypeSet current_types; 192 EXPECT_TRUE(registry()->GetEnabledTypes().Empty()); 193 194 // Add the themes non-blocking type. 195 registry()->ConnectSyncTypeToWorker(syncer::THEMES, 196 MakeInitialDataTypeState(THEMES), 197 UpdateResponseDataList(), 198 task_runner, 199 themes_sync_proxy.AsWeakPtrForUI()); 200 current_types.Put(syncer::THEMES); 201 EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types)); 202 203 // Add some directory types. 204 registry()->SetEnabledDirectoryTypes(routing_info1); 205 current_types.PutAll(GetRoutingInfoTypes(routing_info1)); 206 EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types)); 207 208 // Add sessions non-blocking type. 209 registry()->ConnectSyncTypeToWorker(syncer::SESSIONS, 210 MakeInitialDataTypeState(SESSIONS), 211 UpdateResponseDataList(), 212 task_runner, 213 sessions_sync_proxy.AsWeakPtrForUI()); 214 current_types.Put(syncer::SESSIONS); 215 EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types)); 216 217 // Remove themes non-blocking type. 218 registry()->DisconnectSyncWorker(syncer::THEMES); 219 current_types.Remove(syncer::THEMES); 220 EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types)); 221 222 // Clear all directory types. 223 ModelSafeRoutingInfo routing_info2; 224 registry()->SetEnabledDirectoryTypes(routing_info2); 225 current_types.RemoveAll(GetRoutingInfoTypes(routing_info1)); 226 EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types)); 227} 228 229TEST_F(ModelTypeRegistryTest, DeletionOrdering) { 230 scoped_ptr<ModelTypeSyncProxyImpl> themes_sync_proxy( 231 new ModelTypeSyncProxyImpl(syncer::THEMES)); 232 scoped_ptr<ModelTypeSyncProxyImpl> sessions_sync_proxy( 233 new ModelTypeSyncProxyImpl(syncer::SESSIONS)); 234 scoped_refptr<base::DeferredSequencedTaskRunner> task_runner = 235 new base::DeferredSequencedTaskRunner( 236 base::ThreadTaskRunnerHandle::Get()); 237 238 EXPECT_TRUE(registry()->GetEnabledTypes().Empty()); 239 240 registry()->ConnectSyncTypeToWorker(syncer::THEMES, 241 MakeInitialDataTypeState(THEMES), 242 UpdateResponseDataList(), 243 task_runner, 244 themes_sync_proxy->AsWeakPtrForUI()); 245 registry()->ConnectSyncTypeToWorker(syncer::SESSIONS, 246 MakeInitialDataTypeState(SESSIONS), 247 UpdateResponseDataList(), 248 task_runner, 249 sessions_sync_proxy->AsWeakPtrForUI()); 250 EXPECT_TRUE(registry()->GetEnabledTypes().Equals( 251 ModelTypeSet(syncer::THEMES, syncer::SESSIONS))); 252 253 // Tear down themes processing, starting with the worker. 254 registry()->DisconnectSyncWorker(syncer::THEMES); 255 themes_sync_proxy.reset(); 256 257 // Tear down sessions processing, starting with the type sync proxy. 258 sessions_sync_proxy.reset(); 259 registry()->DisconnectSyncWorker(syncer::SESSIONS); 260 261 EXPECT_TRUE(registry()->GetEnabledTypes().Empty()); 262} 263 264} // namespace syncer 265