1 // Copyright 2013 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.
6 #include "base/callback.h"
7 #include "base/json/json_reader.h"
8 #include "base/prefs/testing_pref_store.h"
9 #include "base/strings/string_util.h"
10 #include "chrome/browser/managed_mode/managed_user_settings_service.h"
11 #include "sync/api/sync_change.h"
12 #include "sync/api/sync_error_factory_mock.h"
13 #include "sync/protocol/sync.pb.h"
14 #include "testing/gtest/include/gtest/gtest.h"
18 class MockChangeProcessor
: public syncer::SyncChangeProcessor
{
20 MockChangeProcessor() {}
21 virtual ~MockChangeProcessor() {}
23 // SyncChangeProcessor implementation:
24 virtual syncer::SyncError
ProcessSyncChanges(
25 const tracked_objects::Location
& from_here
,
26 const syncer::SyncChangeList
& change_list
) OVERRIDE
;
27 virtual syncer::SyncDataList
GetAllSyncData(syncer::ModelType type
) const
30 const syncer::SyncChangeList
& changes() const { return change_list_
; }
33 syncer::SyncChangeList change_list_
;
35 DISALLOW_COPY_AND_ASSIGN(MockChangeProcessor
);
38 syncer::SyncError
MockChangeProcessor::ProcessSyncChanges(
39 const tracked_objects::Location
& from_here
,
40 const syncer::SyncChangeList
& change_list
) {
41 change_list_
= change_list
;
42 return syncer::SyncError();
45 syncer::SyncDataList
MockChangeProcessor::GetAllSyncData(
46 syncer::ModelType type
) const {
47 return syncer::SyncDataList();
50 class MockSyncErrorFactory
: public syncer::SyncErrorFactory
{
52 explicit MockSyncErrorFactory(syncer::ModelType type
);
53 virtual ~MockSyncErrorFactory();
55 // SyncErrorFactory implementation:
56 virtual syncer::SyncError
CreateAndUploadError(
57 const tracked_objects::Location
& location
,
58 const std::string
& message
) OVERRIDE
;
61 syncer::ModelType type_
;
63 DISALLOW_COPY_AND_ASSIGN(MockSyncErrorFactory
);
66 MockSyncErrorFactory::MockSyncErrorFactory(syncer::ModelType type
)
69 MockSyncErrorFactory::~MockSyncErrorFactory() {}
71 syncer::SyncError
MockSyncErrorFactory::CreateAndUploadError(
72 const tracked_objects::Location
& location
,
73 const std::string
& message
) {
74 return syncer::SyncError(location
,
75 syncer::SyncError::DATATYPE_ERROR
,
82 const char kAtomicItemName
[] = "X-Wombat";
83 const char kSettingsName
[] = "TestingSetting";
84 const char kSettingsValue
[] = "SettingsValue";
85 const char kSplitItemName
[] = "X-SuperMoosePowers";
87 class ManagedUserSettingsServiceTest
: public ::testing::Test
{
89 ManagedUserSettingsServiceTest() {}
90 virtual ~ManagedUserSettingsServiceTest() {}
92 scoped_ptr
<syncer::SyncChangeProcessor
> CreateSyncProcessor() {
93 sync_processor_
= new MockChangeProcessor();
94 return scoped_ptr
<syncer::SyncChangeProcessor
>(sync_processor_
);
97 void StartSyncing(const syncer::SyncDataList
& initial_sync_data
) {
98 scoped_ptr
<syncer::SyncErrorFactory
> error_handler(
99 new MockSyncErrorFactory(syncer::MANAGED_USER_SETTINGS
));
100 syncer::SyncMergeResult result
= settings_service_
.MergeDataAndStartSyncing(
101 syncer::MANAGED_USER_SETTINGS
,
103 CreateSyncProcessor(),
104 error_handler
.Pass());
105 EXPECT_FALSE(result
.error().IsSet());
108 void UploadSplitItem(const std::string
& key
, const std::string
& value
) {
109 split_items_
.SetStringWithoutPathExpansion(key
, value
);
110 settings_service_
.UploadItem(
111 ManagedUserSettingsService::MakeSplitSettingKey(kSplitItemName
,
113 scoped_ptr
<base::Value
>(new base::StringValue(value
)));
116 void UploadAtomicItem(const std::string
& value
) {
117 atomic_setting_value_
.reset(new base::StringValue(value
));
118 settings_service_
.UploadItem(
120 scoped_ptr
<base::Value
>(new base::StringValue(value
)));
123 void VerifySyncDataItem(syncer::SyncData sync_data
) {
124 const sync_pb::ManagedUserSettingSpecifics
& managed_user_setting
=
125 sync_data
.GetSpecifics().managed_user_setting();
126 base::Value
* expected_value
= NULL
;
127 if (managed_user_setting
.name() == kAtomicItemName
) {
128 expected_value
= atomic_setting_value_
.get();
130 EXPECT_TRUE(StartsWithASCII(managed_user_setting
.name(),
131 std::string(kSplitItemName
) + ':',
134 managed_user_setting
.name().substr(strlen(kSplitItemName
) + 1);
135 EXPECT_TRUE(split_items_
.GetWithoutPathExpansion(key
, &expected_value
));
138 scoped_ptr
<base::Value
> value(
139 base::JSONReader::Read(managed_user_setting
.value()));
140 EXPECT_TRUE(expected_value
->Equals(value
.get()));
143 void OnNewSettingsAvailable(const base::DictionaryValue
* settings
) {
147 settings_
.reset(settings
->DeepCopy());
150 // testing::Test overrides:
151 virtual void SetUp() OVERRIDE
{
152 TestingPrefStore
* pref_store
= new TestingPrefStore
;
153 settings_service_
.Init(pref_store
);
154 settings_service_
.Subscribe(
155 base::Bind(&ManagedUserSettingsServiceTest::OnNewSettingsAvailable
,
156 base::Unretained(this)));
157 pref_store
->SetInitializationCompleted();
158 ASSERT_FALSE(settings_
);
159 settings_service_
.Activate();
160 ASSERT_TRUE(settings_
);
163 virtual void TearDown() OVERRIDE
{
164 settings_service_
.Shutdown();
167 base::DictionaryValue split_items_
;
168 scoped_ptr
<base::Value
> atomic_setting_value_
;
169 ManagedUserSettingsService settings_service_
;
170 scoped_ptr
<base::DictionaryValue
> settings_
;
172 // Owned by the ManagedUserSettingsService.
173 MockChangeProcessor
* sync_processor_
;
176 TEST_F(ManagedUserSettingsServiceTest
, ProcessAtomicSetting
) {
177 StartSyncing(syncer::SyncDataList());
178 ASSERT_TRUE(settings_
);
179 const base::Value
* value
= NULL
;
180 EXPECT_FALSE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
183 syncer::SyncData data
=
184 ManagedUserSettingsService::CreateSyncDataForSetting(
185 kSettingsName
, base::StringValue(kSettingsValue
));
186 syncer::SyncChangeList change_list
;
187 change_list
.push_back(
188 syncer::SyncChange(FROM_HERE
, syncer::SyncChange::ACTION_ADD
, data
));
189 syncer::SyncError error
=
190 settings_service_
.ProcessSyncChanges(FROM_HERE
, change_list
);
191 EXPECT_FALSE(error
.IsSet()) << error
.ToString();
192 ASSERT_TRUE(settings_
);
193 ASSERT_TRUE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
194 std::string string_value
;
195 EXPECT_TRUE(value
->GetAsString(&string_value
));
196 EXPECT_EQ(kSettingsValue
, string_value
);
199 TEST_F(ManagedUserSettingsServiceTest
, ProcessSplitSetting
) {
200 StartSyncing(syncer::SyncDataList());
201 ASSERT_TRUE(settings_
);
202 const base::Value
* value
= NULL
;
203 EXPECT_FALSE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
205 base::DictionaryValue dict
;
206 dict
.SetString("foo", "bar");
207 dict
.SetBoolean("awesomesauce", true);
208 dict
.SetInteger("eaudecologne", 4711);
211 syncer::SyncChangeList change_list
;
212 for (base::DictionaryValue::Iterator
it(dict
); !it
.IsAtEnd(); it
.Advance()) {
213 syncer::SyncData data
=
214 ManagedUserSettingsService::CreateSyncDataForSetting(
215 ManagedUserSettingsService::MakeSplitSettingKey(kSettingsName
,
218 change_list
.push_back(
219 syncer::SyncChange(FROM_HERE
, syncer::SyncChange::ACTION_ADD
, data
));
221 syncer::SyncError error
=
222 settings_service_
.ProcessSyncChanges(FROM_HERE
, change_list
);
223 EXPECT_FALSE(error
.IsSet()) << error
.ToString();
224 ASSERT_TRUE(settings_
);
225 ASSERT_TRUE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
226 const base::DictionaryValue
* dict_value
= NULL
;
227 ASSERT_TRUE(value
->GetAsDictionary(&dict_value
));
228 EXPECT_TRUE(dict_value
->Equals(&dict
));
231 TEST_F(ManagedUserSettingsServiceTest
, SetLocalSetting
) {
232 const base::Value
* value
= NULL
;
233 EXPECT_FALSE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
236 settings_service_
.SetLocalSettingForTesting(
238 scoped_ptr
<base::Value
>(new base::StringValue(kSettingsValue
)));
239 ASSERT_TRUE(settings_
);
240 ASSERT_TRUE(settings_
->GetWithoutPathExpansion(kSettingsName
, &value
));
241 std::string string_value
;
242 EXPECT_TRUE(value
->GetAsString(&string_value
));
243 EXPECT_EQ(kSettingsValue
, string_value
);
246 TEST_F(ManagedUserSettingsServiceTest
, UploadItem
) {
247 UploadSplitItem("foo", "bar");
248 UploadSplitItem("blurp", "baz");
249 UploadAtomicItem("hurdle");
251 // Uploading should produce changes when we start syncing.
252 StartSyncing(syncer::SyncDataList());
253 const syncer::SyncChangeList
& changes
= sync_processor_
->changes();
254 ASSERT_EQ(3u, changes
.size());
255 for (syncer::SyncChangeList::const_iterator it
= changes
.begin();
256 it
!= changes
.end(); ++it
) {
257 ASSERT_TRUE(it
->IsValid());
258 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, it
->change_type());
259 VerifySyncDataItem(it
->sync_data());
262 // It should also show up in local Sync data.
263 syncer::SyncDataList sync_data
=
264 settings_service_
.GetAllSyncData(syncer::MANAGED_USER_SETTINGS
);
265 EXPECT_EQ(3u, sync_data
.size());
266 for (syncer::SyncDataList::const_iterator it
= sync_data
.begin();
267 it
!= sync_data
.end(); ++it
) {
268 VerifySyncDataItem(*it
);
271 // Uploading after we have started syncing should work too.
272 UploadSplitItem("froodle", "narf");
273 ASSERT_EQ(1u, sync_processor_
->changes().size());
274 syncer::SyncChange change
= sync_processor_
->changes()[0];
275 ASSERT_TRUE(change
.IsValid());
276 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, change
.change_type());
277 VerifySyncDataItem(change
.sync_data());
279 sync_data
= settings_service_
.GetAllSyncData(syncer::MANAGED_USER_SETTINGS
);
280 EXPECT_EQ(4u, sync_data
.size());
281 for (syncer::SyncDataList::const_iterator it
= sync_data
.begin();
282 it
!= sync_data
.end(); ++it
) {
283 VerifySyncDataItem(*it
);
286 // Uploading an item with a previously seen key should create an UPDATE
288 UploadSplitItem("blurp", "snarl");
289 ASSERT_EQ(1u, sync_processor_
->changes().size());
290 change
= sync_processor_
->changes()[0];
291 ASSERT_TRUE(change
.IsValid());
292 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, change
.change_type());
293 VerifySyncDataItem(change
.sync_data());
295 sync_data
= settings_service_
.GetAllSyncData(syncer::MANAGED_USER_SETTINGS
);
296 EXPECT_EQ(4u, sync_data
.size());
297 for (syncer::SyncDataList::const_iterator it
= sync_data
.begin();
298 it
!= sync_data
.end(); ++it
) {
299 VerifySyncDataItem(*it
);
302 UploadAtomicItem("fjord");
303 ASSERT_EQ(1u, sync_processor_
->changes().size());
304 change
= sync_processor_
->changes()[0];
305 ASSERT_TRUE(change
.IsValid());
306 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, change
.change_type());
307 VerifySyncDataItem(change
.sync_data());
309 sync_data
= settings_service_
.GetAllSyncData(syncer::MANAGED_USER_SETTINGS
);
310 EXPECT_EQ(4u, sync_data
.size());
311 for (syncer::SyncDataList::const_iterator it
= sync_data
.begin();
312 it
!= sync_data
.end(); ++it
) {
313 VerifySyncDataItem(*it
);
316 // The uploaded items should not show up as settings.
317 const base::Value
* value
= NULL
;
318 EXPECT_FALSE(settings_
->GetWithoutPathExpansion(kAtomicItemName
, &value
));
319 EXPECT_FALSE(settings_
->GetWithoutPathExpansion(kSplitItemName
, &value
));
321 // Restarting sync should not create any new changes.
322 settings_service_
.StopSyncing(syncer::MANAGED_USER_SETTINGS
);
323 StartSyncing(sync_data
);
324 ASSERT_EQ(0u, sync_processor_
->changes().size());