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 "base/bind.h"
6#include "base/json/json_writer.h"
7#include "base/prefs/pref_service.h"
8#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h"
9#include "chrome/common/pref_names.h"
10#include "chrome/test/base/testing_profile.h"
11#include "sync/api/fake_sync_change_processor.h"
12#include "sync/api/sync_change.h"
13#include "sync/api/sync_change_processor_wrapper_for_test.h"
14#include "sync/api/sync_error_factory_mock.h"
15#include "sync/protocol/sync.pb.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18using base::DictionaryValue;
19using base::FundamentalValue;
20using base::StringValue;
21using base::Value;
22using sync_pb::ManagedUserSharedSettingSpecifics;
23using syncer::SUPERVISED_USER_SHARED_SETTINGS;
24using syncer::SyncChange;
25using syncer::SyncChangeList;
26using syncer::SyncChangeProcessor;
27using syncer::SyncChangeProcessorWrapperForTest;
28using syncer::SyncData;
29using syncer::SyncDataList;
30using syncer::SyncError;
31using syncer::SyncErrorFactory;
32using syncer::SyncMergeResult;
33
34namespace {
35
36class MockSyncErrorFactory : public syncer::SyncErrorFactory {
37 public:
38  explicit MockSyncErrorFactory(syncer::ModelType type);
39  virtual ~MockSyncErrorFactory();
40
41  // SyncErrorFactory implementation:
42  virtual syncer::SyncError CreateAndUploadError(
43      const tracked_objects::Location& location,
44      const std::string& message) OVERRIDE;
45
46 private:
47  syncer::ModelType type_;
48
49  DISALLOW_COPY_AND_ASSIGN(MockSyncErrorFactory);
50};
51
52MockSyncErrorFactory::MockSyncErrorFactory(syncer::ModelType type)
53    : type_(type) {}
54
55MockSyncErrorFactory::~MockSyncErrorFactory() {}
56
57syncer::SyncError MockSyncErrorFactory::CreateAndUploadError(
58    const tracked_objects::Location& location,
59    const std::string& message) {
60  return syncer::SyncError(location, SyncError::DATATYPE_ERROR, message, type_);
61}
62
63// Convenience method to allow us to use EXPECT_EQ to compare values.
64std::string ToJson(const Value* value) {
65  if (!value)
66    return std::string();
67
68  std::string json_value;
69  base::JSONWriter::Write(value, &json_value);
70  return json_value;
71}
72
73}  // namespace
74
75class SupervisedUserSharedSettingsServiceTest : public ::testing::Test {
76 protected:
77  typedef base::CallbackList<void(const std::string&, const std::string&)>
78      CallbackList;
79
80  SupervisedUserSharedSettingsServiceTest()
81      : settings_service_(profile_.GetPrefs()) {}
82  virtual ~SupervisedUserSharedSettingsServiceTest() {}
83
84  void StartSyncing(const syncer::SyncDataList& initial_sync_data) {
85    sync_processor_.reset(new syncer::FakeSyncChangeProcessor);
86    scoped_ptr<syncer::SyncErrorFactory> error_handler(
87        new MockSyncErrorFactory(SUPERVISED_USER_SHARED_SETTINGS));
88    SyncMergeResult result = settings_service_.MergeDataAndStartSyncing(
89        SUPERVISED_USER_SHARED_SETTINGS,
90        initial_sync_data,
91        scoped_ptr<SyncChangeProcessor>(
92            new SyncChangeProcessorWrapperForTest(sync_processor_.get())),
93        error_handler.Pass());
94    EXPECT_FALSE(result.error().IsSet());
95  }
96
97  const base::DictionaryValue* GetAllSettings() {
98    return profile_.GetPrefs()->GetDictionary(
99        prefs::kSupervisedUserSharedSettings);
100  }
101
102  void VerifySyncChangesAndClear() {
103    SyncChangeList& changes = sync_processor_->changes();
104    for (SyncChangeList::const_iterator it = changes.begin();
105         it != changes.end();
106         ++it) {
107      const sync_pb::ManagedUserSharedSettingSpecifics& setting =
108          it->sync_data().GetSpecifics().managed_user_shared_setting();
109      EXPECT_EQ(
110          setting.value(),
111          ToJson(settings_service_.GetValue(setting.mu_id(), setting.key())));
112    }
113    changes.clear();
114  }
115
116  // testing::Test overrides:
117  virtual void SetUp() OVERRIDE {
118    subscription_ = settings_service_.Subscribe(
119        base::Bind(&SupervisedUserSharedSettingsServiceTest::OnSettingChanged,
120                   base::Unretained(this)));
121  }
122
123  virtual void TearDown() OVERRIDE { settings_service_.Shutdown(); }
124
125  void OnSettingChanged(const std::string& su_id, const std::string& key) {
126    const Value* value = settings_service_.GetValue(su_id, key);
127    ASSERT_TRUE(value);
128    changed_settings_.push_back(
129        SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
130            su_id, key, *value, true));
131  }
132
133  TestingProfile profile_;
134  SupervisedUserSharedSettingsService settings_service_;
135  SyncDataList changed_settings_;
136
137  scoped_ptr<CallbackList::Subscription> subscription_;
138
139  scoped_ptr<syncer::FakeSyncChangeProcessor> sync_processor_;
140};
141
142TEST_F(SupervisedUserSharedSettingsServiceTest, Empty) {
143  StartSyncing(SyncDataList());
144  EXPECT_EQ(0u, sync_processor_->changes().size());
145  EXPECT_EQ(0u, changed_settings_.size());
146  EXPECT_EQ(
147      0u,
148      settings_service_.GetAllSyncData(SUPERVISED_USER_SHARED_SETTINGS).size());
149  EXPECT_EQ(0u, GetAllSettings()->size());
150}
151
152TEST_F(SupervisedUserSharedSettingsServiceTest, SetAndGet) {
153  StartSyncing(SyncDataList());
154
155  const char kIdA[] = "aaaaaa";
156  const char kIdB[] = "bbbbbb";
157  const char kIdC[] = "cccccc";
158
159  StringValue name("Jack");
160  FundamentalValue age(8);
161  StringValue bar("bar");
162  settings_service_.SetValue(kIdA, "name", name);
163  ASSERT_EQ(1u, sync_processor_->changes().size());
164  VerifySyncChangesAndClear();
165  settings_service_.SetValue(kIdA, "age", FundamentalValue(6));
166  ASSERT_EQ(1u, sync_processor_->changes().size());
167  VerifySyncChangesAndClear();
168  settings_service_.SetValue(kIdA, "age", age);
169  ASSERT_EQ(1u, sync_processor_->changes().size());
170  VerifySyncChangesAndClear();
171  settings_service_.SetValue(kIdB, "foo", bar);
172  ASSERT_EQ(1u, sync_processor_->changes().size());
173  VerifySyncChangesAndClear();
174
175  EXPECT_EQ(
176      3u,
177      settings_service_.GetAllSyncData(SUPERVISED_USER_SHARED_SETTINGS).size());
178
179  EXPECT_EQ(ToJson(&name), ToJson(settings_service_.GetValue(kIdA, "name")));
180  EXPECT_EQ(ToJson(&age), ToJson(settings_service_.GetValue(kIdA, "age")));
181  EXPECT_EQ(ToJson(&bar), ToJson(settings_service_.GetValue(kIdB, "foo")));
182  EXPECT_FALSE(settings_service_.GetValue(kIdA, "foo"));
183  EXPECT_FALSE(settings_service_.GetValue(kIdB, "name"));
184  EXPECT_FALSE(settings_service_.GetValue(kIdC, "name"));
185}
186
187TEST_F(SupervisedUserSharedSettingsServiceTest, Merge) {
188  // Set initial values, then stop syncing so we can restart.
189  StartSyncing(SyncDataList());
190
191  const char kIdA[] = "aaaaaa";
192  const char kIdB[] = "bbbbbb";
193  const char kIdC[] = "cccccc";
194
195  FundamentalValue age(8);
196  StringValue bar("bar");
197  settings_service_.SetValue(kIdA, "name", StringValue("Jack"));
198  settings_service_.SetValue(kIdA, "age", age);
199  settings_service_.SetValue(kIdB, "foo", bar);
200
201  settings_service_.StopSyncing(SUPERVISED_USER_SHARED_SETTINGS);
202
203  StringValue name("Jill");
204  StringValue blurp("blurp");
205  SyncDataList sync_data;
206  sync_data.push_back(
207      SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
208          kIdA, "name", name, true));
209  sync_data.push_back(
210      SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
211          kIdC, "baz", blurp, true));
212
213  StartSyncing(sync_data);
214  EXPECT_EQ(2u, sync_processor_->changes().size());
215  VerifySyncChangesAndClear();
216  EXPECT_EQ(2u, changed_settings_.size());
217
218  EXPECT_EQ(
219      4u,
220      settings_service_.GetAllSyncData(SUPERVISED_USER_SHARED_SETTINGS).size());
221  EXPECT_EQ(ToJson(&name),
222            ToJson(settings_service_.GetValue(kIdA, "name")));
223  EXPECT_EQ(ToJson(&age), ToJson(settings_service_.GetValue(kIdA, "age")));
224  EXPECT_EQ(ToJson(&bar), ToJson(settings_service_.GetValue(kIdB, "foo")));
225  EXPECT_EQ(ToJson(&blurp), ToJson(settings_service_.GetValue(kIdC, "baz")));
226  EXPECT_FALSE(settings_service_.GetValue(kIdA, "foo"));
227  EXPECT_FALSE(settings_service_.GetValue(kIdB, "name"));
228  EXPECT_FALSE(settings_service_.GetValue(kIdC, "name"));
229}
230
231TEST_F(SupervisedUserSharedSettingsServiceTest, ProcessChanges) {
232  StartSyncing(SyncDataList());
233
234  const char kIdA[] = "aaaaaa";
235  const char kIdB[] = "bbbbbb";
236  const char kIdC[] = "cccccc";
237
238  FundamentalValue age(8);
239  StringValue bar("bar");
240  settings_service_.SetValue(kIdA, "name", StringValue("Jack"));
241  settings_service_.SetValue(kIdA, "age", age);
242  settings_service_.SetValue(kIdB, "foo", bar);
243
244  StringValue name("Jill");
245  StringValue blurp("blurp");
246  SyncChangeList changes;
247  changes.push_back(
248      SyncChange(FROM_HERE,
249                 SyncChange::ACTION_UPDATE,
250                 SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
251                     kIdA, "name", name, true)));
252  changes.push_back(
253      SyncChange(FROM_HERE,
254                 SyncChange::ACTION_ADD,
255                 SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
256                     kIdC, "baz", blurp, true)));
257  SyncError error = settings_service_.ProcessSyncChanges(FROM_HERE, changes);
258  EXPECT_FALSE(error.IsSet()) << error.ToString();
259  EXPECT_EQ(2u, changed_settings_.size());
260
261  EXPECT_EQ(
262      4u,
263      settings_service_.GetAllSyncData(SUPERVISED_USER_SHARED_SETTINGS).size());
264  EXPECT_EQ(ToJson(&name),
265            ToJson(settings_service_.GetValue(kIdA, "name")));
266  EXPECT_EQ(ToJson(&age), ToJson(settings_service_.GetValue(kIdA, "age")));
267  EXPECT_EQ(ToJson(&bar), ToJson(settings_service_.GetValue(kIdB, "foo")));
268  EXPECT_EQ(ToJson(&blurp), ToJson(settings_service_.GetValue(kIdC, "baz")));
269  EXPECT_FALSE(settings_service_.GetValue(kIdA, "foo"));
270  EXPECT_FALSE(settings_service_.GetValue(kIdB, "name"));
271  EXPECT_FALSE(settings_service_.GetValue(kIdC, "name"));
272}
273