1// Copyright (c) 2011 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/memory/scoped_ptr.h"
6#include "base/values.h"
7#include "chrome/browser/prefs/pref_model_associator.h"
8#include "chrome/browser/prefs/scoped_user_pref_update.h"
9#include "chrome/common/pref_names.h"
10#include "chrome/test/base/testing_profile.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13class AbstractPreferenceMergeTest : public testing::Test {
14 protected:
15  virtual void SetUp() {
16    pref_service_ = profile_.GetPrefs();
17  }
18
19  void SetContentPattern(DictionaryValue* patterns_dict,
20                         const std::string& expression,
21                         const std::string& content_type,
22                         int setting) {
23    DictionaryValue* expression_dict;
24    bool found =
25        patterns_dict->GetDictionaryWithoutPathExpansion(expression,
26                                                         &expression_dict);
27    if (!found) {
28      expression_dict = new DictionaryValue;
29      patterns_dict->SetWithoutPathExpansion(expression, expression_dict);
30    }
31    expression_dict->SetWithoutPathExpansion(
32        content_type,
33        Value::CreateIntegerValue(setting));
34  }
35
36  void SetPrefToEmpty(const std::string& pref_name) {
37    scoped_ptr<Value> empty_value;
38    const PrefService::Preference* pref =
39        pref_service_->FindPreference(pref_name.c_str());
40    ASSERT_TRUE(pref);
41    base::Value::Type type = pref->GetType();
42    if (type == Value::TYPE_DICTIONARY)
43      empty_value.reset(new DictionaryValue);
44    else if (type == Value::TYPE_LIST)
45      empty_value.reset(new ListValue);
46    else
47      FAIL();
48    pref_service_->Set(pref_name.c_str(), *empty_value);
49  }
50
51  TestingProfile profile_;
52  PrefService* pref_service_;
53};
54
55class ListPreferenceMergeTest : public AbstractPreferenceMergeTest {
56 protected:
57  ListPreferenceMergeTest() :
58      server_url0_("http://example.com/server0"),
59      server_url1_("http://example.com/server1"),
60      local_url0_("http://example.com/local0"),
61      local_url1_("http://example.com/local1") {}
62
63  virtual void SetUp() {
64    AbstractPreferenceMergeTest::SetUp();
65    server_url_list_.Append(Value::CreateStringValue(server_url0_));
66    server_url_list_.Append(Value::CreateStringValue(server_url1_));
67  }
68
69  std::string server_url0_;
70  std::string server_url1_;
71  std::string local_url0_;
72  std::string local_url1_;
73  ListValue server_url_list_;
74};
75
76TEST_F(ListPreferenceMergeTest, NotListOrDictionary) {
77  pref_service_->SetString(prefs::kHomePage, local_url0_);
78  const PrefService::Preference* pref =
79      pref_service_->FindPreference(prefs::kHomePage);
80  scoped_ptr<Value> server_value(Value::CreateStringValue(server_url0_));
81  scoped_ptr<Value> merged_value(
82      PrefModelAssociator::MergePreference(pref->name(),
83                                           *pref->GetValue(),
84                                           *server_value));
85  EXPECT_TRUE(merged_value->Equals(server_value.get()));
86}
87
88TEST_F(ListPreferenceMergeTest, LocalEmpty) {
89  SetPrefToEmpty(prefs::kURLsToRestoreOnStartup);
90  const PrefService::Preference* pref =
91      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
92  scoped_ptr<Value> merged_value(
93      PrefModelAssociator::MergePreference(pref->name(),
94                                           *pref->GetValue(),
95                                           server_url_list_));
96  EXPECT_TRUE(merged_value->Equals(&server_url_list_));
97}
98
99TEST_F(ListPreferenceMergeTest, ServerNull) {
100  scoped_ptr<Value> null_value(Value::CreateNullValue());
101  {
102    ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup);
103    ListValue* local_list_value = update.Get();
104    local_list_value->Append(Value::CreateStringValue(local_url0_));
105  }
106
107  const PrefService::Preference* pref =
108      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
109  scoped_ptr<Value> merged_value(
110      PrefModelAssociator::MergePreference(pref->name(),
111                                           *pref->GetValue(),
112                                           *null_value));
113  const ListValue* local_list_value =
114        pref_service_->GetList(prefs::kURLsToRestoreOnStartup);
115  EXPECT_TRUE(merged_value->Equals(local_list_value));
116}
117
118TEST_F(ListPreferenceMergeTest, ServerEmpty) {
119  scoped_ptr<Value> empty_value(new ListValue);
120  {
121    ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup);
122    ListValue* local_list_value = update.Get();
123    local_list_value->Append(Value::CreateStringValue(local_url0_));
124  }
125
126  const PrefService::Preference* pref =
127      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
128  scoped_ptr<Value> merged_value(
129      PrefModelAssociator::MergePreference(pref->name(),
130                                           *pref->GetValue(),
131                                           *empty_value));
132  const ListValue* local_list_value =
133        pref_service_->GetList(prefs::kURLsToRestoreOnStartup);
134  EXPECT_TRUE(merged_value->Equals(local_list_value));
135}
136
137TEST_F(ListPreferenceMergeTest, Merge) {
138  {
139    ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup);
140    ListValue* local_list_value = update.Get();
141    local_list_value->Append(Value::CreateStringValue(local_url0_));
142    local_list_value->Append(Value::CreateStringValue(local_url1_));
143  }
144
145  const PrefService::Preference* pref =
146      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
147  scoped_ptr<Value> merged_value(
148      PrefModelAssociator::MergePreference(pref->name(),
149                                           *pref->GetValue(),
150                                           server_url_list_));
151
152  ListValue expected;
153  expected.Append(Value::CreateStringValue(server_url0_));
154  expected.Append(Value::CreateStringValue(server_url1_));
155  expected.Append(Value::CreateStringValue(local_url0_));
156  expected.Append(Value::CreateStringValue(local_url1_));
157  EXPECT_TRUE(merged_value->Equals(&expected));
158}
159
160TEST_F(ListPreferenceMergeTest, Duplicates) {
161  {
162    ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup);
163    ListValue* local_list_value = update.Get();
164    local_list_value->Append(Value::CreateStringValue(local_url0_));
165    local_list_value->Append(Value::CreateStringValue(server_url0_));
166    local_list_value->Append(Value::CreateStringValue(server_url1_));
167  }
168
169  const PrefService::Preference* pref =
170      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
171  scoped_ptr<Value> merged_value(
172      PrefModelAssociator::MergePreference(pref->name(),
173                                           *pref->GetValue(),
174                                           server_url_list_));
175
176  ListValue expected;
177  expected.Append(Value::CreateStringValue(server_url0_));
178  expected.Append(Value::CreateStringValue(server_url1_));
179  expected.Append(Value::CreateStringValue(local_url0_));
180  EXPECT_TRUE(merged_value->Equals(&expected));
181}
182
183TEST_F(ListPreferenceMergeTest, Equals) {
184  {
185    ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup);
186    ListValue* local_list_value = update.Get();
187    local_list_value->Append(Value::CreateStringValue(server_url0_));
188    local_list_value->Append(Value::CreateStringValue(server_url1_));
189  }
190
191  scoped_ptr<Value> original(server_url_list_.DeepCopy());
192  const PrefService::Preference* pref =
193      pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
194  scoped_ptr<Value> merged_value(
195      PrefModelAssociator::MergePreference(pref->name(),
196                                           *pref->GetValue(),
197                                           server_url_list_));
198  EXPECT_TRUE(merged_value->Equals(original.get()));
199}
200
201class DictionaryPreferenceMergeTest : public AbstractPreferenceMergeTest {
202 protected:
203  DictionaryPreferenceMergeTest() :
204      expression0_("expression0"),
205      expression1_("expression1"),
206      expression2_("expression2"),
207      content_type0_("content_type0"),
208      content_type1_("content_type1") {}
209
210  virtual void SetUp() {
211    AbstractPreferenceMergeTest::SetUp();
212    SetContentPattern(&server_patterns_, expression0_, content_type0_, 1);
213    SetContentPattern(&server_patterns_, expression0_, content_type1_, 2);
214    SetContentPattern(&server_patterns_, expression1_, content_type0_, 1);
215  }
216
217  std::string expression0_;
218  std::string expression1_;
219  std::string expression2_;
220  std::string content_type0_;
221  std::string content_type1_;
222  DictionaryValue server_patterns_;
223};
224
225TEST_F(DictionaryPreferenceMergeTest, LocalEmpty) {
226  SetPrefToEmpty(prefs::kContentSettingsPatternPairs);
227  const PrefService::Preference* pref =
228      pref_service_->FindPreference(prefs::kContentSettingsPatternPairs);
229  scoped_ptr<Value> merged_value(
230      PrefModelAssociator::MergePreference(pref->name(),
231                                           *pref->GetValue(),
232                                           server_patterns_));
233  EXPECT_TRUE(merged_value->Equals(&server_patterns_));
234}
235
236TEST_F(DictionaryPreferenceMergeTest, ServerNull) {
237  scoped_ptr<Value> null_value(Value::CreateNullValue());
238  {
239    DictionaryPrefUpdate update(pref_service_,
240                                prefs::kContentSettingsPatternPairs);
241    DictionaryValue* local_dict_value = update.Get();
242    SetContentPattern(local_dict_value, expression2_, content_type0_, 1);
243  }
244
245  const PrefService::Preference* pref =
246      pref_service_->FindPreference(prefs::kContentSettingsPatternPairs);
247  scoped_ptr<Value> merged_value(
248      PrefModelAssociator::MergePreference(pref->name(),
249                                           *pref->GetValue(),
250                                           *null_value));
251  const DictionaryValue* local_dict_value =
252      pref_service_->GetDictionary(prefs::kContentSettingsPatternPairs);
253  EXPECT_TRUE(merged_value->Equals(local_dict_value));
254}
255
256TEST_F(DictionaryPreferenceMergeTest, ServerEmpty) {
257  scoped_ptr<Value> empty_value(new DictionaryValue);
258  {
259    DictionaryPrefUpdate update(pref_service_,
260                                prefs::kContentSettingsPatternPairs);
261    DictionaryValue* local_dict_value = update.Get();
262    SetContentPattern(local_dict_value, expression2_, content_type0_, 1);
263  }
264
265  const PrefService::Preference* pref =
266      pref_service_->FindPreference(prefs::kContentSettingsPatternPairs);
267  scoped_ptr<Value> merged_value(
268      PrefModelAssociator::MergePreference(pref->name(),
269                                           *pref->GetValue(),
270                                           *empty_value));
271  const DictionaryValue* local_dict_value =
272      pref_service_->GetDictionary(prefs::kContentSettingsPatternPairs);
273  EXPECT_TRUE(merged_value->Equals(local_dict_value));
274}
275
276TEST_F(DictionaryPreferenceMergeTest, MergeNoConflicts) {
277  {
278    DictionaryPrefUpdate update(pref_service_,
279                                prefs::kContentSettingsPatternPairs);
280    DictionaryValue* local_dict_value = update.Get();
281    SetContentPattern(local_dict_value, expression2_, content_type0_, 1);
282  }
283
284  scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
285     prefs::kContentSettingsPatternPairs,
286      *pref_service_->FindPreference(prefs::kContentSettingsPatternPairs)->
287          GetValue(),
288      server_patterns_));
289
290  DictionaryValue expected;
291  SetContentPattern(&expected, expression0_, content_type0_, 1);
292  SetContentPattern(&expected, expression0_, content_type1_, 2);
293  SetContentPattern(&expected, expression1_, content_type0_, 1);
294  SetContentPattern(&expected, expression2_, content_type0_, 1);
295  EXPECT_TRUE(merged_value->Equals(&expected));
296}
297
298TEST_F(DictionaryPreferenceMergeTest, MergeConflicts) {
299  {
300    DictionaryPrefUpdate update(pref_service_,
301                                prefs::kContentSettingsPatternPairs);
302    DictionaryValue* local_dict_value = update.Get();
303    SetContentPattern(local_dict_value, expression0_, content_type0_, 2);
304    SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
305    SetContentPattern(local_dict_value, expression1_, content_type1_, 1);
306    SetContentPattern(local_dict_value, expression2_, content_type0_, 2);
307  }
308
309  scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
310      prefs::kContentSettingsPatternPairs,
311      *pref_service_->FindPreference(prefs::kContentSettingsPatternPairs)->
312          GetValue(),
313      server_patterns_));
314
315  DictionaryValue expected;
316  SetContentPattern(&expected, expression0_, content_type0_, 1);
317  SetContentPattern(&expected, expression0_, content_type1_, 2);
318  SetContentPattern(&expected, expression1_, content_type0_, 1);
319  SetContentPattern(&expected, expression1_, content_type1_, 1);
320  SetContentPattern(&expected, expression2_, content_type0_, 2);
321  EXPECT_TRUE(merged_value->Equals(&expected));
322}
323
324TEST_F(DictionaryPreferenceMergeTest, Equal) {
325  {
326    DictionaryPrefUpdate update(pref_service_,
327                                prefs::kContentSettingsPatternPairs);
328    DictionaryValue* local_dict_value = update.Get();
329    SetContentPattern(local_dict_value, expression0_, content_type0_, 1);
330    SetContentPattern(local_dict_value, expression0_, content_type1_, 2);
331    SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
332  }
333
334  scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
335      prefs::kContentSettingsPatternPairs,
336      *pref_service_->
337          FindPreference(prefs::kContentSettingsPatternPairs)->GetValue(),
338      server_patterns_));
339  EXPECT_TRUE(merged_value->Equals(&server_patterns_));
340}
341
342TEST_F(DictionaryPreferenceMergeTest, ConflictButServerWins) {
343  {
344    DictionaryPrefUpdate update(pref_service_,
345                                prefs::kContentSettingsPatternPairs);
346    DictionaryValue* local_dict_value = update.Get();
347    SetContentPattern(local_dict_value, expression0_, content_type0_, 2);
348    SetContentPattern(local_dict_value, expression0_, content_type1_, 2);
349    SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
350  }
351
352  scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
353      prefs::kContentSettingsPatternPairs,
354      *pref_service_->
355          FindPreference(prefs::kContentSettingsPatternPairs)->GetValue(),
356      server_patterns_));
357  EXPECT_TRUE(merged_value->Equals(&server_patterns_));
358}
359
360class IndividualPreferenceMergeTest : public AbstractPreferenceMergeTest {
361 protected:
362  IndividualPreferenceMergeTest() :
363      url0_("http://example.com/server0"),
364      url1_("http://example.com/server1"),
365      expression0_("expression0"),
366      expression1_("expression1"),
367      content_type0_("content_type0") {}
368
369  virtual void SetUp() {
370    AbstractPreferenceMergeTest::SetUp();
371    server_url_list_.Append(Value::CreateStringValue(url0_));
372    SetContentPattern(&server_patterns_, expression0_, content_type0_, 1);
373  }
374
375  bool MergeListPreference(const char* pref) {
376    {
377      ListPrefUpdate update(pref_service_, pref);
378      ListValue* local_list_value = update.Get();
379      local_list_value->Append(Value::CreateStringValue(url1_));
380    }
381
382    scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
383        pref,
384        *pref_service_->GetUserPrefValue(pref),
385        server_url_list_));
386
387    ListValue expected;
388    expected.Append(Value::CreateStringValue(url0_));
389    expected.Append(Value::CreateStringValue(url1_));
390    return merged_value->Equals(&expected);
391  }
392
393  bool MergeDictionaryPreference(const char* pref) {
394    {
395      DictionaryPrefUpdate update(pref_service_, pref);
396      DictionaryValue* local_dict_value = update.Get();
397      SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
398    }
399
400    scoped_ptr<Value> merged_value(PrefModelAssociator::MergePreference(
401        pref,
402        *pref_service_->GetUserPrefValue(pref),
403        server_patterns_));
404
405    DictionaryValue expected;
406    SetContentPattern(&expected, expression0_, content_type0_, 1);
407    SetContentPattern(&expected, expression1_, content_type0_, 1);
408    return merged_value->Equals(&expected);
409  }
410
411  std::string url0_;
412  std::string url1_;
413  std::string expression0_;
414  std::string expression1_;
415  std::string content_type0_;
416  ListValue server_url_list_;
417  DictionaryValue server_patterns_;
418};
419
420TEST_F(IndividualPreferenceMergeTest, URLsToRestoreOnStartup) {
421  EXPECT_TRUE(MergeListPreference(prefs::kURLsToRestoreOnStartup));
422}
423