segregated_pref_store_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. #include "components/prefs/segregated_pref_store.h"
  5. #include <memory>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/run_loop.h"
  14. #include "base/synchronization/waitable_event.h"
  15. #include "base/test/task_environment.h"
  16. #include "base/values.h"
  17. #include "components/prefs/persistent_pref_store.h"
  18. #include "components/prefs/pref_store_observer_mock.h"
  19. #include "components/prefs/testing_pref_store.h"
  20. #include "testing/gtest/include/gtest/gtest.h"
  21. namespace {
  22. const char kSelectedPref[] = "selected_pref";
  23. const char kUnselectedPref[] = "unselected_pref";
  24. const char kSharedPref[] = "shared_pref";
  25. const char kValue1[] = "value1";
  26. const char kValue2[] = "value2";
  27. class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
  28. public:
  29. struct Data {
  30. Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
  31. : invoked(invoked_in), read_error(read_error_in) {}
  32. bool invoked;
  33. PersistentPrefStore::PrefReadError read_error;
  34. };
  35. explicit MockReadErrorDelegate(Data* data) : data_(data) {
  36. DCHECK(data_);
  37. EXPECT_FALSE(data_->invoked);
  38. }
  39. // PersistentPrefStore::ReadErrorDelegate implementation
  40. void OnError(PersistentPrefStore::PrefReadError read_error) override {
  41. EXPECT_FALSE(data_->invoked);
  42. data_->invoked = true;
  43. data_->read_error = read_error;
  44. }
  45. private:
  46. raw_ptr<Data> data_;
  47. };
  48. enum class CommitPendingWriteMode {
  49. // Basic mode.
  50. WITHOUT_CALLBACK,
  51. // With reply callback.
  52. WITH_CALLBACK,
  53. // With synchronous notify callback (synchronous after the write -- shouldn't
  54. // require pumping messages to observe).
  55. WITH_SYNCHRONOUS_CALLBACK,
  56. };
  57. class SegregatedPrefStoreTest
  58. : public testing::TestWithParam<CommitPendingWriteMode> {
  59. public:
  60. SegregatedPrefStoreTest()
  61. : read_error_delegate_data_(false,
  62. PersistentPrefStore::PREF_READ_ERROR_NONE),
  63. read_error_delegate_(
  64. new MockReadErrorDelegate(&read_error_delegate_data_)) {}
  65. void SetUp() override {
  66. selected_store_ = new TestingPrefStore;
  67. default_store_ = new TestingPrefStore;
  68. selected_pref_names_.insert(kSelectedPref);
  69. selected_pref_names_.insert(kSharedPref);
  70. segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_,
  71. selected_pref_names_);
  72. segregated_store_->AddObserver(&observer_);
  73. }
  74. void TearDown() override { segregated_store_->RemoveObserver(&observer_); }
  75. protected:
  76. std::unique_ptr<PersistentPrefStore::ReadErrorDelegate>
  77. GetReadErrorDelegate() {
  78. EXPECT_TRUE(read_error_delegate_);
  79. return std::move(read_error_delegate_);
  80. }
  81. base::test::TaskEnvironment task_environment_;
  82. PrefStoreObserverMock observer_;
  83. scoped_refptr<TestingPrefStore> default_store_;
  84. scoped_refptr<TestingPrefStore> selected_store_;
  85. scoped_refptr<SegregatedPrefStore> segregated_store_;
  86. std::set<std::string> selected_pref_names_;
  87. MockReadErrorDelegate::Data read_error_delegate_data_;
  88. private:
  89. std::unique_ptr<MockReadErrorDelegate> read_error_delegate_;
  90. };
  91. } // namespace
  92. TEST_P(SegregatedPrefStoreTest, StoreValues) {
  93. ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  94. segregated_store_->ReadPrefs());
  95. // Properly stores new values.
  96. segregated_store_->SetValue(kSelectedPref,
  97. std::make_unique<base::Value>(kValue1),
  98. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  99. segregated_store_->SetValue(kUnselectedPref,
  100. std::make_unique<base::Value>(kValue2),
  101. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  102. ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
  103. ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
  104. ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
  105. ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
  106. ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
  107. ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
  108. ASSERT_FALSE(selected_store_->committed());
  109. ASSERT_FALSE(default_store_->committed());
  110. switch (GetParam()) {
  111. case CommitPendingWriteMode::WITHOUT_CALLBACK: {
  112. segregated_store_->CommitPendingWrite();
  113. base::RunLoop().RunUntilIdle();
  114. break;
  115. }
  116. case CommitPendingWriteMode::WITH_CALLBACK: {
  117. base::RunLoop run_loop;
  118. segregated_store_->CommitPendingWrite(run_loop.QuitClosure());
  119. run_loop.Run();
  120. break;
  121. }
  122. case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: {
  123. base::WaitableEvent written;
  124. segregated_store_->CommitPendingWrite(
  125. base::OnceClosure(),
  126. base::BindOnce(&base::WaitableEvent::Signal, Unretained(&written)));
  127. written.Wait();
  128. break;
  129. }
  130. }
  131. ASSERT_TRUE(selected_store_->committed());
  132. ASSERT_TRUE(default_store_->committed());
  133. }
  134. TEST_F(SegregatedPrefStoreTest, ReadValues) {
  135. selected_store_->SetValue(kSelectedPref,
  136. std::make_unique<base::Value>(kValue1),
  137. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  138. default_store_->SetValue(kUnselectedPref,
  139. std::make_unique<base::Value>(kValue2),
  140. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  141. // Works properly with values that are already there.
  142. ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  143. segregated_store_->ReadPrefs());
  144. ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  145. segregated_store_->GetReadError());
  146. ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
  147. ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
  148. ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
  149. ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
  150. ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
  151. ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
  152. }
  153. TEST_F(SegregatedPrefStoreTest, RemoveValuesByPrefix) {
  154. const std::string subpref_name1 = kSelectedPref;
  155. const std::string subpref_name2 = std::string(kSelectedPref) + "b";
  156. const std::string other_name = kUnselectedPref;
  157. const std::string prefix = kSelectedPref;
  158. selected_store_->SetValue(subpref_name1,
  159. std::make_unique<base::Value>(kValue1),
  160. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  161. default_store_->SetValue(subpref_name2,
  162. std::make_unique<base::Value>(kValue2),
  163. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  164. default_store_->SetValue(other_name, std::make_unique<base::Value>(kValue2),
  165. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  166. ASSERT_TRUE(selected_store_->GetValue(subpref_name1, nullptr));
  167. ASSERT_TRUE(default_store_->GetValue(subpref_name2, nullptr));
  168. ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
  169. segregated_store_->RemoveValuesByPrefixSilently(kSelectedPref);
  170. ASSERT_FALSE(selected_store_->GetValue(subpref_name1, nullptr));
  171. ASSERT_FALSE(default_store_->GetValue(subpref_name2, nullptr));
  172. ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
  173. }
  174. TEST_F(SegregatedPrefStoreTest, Observer) {
  175. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  176. segregated_store_->ReadPrefs());
  177. EXPECT_TRUE(observer_.initialized);
  178. EXPECT_TRUE(observer_.initialization_success);
  179. EXPECT_TRUE(observer_.changed_keys.empty());
  180. segregated_store_->SetValue(kSelectedPref,
  181. std::make_unique<base::Value>(kValue1),
  182. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  183. observer_.VerifyAndResetChangedKey(kSelectedPref);
  184. segregated_store_->SetValue(kUnselectedPref,
  185. std::make_unique<base::Value>(kValue2),
  186. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  187. observer_.VerifyAndResetChangedKey(kUnselectedPref);
  188. }
  189. TEST_F(SegregatedPrefStoreTest,
  190. ObserverAfterConstructionAfterSubInitialization) {
  191. // Ensure that underlying PrefStores are initialized first.
  192. default_store_->ReadPrefs();
  193. selected_store_->ReadPrefs();
  194. EXPECT_TRUE(default_store_->IsInitializationComplete());
  195. EXPECT_TRUE(selected_store_->IsInitializationComplete());
  196. // Create a new SegregatedPrefStore based on the initialized PrefStores.
  197. segregated_store_->RemoveObserver(&observer_);
  198. segregated_store_ = base::MakeRefCounted<SegregatedPrefStore>(
  199. default_store_, selected_store_, selected_pref_names_);
  200. segregated_store_->AddObserver(&observer_);
  201. EXPECT_TRUE(segregated_store_->IsInitializationComplete());
  202. // The Observer should receive notifications from the SegregatedPrefStore.
  203. EXPECT_TRUE(observer_.changed_keys.empty());
  204. segregated_store_->SetValue(kSelectedPref,
  205. std::make_unique<base::Value>(kValue1),
  206. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  207. observer_.VerifyAndResetChangedKey(kSelectedPref);
  208. segregated_store_->SetValue(kUnselectedPref,
  209. std::make_unique<base::Value>(kValue2),
  210. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  211. observer_.VerifyAndResetChangedKey(kUnselectedPref);
  212. }
  213. TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
  214. // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
  215. // to PREF_READ_ERROR_NONE.
  216. selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
  217. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  218. segregated_store_->ReadPrefs());
  219. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  220. segregated_store_->GetReadError());
  221. }
  222. TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
  223. selected_store_->set_read_error(
  224. PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
  225. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
  226. segregated_store_->ReadPrefs());
  227. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
  228. segregated_store_->GetReadError());
  229. }
  230. TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) {
  231. // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
  232. // to PREF_READ_ERROR_NONE.
  233. selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
  234. default_store_->SetBlockAsyncRead(true);
  235. EXPECT_FALSE(read_error_delegate_data_.invoked);
  236. segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
  237. EXPECT_FALSE(read_error_delegate_data_.invoked);
  238. default_store_->SetBlockAsyncRead(false);
  239. // ReadErrorDelegate is not invoked for ERROR_NONE.
  240. EXPECT_FALSE(read_error_delegate_data_.invoked);
  241. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  242. segregated_store_->GetReadError());
  243. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
  244. segregated_store_->GetReadError());
  245. }
  246. TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) {
  247. default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
  248. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  249. segregated_store_->ReadPrefs());
  250. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  251. segregated_store_->GetReadError());
  252. }
  253. TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
  254. default_store_->set_read_error(
  255. PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
  256. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
  257. segregated_store_->ReadPrefs());
  258. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
  259. segregated_store_->GetReadError());
  260. }
  261. TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
  262. default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
  263. selected_store_->set_read_error(
  264. PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
  265. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  266. segregated_store_->ReadPrefs());
  267. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  268. segregated_store_->GetReadError());
  269. }
  270. TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
  271. default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
  272. selected_store_->set_read_error(
  273. PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
  274. selected_store_->SetBlockAsyncRead(true);
  275. EXPECT_FALSE(read_error_delegate_data_.invoked);
  276. segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
  277. EXPECT_FALSE(read_error_delegate_data_.invoked);
  278. selected_store_->SetBlockAsyncRead(false);
  279. EXPECT_TRUE(read_error_delegate_data_.invoked);
  280. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  281. segregated_store_->GetReadError());
  282. EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
  283. segregated_store_->GetReadError());
  284. }
  285. TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
  286. EXPECT_FALSE(segregated_store_->IsInitializationComplete());
  287. segregated_store_->ReadPrefs();
  288. EXPECT_TRUE(segregated_store_->IsInitializationComplete());
  289. }
  290. TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
  291. selected_store_->SetBlockAsyncRead(true);
  292. default_store_->SetBlockAsyncRead(true);
  293. EXPECT_FALSE(segregated_store_->IsInitializationComplete());
  294. segregated_store_->ReadPrefsAsync(NULL);
  295. EXPECT_FALSE(segregated_store_->IsInitializationComplete());
  296. selected_store_->SetBlockAsyncRead(false);
  297. EXPECT_FALSE(segregated_store_->IsInitializationComplete());
  298. default_store_->SetBlockAsyncRead(false);
  299. EXPECT_TRUE(segregated_store_->IsInitializationComplete());
  300. }
  301. TEST_F(SegregatedPrefStoreTest, GetValues) {
  302. // To check merge behavior, create selected and default stores so each has a
  303. // key the other doesn't have and they have one key in common.
  304. selected_store_->SetValue(kSelectedPref,
  305. std::make_unique<base::Value>(kValue1),
  306. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  307. default_store_->SetValue(kUnselectedPref,
  308. std::make_unique<base::Value>(kValue2),
  309. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  310. selected_store_->SetValue(kSharedPref, std::make_unique<base::Value>(kValue1),
  311. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  312. auto values = segregated_store_->GetValues();
  313. // Check that a selected preference is returned.
  314. const base::Value* value = values.Find(kSelectedPref);
  315. ASSERT_TRUE(value);
  316. EXPECT_EQ(base::Value(kValue1), *value);
  317. // Check that a a default preference is returned.
  318. value = values.Find(kUnselectedPref);
  319. ASSERT_TRUE(value);
  320. EXPECT_EQ(base::Value(kValue2), *value);
  321. // Check that the selected preference is preferred.
  322. value = values.Find(kSharedPref);
  323. ASSERT_TRUE(value);
  324. EXPECT_EQ(base::Value(kValue1), *value);
  325. }
  326. INSTANTIATE_TEST_SUITE_P(
  327. WithoutCallback,
  328. SegregatedPrefStoreTest,
  329. ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
  330. INSTANTIATE_TEST_SUITE_P(
  331. WithCallback,
  332. SegregatedPrefStoreTest,
  333. ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
  334. INSTANTIATE_TEST_SUITE_P(
  335. WithSynchronousCallback,
  336. SegregatedPrefStoreTest,
  337. ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK));