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 "chrome/browser/prefs/tracked/segregated_pref_store.h"
6
7#include <set>
8#include <string>
9
10#include "base/bind.h"
11#include "base/callback.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/prefs/persistent_pref_store.h"
15#include "base/prefs/pref_store_observer_mock.h"
16#include "base/prefs/testing_pref_store.h"
17#include "base/values.h"
18#include "chrome/browser/prefs/tracked/segregated_pref_store.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21namespace {
22
23const char kSelectedPref[] = "selected_pref";
24const char kUnselectedPref[] = "unselected_pref";
25
26const char kValue1[] = "value1";
27const char kValue2[] = "value2";
28
29class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
30 public:
31  struct Data {
32    Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
33        : invoked(invoked_in), read_error(read_error_in) {}
34
35    bool invoked;
36    PersistentPrefStore::PrefReadError read_error;
37  };
38
39  explicit MockReadErrorDelegate(Data* data) : data_(data) {
40    DCHECK(data_);
41    EXPECT_FALSE(data_->invoked);
42  }
43
44  // PersistentPrefStore::ReadErrorDelegate implementation
45  virtual void OnError(PersistentPrefStore::PrefReadError read_error) OVERRIDE {
46    EXPECT_FALSE(data_->invoked);
47    data_->invoked = true;
48    data_->read_error = read_error;
49  }
50
51 private:
52  Data* data_;
53};
54
55}  // namespace
56
57class SegregatedPrefStoreTest : public testing::Test {
58 public:
59  SegregatedPrefStoreTest()
60      : read_error_delegate_data_(false,
61                                  PersistentPrefStore::PREF_READ_ERROR_NONE),
62        read_error_delegate_(
63            new MockReadErrorDelegate(&read_error_delegate_data_)) {}
64
65  virtual void SetUp() OVERRIDE {
66    selected_store_ = new TestingPrefStore;
67    default_store_ = new TestingPrefStore;
68
69    std::set<std::string> selected_pref_names;
70    selected_pref_names.insert(kSelectedPref);
71
72    segregated_store_ = new SegregatedPrefStore(
73        default_store_,
74        selected_store_,
75        selected_pref_names);
76
77    segregated_store_->AddObserver(&observer_);
78  }
79
80  virtual void TearDown() OVERRIDE {
81    segregated_store_->RemoveObserver(&observer_);
82  }
83
84 protected:
85  scoped_ptr<PersistentPrefStore::ReadErrorDelegate> GetReadErrorDelegate() {
86    EXPECT_TRUE(read_error_delegate_);
87    return read_error_delegate_
88        .PassAs<PersistentPrefStore::ReadErrorDelegate>();
89  }
90
91  PrefStoreObserverMock observer_;
92
93  scoped_refptr<TestingPrefStore> default_store_;
94  scoped_refptr<TestingPrefStore> selected_store_;
95  scoped_refptr<SegregatedPrefStore> segregated_store_;
96
97  MockReadErrorDelegate::Data read_error_delegate_data_;
98
99 private:
100  scoped_ptr<MockReadErrorDelegate> read_error_delegate_;
101};
102
103TEST_F(SegregatedPrefStoreTest, StoreValues) {
104  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
105            segregated_store_->ReadPrefs());
106
107  // Properly stores new values.
108  segregated_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
109  segregated_store_->SetValue(kUnselectedPref, new base::StringValue(kValue2));
110
111  ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
112  ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
113  ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
114  ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
115
116  ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
117  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
118
119  ASSERT_FALSE(selected_store_->committed());
120  ASSERT_FALSE(default_store_->committed());
121
122  segregated_store_->CommitPendingWrite();
123
124  ASSERT_TRUE(selected_store_->committed());
125  ASSERT_TRUE(default_store_->committed());
126}
127
128TEST_F(SegregatedPrefStoreTest, ReadValues) {
129  selected_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
130  default_store_->SetValue(kUnselectedPref,
131                               new base::StringValue(kValue2));
132
133  // Works properly with values that are already there.
134  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
135            segregated_store_->ReadPrefs());
136  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
137            segregated_store_->GetReadError());
138
139  ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
140  ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
141  ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
142  ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
143
144  ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
145  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
146}
147
148TEST_F(SegregatedPrefStoreTest, Observer) {
149  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
150            segregated_store_->ReadPrefs());
151  EXPECT_TRUE(observer_.initialized);
152  EXPECT_TRUE(observer_.initialization_success);
153  EXPECT_TRUE(observer_.changed_keys.empty());
154  segregated_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
155  observer_.VerifyAndResetChangedKey(kSelectedPref);
156  segregated_store_->SetValue(kUnselectedPref, new base::StringValue(kValue2));
157  observer_.VerifyAndResetChangedKey(kUnselectedPref);
158}
159
160TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
161  // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
162  // to PREF_READ_ERROR_NONE.
163  selected_store_->set_read_error(
164      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
165  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
166            segregated_store_->ReadPrefs());
167  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
168            segregated_store_->GetReadError());
169}
170
171TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
172  selected_store_->set_read_error(
173      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
174  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
175            segregated_store_->ReadPrefs());
176  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
177            segregated_store_->GetReadError());
178}
179
180TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) {
181  // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
182  // to PREF_READ_ERROR_NONE.
183  selected_store_->set_read_error(
184      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
185
186  default_store_->SetBlockAsyncRead(true);
187
188  EXPECT_FALSE(read_error_delegate_data_.invoked);
189
190  segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
191
192  EXPECT_FALSE(read_error_delegate_data_.invoked);
193
194  default_store_->SetBlockAsyncRead(false);
195
196  // ReadErrorDelegate is not invoked for ERROR_NONE.
197  EXPECT_FALSE(read_error_delegate_data_.invoked);
198  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
199            segregated_store_->GetReadError());
200  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
201            segregated_store_->GetReadError());
202}
203
204TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) {
205  default_store_->set_read_error(
206      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
207  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
208            segregated_store_->ReadPrefs());
209  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
210            segregated_store_->GetReadError());
211}
212
213TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
214  default_store_->set_read_error(
215      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
216  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
217            segregated_store_->ReadPrefs());
218  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
219            segregated_store_->GetReadError());
220}
221
222TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
223  default_store_->set_read_error(
224      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
225  selected_store_->set_read_error(
226      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
227  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
228            segregated_store_->ReadPrefs());
229  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
230            segregated_store_->GetReadError());
231}
232
233TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
234  default_store_->set_read_error(
235      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
236  selected_store_->set_read_error(
237      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
238
239  selected_store_->SetBlockAsyncRead(true);
240
241  EXPECT_FALSE(read_error_delegate_data_.invoked);
242
243  segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
244
245  EXPECT_FALSE(read_error_delegate_data_.invoked);
246
247  selected_store_->SetBlockAsyncRead(false);
248
249  EXPECT_TRUE(read_error_delegate_data_.invoked);
250  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
251            segregated_store_->GetReadError());
252  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
253            segregated_store_->GetReadError());
254}
255
256TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
257  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
258  segregated_store_->ReadPrefs();
259  EXPECT_TRUE(segregated_store_->IsInitializationComplete());
260}
261
262TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
263  selected_store_->SetBlockAsyncRead(true);
264  default_store_->SetBlockAsyncRead(true);
265  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
266  segregated_store_->ReadPrefsAsync(NULL);
267  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
268  selected_store_->SetBlockAsyncRead(false);
269  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
270  default_store_->SetBlockAsyncRead(false);
271  EXPECT_TRUE(segregated_store_->IsInitializationComplete());
272}
273