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.
5 #include "chrome/browser/prefs/pref_hash_filter.h"
13 #include "base/basictypes.h"
14 #include "base/bind.h"
15 #include "base/callback_forward.h"
16 #include "base/compiler_specific.h"
17 #include "base/logging.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/metrics/histogram_base.h"
21 #include "base/metrics/histogram_samples.h"
22 #include "base/metrics/statistics_recorder.h"
23 #include "base/prefs/testing_pref_store.h"
24 #include "base/values.h"
25 #include "chrome/browser/prefs/mock_validation_delegate.h"
26 #include "chrome/browser/prefs/pref_hash_store.h"
27 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
28 #include "chrome/browser/prefs/tracked/hash_store_contents.h"
29 #include "chrome/common/pref_names.h"
30 #include "testing/gtest/include/gtest/gtest.h"
34 const char kAtomicPref[] = "atomic_pref";
35 const char kAtomicPref2[] = "atomic_pref2";
36 const char kAtomicPref3[] = "pref3";
37 const char kAtomicPref4[] = "pref4";
38 const char kReportOnlyPref[] = "report_only";
39 const char kReportOnlySplitPref[] = "report_only_split_pref";
40 const char kSplitPref[] = "split_pref";
42 const PrefHashFilter::TrackedPreferenceMetadata kTestTrackedPrefs[] = {
44 0, kAtomicPref, PrefHashFilter::ENFORCE_ON_LOAD,
45 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
48 1, kReportOnlyPref, PrefHashFilter::NO_ENFORCEMENT,
49 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
52 2, kSplitPref, PrefHashFilter::ENFORCE_ON_LOAD,
53 PrefHashFilter::TRACKING_STRATEGY_SPLIT
56 3, kReportOnlySplitPref, PrefHashFilter::NO_ENFORCEMENT,
57 PrefHashFilter::TRACKING_STRATEGY_SPLIT
60 4, kAtomicPref2, PrefHashFilter::ENFORCE_ON_LOAD,
61 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
64 5, kAtomicPref3, PrefHashFilter::ENFORCE_ON_LOAD,
65 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
68 6, kAtomicPref4, PrefHashFilter::ENFORCE_ON_LOAD,
69 PrefHashFilter::TRACKING_STRATEGY_ATOMIC
75 // A PrefHashStore that allows simulation of CheckValue results and captures
76 // checked and stored values.
77 class MockPrefHashStore : public PrefHashStore {
79 typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy>
83 : stamp_super_mac_result_(false),
84 is_super_mac_valid_result_(false),
85 transactions_performed_(0),
86 transaction_active_(false) {}
88 virtual ~MockPrefHashStore() {
89 EXPECT_FALSE(transaction_active_);
92 // Set the result that will be returned when |path| is passed to
93 // |CheckValue/CheckSplitValue|.
94 void SetCheckResult(const std::string& path,
95 PrefHashStoreTransaction::ValueState result);
97 // Set the invalid_keys that will be returned when |path| is passed to
98 // |CheckSplitValue|. SetCheckResult should already have been called for
99 // |path| with |result == CHANGED| for this to make any sense.
100 void SetInvalidKeysResult(
101 const std::string& path,
102 const std::vector<std::string>& invalid_keys_result);
104 // Sets the value that will be returned from
105 // PrefHashStoreTransaction::StampSuperMAC().
106 void set_stamp_super_mac_result(bool result) {
107 stamp_super_mac_result_ = result;
110 // Sets the value that will be returned from
111 // PrefHashStoreTransaction::IsSuperMACValid().
112 void set_is_super_mac_valid_result(bool result) {
113 is_super_mac_valid_result_ = result;
116 // Returns the number of transactions that were performed.
117 size_t transactions_performed() { return transactions_performed_; }
119 // Returns the number of paths checked.
120 size_t checked_paths_count() const {
121 return checked_values_.size();
124 // Returns the number of paths stored.
125 size_t stored_paths_count() const {
126 return stored_values_.size();
129 // Returns the pointer value and strategy that was passed to
130 // |CheckHash/CheckSplitHash| for |path|. The returned pointer could since
131 // have been freed and is thus not safe to dereference.
132 ValuePtrStrategyPair checked_value(const std::string& path) const {
133 std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
134 checked_values_.find(path);
135 if (value != checked_values_.end())
136 return value->second;
137 return std::make_pair(
138 reinterpret_cast<void*>(0xBAD),
139 static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
142 // Returns the pointer value that was passed to |StoreHash/StoreSplitHash| for
143 // |path|. The returned pointer could since have been freed and is thus not
144 // safe to dereference.
145 ValuePtrStrategyPair stored_value(const std::string& path) const {
146 std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
147 stored_values_.find(path);
148 if (value != stored_values_.end())
149 return value->second;
150 return std::make_pair(
151 reinterpret_cast<void*>(0xBAD),
152 static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
155 // PrefHashStore implementation.
156 virtual scoped_ptr<PrefHashStoreTransaction> BeginTransaction(
157 scoped_ptr<HashStoreContents> storage) OVERRIDE;
160 // A MockPrefHashStoreTransaction is handed to the caller on
161 // MockPrefHashStore::BeginTransaction(). It then stores state in its
162 // underlying MockPrefHashStore about calls it receives from that same caller
163 // which can later be verified in tests.
164 class MockPrefHashStoreTransaction : public PrefHashStoreTransaction {
166 explicit MockPrefHashStoreTransaction(MockPrefHashStore* outer)
169 virtual ~MockPrefHashStoreTransaction() {
170 outer_->transaction_active_ = false;
171 ++outer_->transactions_performed_;
174 // PrefHashStoreTransaction implementation.
175 virtual PrefHashStoreTransaction::ValueState CheckValue(
176 const std::string& path, const base::Value* value) const OVERRIDE;
177 virtual void StoreHash(const std::string& path,
178 const base::Value* new_value) OVERRIDE;
179 virtual PrefHashStoreTransaction::ValueState CheckSplitValue(
180 const std::string& path,
181 const base::DictionaryValue* initial_split_value,
182 std::vector<std::string>* invalid_keys) const OVERRIDE;
183 virtual void StoreSplitHash(
184 const std::string& path,
185 const base::DictionaryValue* split_value) OVERRIDE;
186 virtual bool HasHash(const std::string& path) const OVERRIDE;
187 virtual void ImportHash(const std::string& path,
188 const base::Value* hash) OVERRIDE;
189 virtual void ClearHash(const std::string& path) OVERRIDE;
190 virtual bool IsSuperMACValid() const OVERRIDE;
191 virtual bool StampSuperMac() OVERRIDE;
194 MockPrefHashStore* outer_;
196 DISALLOW_COPY_AND_ASSIGN(MockPrefHashStoreTransaction);
199 // Records a call to this mock's CheckValue/CheckSplitValue methods.
200 PrefHashStoreTransaction::ValueState RecordCheckValue(
201 const std::string& path,
202 const base::Value* value,
203 PrefHashFilter::PrefTrackingStrategy strategy);
205 // Records a call to this mock's StoreHash/StoreSplitHash methods.
206 void RecordStoreHash(const std::string& path,
207 const base::Value* new_value,
208 PrefHashFilter::PrefTrackingStrategy strategy);
210 std::map<std::string, PrefHashStoreTransaction::ValueState> check_results_;
211 std::map<std::string, std::vector<std::string> > invalid_keys_results_;
213 bool stamp_super_mac_result_;
214 bool is_super_mac_valid_result_;
216 std::map<std::string, ValuePtrStrategyPair> checked_values_;
217 std::map<std::string, ValuePtrStrategyPair> stored_values_;
219 // Number of transactions that are expected to be performed in the scope of
220 // this test (defaults to 1).
221 size_t transactions_expected_;
223 // Number of transactions that were performed via this MockPrefHashStore.
224 // Verified to match |transactions_expected_| when this MockPrefHashStore is
226 size_t transactions_performed_;
228 // Whether a transaction is currently active (only one transaction should be
229 // active at a time).
230 bool transaction_active_;
232 DISALLOW_COPY_AND_ASSIGN(MockPrefHashStore);
235 void MockPrefHashStore::SetCheckResult(
236 const std::string& path, PrefHashStoreTransaction::ValueState result) {
237 check_results_.insert(std::make_pair(path, result));
240 void MockPrefHashStore::SetInvalidKeysResult(
241 const std::string& path,
242 const std::vector<std::string>& invalid_keys_result) {
243 // Ensure |check_results_| has a CHANGED entry for |path|.
244 std::map<std::string,
245 PrefHashStoreTransaction::ValueState>::const_iterator result =
246 check_results_.find(path);
247 ASSERT_TRUE(result != check_results_.end());
248 ASSERT_EQ(PrefHashStoreTransaction::CHANGED, result->second);
250 invalid_keys_results_.insert(std::make_pair(path, invalid_keys_result));
253 scoped_ptr<PrefHashStoreTransaction> MockPrefHashStore::BeginTransaction(
254 scoped_ptr<HashStoreContents> storage) {
255 EXPECT_FALSE(transaction_active_);
256 return scoped_ptr<PrefHashStoreTransaction>(
257 new MockPrefHashStoreTransaction(this));
260 PrefHashStoreTransaction::ValueState MockPrefHashStore::RecordCheckValue(
261 const std::string& path,
262 const base::Value* value,
263 PrefHashFilter::PrefTrackingStrategy strategy) {
264 // Record that |path| was checked and validate that it wasn't previously
266 EXPECT_TRUE(checked_values_.insert(
267 std::make_pair(path, std::make_pair(value, strategy))).second);
268 std::map<std::string,
269 PrefHashStoreTransaction::ValueState>::const_iterator result =
270 check_results_.find(path);
271 if (result != check_results_.end())
272 return result->second;
273 return PrefHashStoreTransaction::UNCHANGED;
276 void MockPrefHashStore::RecordStoreHash(
277 const std::string& path,
278 const base::Value* new_value,
279 PrefHashFilter::PrefTrackingStrategy strategy) {
280 EXPECT_TRUE(stored_values_.insert(
281 std::make_pair(path, std::make_pair(new_value, strategy))).second);
284 PrefHashStoreTransaction::ValueState
285 MockPrefHashStore::MockPrefHashStoreTransaction::CheckValue(
286 const std::string& path, const base::Value* value) const {
287 return outer_->RecordCheckValue(path, value,
288 PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
291 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreHash(
292 const std::string& path,
293 const base::Value* new_value) {
294 outer_->RecordStoreHash(path, new_value,
295 PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
298 PrefHashStoreTransaction::ValueState
299 MockPrefHashStore::MockPrefHashStoreTransaction::CheckSplitValue(
300 const std::string& path,
301 const base::DictionaryValue* initial_split_value,
302 std::vector<std::string>* invalid_keys) const {
303 EXPECT_TRUE(invalid_keys && invalid_keys->empty());
305 std::map<std::string, std::vector<std::string> >::const_iterator
306 invalid_keys_result = outer_->invalid_keys_results_.find(path);
307 if (invalid_keys_result != outer_->invalid_keys_results_.end()) {
308 invalid_keys->insert(invalid_keys->begin(),
309 invalid_keys_result->second.begin(),
310 invalid_keys_result->second.end());
313 return outer_->RecordCheckValue(path, initial_split_value,
314 PrefHashFilter::TRACKING_STRATEGY_SPLIT);
317 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreSplitHash(
318 const std::string& path,
319 const base::DictionaryValue* new_value) {
320 outer_->RecordStoreHash(path, new_value,
321 PrefHashFilter::TRACKING_STRATEGY_SPLIT);
324 bool MockPrefHashStore::MockPrefHashStoreTransaction::HasHash(
325 const std::string& path) const {
326 ADD_FAILURE() << "Unexpected call.";
330 void MockPrefHashStore::MockPrefHashStoreTransaction::ImportHash(
331 const std::string& path,
332 const base::Value* hash) {
333 ADD_FAILURE() << "Unexpected call.";
336 void MockPrefHashStore::MockPrefHashStoreTransaction::ClearHash(
337 const std::string& path) {
338 // Allow this to be called by PrefHashFilter's deprecated tracked prefs
342 bool MockPrefHashStore::MockPrefHashStoreTransaction::IsSuperMACValid() const {
343 return outer_->is_super_mac_valid_result_;
346 bool MockPrefHashStore::MockPrefHashStoreTransaction::StampSuperMac() {
347 return outer_->stamp_super_mac_result_;
350 std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration(
351 PrefHashFilter::EnforcementLevel max_enforcement_level) {
352 std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration(
353 kTestTrackedPrefs, kTestTrackedPrefs + arraysize(kTestTrackedPrefs));
354 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
355 configuration.begin();
356 it != configuration.end();
358 if (it->enforcement_level > max_enforcement_level)
359 it->enforcement_level = max_enforcement_level;
361 return configuration;
364 class PrefHashFilterTest
365 : public testing::TestWithParam<PrefHashFilter::EnforcementLevel> {
367 PrefHashFilterTest() : mock_pref_hash_store_(NULL),
368 pref_store_contents_(new base::DictionaryValue),
369 last_filter_on_load_modified_prefs_(false),
370 reset_recorded_(false) {}
372 virtual void SetUp() OVERRIDE {
373 base::StatisticsRecorder::Initialize();
378 // Reset the PrefHashFilter instance.
380 // Construct a PrefHashFilter and MockPrefHashStore for the test.
381 InitializePrefHashFilter(GetConfiguration(GetParam()));
384 // Initializes |pref_hash_filter_| with a PrefHashFilter that uses a
385 // MockPrefHashStore. The raw pointer to the MockPrefHashStore (owned by the
386 // PrefHashFilter) is stored in |mock_pref_hash_store_|.
387 void InitializePrefHashFilter(const std::vector<
388 PrefHashFilter::TrackedPreferenceMetadata>& configuration) {
389 scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
390 new MockPrefHashStore);
391 mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
392 pref_hash_filter_.reset(new PrefHashFilter(
393 temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
395 base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)),
396 &mock_validation_delegate_,
397 arraysize(kTestTrackedPrefs),
401 // Verifies whether a reset was reported by the PrefHashFiler. Also verifies
402 // that kPreferenceResetTime was set (or not) accordingly.
403 void VerifyRecordedReset(bool reset_expected) {
404 EXPECT_EQ(reset_expected, reset_recorded_);
405 EXPECT_EQ(reset_expected,
406 pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL));
409 // Calls FilterOnLoad() on |pref_hash_Filter_|. |pref_store_contents_| is
410 // handed off, but should be given back to us synchronously through
411 // GetPrefsBack() as there is no FilterOnLoadInterceptor installed on
412 // |pref_hash_filter_|.
413 void DoFilterOnLoad(bool expect_prefs_modifications) {
414 pref_hash_filter_->FilterOnLoad(
415 base::Bind(&PrefHashFilterTest::GetPrefsBack, base::Unretained(this),
416 expect_prefs_modifications),
417 pref_store_contents_.Pass());
420 MockPrefHashStore* mock_pref_hash_store_;
421 scoped_ptr<base::DictionaryValue> pref_store_contents_;
422 bool last_filter_on_load_modified_prefs_;
423 MockValidationDelegate mock_validation_delegate_;
424 scoped_ptr<PrefHashFilter> pref_hash_filter_;
427 // Stores |prefs| back in |pref_store_contents| and ensure
428 // |expected_schedule_write| matches the reported |schedule_write|.
429 void GetPrefsBack(bool expected_schedule_write,
430 scoped_ptr<base::DictionaryValue> prefs,
431 bool schedule_write) {
432 pref_store_contents_ = prefs.Pass();
433 EXPECT_TRUE(pref_store_contents_);
434 EXPECT_EQ(expected_schedule_write, schedule_write);
438 // As-is |reset_recorded_| is only designed to remember a single reset, make
439 // sure none was previously recorded.
440 EXPECT_FALSE(reset_recorded_);
441 reset_recorded_ = true;
444 bool reset_recorded_;
446 DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
449 TEST_P(PrefHashFilterTest, EmptyAndUnchanged) {
450 DoFilterOnLoad(false);
451 // All paths checked.
452 ASSERT_EQ(arraysize(kTestTrackedPrefs),
453 mock_pref_hash_store_->checked_paths_count());
454 // No paths stored, since they all return |UNCHANGED|.
455 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
456 // Since there was nothing in |pref_store_contents_| the checked value should
457 // have been NULL for all tracked preferences.
458 for (size_t i = 0; i < arraysize(kTestTrackedPrefs); ++i) {
459 ASSERT_EQ(NULL, mock_pref_hash_store_->checked_value(
460 kTestTrackedPrefs[i].name).first);
462 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
463 VerifyRecordedReset(false);
465 // Delegate saw all paths, and all unchanged.
466 ASSERT_EQ(arraysize(kTestTrackedPrefs),
467 mock_validation_delegate_.recorded_validations_count());
468 ASSERT_EQ(arraysize(kTestTrackedPrefs),
469 mock_validation_delegate_.CountValidationsOfState(
470 PrefHashStoreTransaction::UNCHANGED));
473 TEST_P(PrefHashFilterTest, StampSuperMACAltersStore) {
474 mock_pref_hash_store_->set_stamp_super_mac_result(true);
475 DoFilterOnLoad(true);
476 // No paths stored, since they all return |UNCHANGED|. The StampSuperMAC
477 // result is the only reason the prefs were considered altered.
478 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
481 TEST_P(PrefHashFilterTest, FilterTrackedPrefUpdate) {
482 base::DictionaryValue root_dict;
483 // Ownership of |string_value| is transfered to |root_dict|.
484 base::Value* string_value = new base::StringValue("string value");
485 root_dict.Set(kAtomicPref, string_value);
487 // No path should be stored on FilterUpdate.
488 pref_hash_filter_->FilterUpdate(kAtomicPref);
489 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
491 // One path should be stored on FilterSerializeData.
492 pref_hash_filter_->FilterSerializeData(&root_dict);
493 ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
494 MockPrefHashStore::ValuePtrStrategyPair stored_value =
495 mock_pref_hash_store_->stored_value(kAtomicPref);
496 ASSERT_EQ(string_value, stored_value.first);
497 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
499 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
500 VerifyRecordedReset(false);
503 TEST_P(PrefHashFilterTest, ReportSuperMacValidity) {
504 // Do this once just to force the histogram to be defined.
505 DoFilterOnLoad(false);
507 base::HistogramBase* histogram = base::StatisticsRecorder::FindHistogram(
508 "Settings.HashesDictionaryTrusted");
509 ASSERT_TRUE(histogram);
511 base::HistogramBase::Count initial_untrusted =
512 histogram->SnapshotSamples()->GetCount(0);
513 base::HistogramBase::Count initial_trusted =
514 histogram->SnapshotSamples()->GetCount(1);
518 // Run with an invalid super MAC.
519 mock_pref_hash_store_->set_is_super_mac_valid_result(false);
521 DoFilterOnLoad(false);
523 // Verify that the invalidity was reported.
524 ASSERT_EQ(initial_untrusted + 1, histogram->SnapshotSamples()->GetCount(0));
525 ASSERT_EQ(initial_trusted, histogram->SnapshotSamples()->GetCount(1));
529 // Run with a valid super MAC.
530 mock_pref_hash_store_->set_is_super_mac_valid_result(true);
532 DoFilterOnLoad(false);
534 // Verify that the validity was reported.
535 ASSERT_EQ(initial_untrusted + 1, histogram->SnapshotSamples()->GetCount(0));
536 ASSERT_EQ(initial_trusted + 1, histogram->SnapshotSamples()->GetCount(1));
539 TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
540 base::DictionaryValue root_dict;
541 // Ownership of |dict_value| is transfered to |root_dict|.
542 base::DictionaryValue* dict_value = new base::DictionaryValue;
543 dict_value->SetString("a", "foo");
544 dict_value->SetInteger("b", 1234);
545 root_dict.Set(kSplitPref, dict_value);
547 // No path should be stored on FilterUpdate.
548 pref_hash_filter_->FilterUpdate(kSplitPref);
549 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
551 // One path should be stored on FilterSerializeData.
552 pref_hash_filter_->FilterSerializeData(&root_dict);
553 ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
554 MockPrefHashStore::ValuePtrStrategyPair stored_value =
555 mock_pref_hash_store_->stored_value(kSplitPref);
556 ASSERT_EQ(dict_value, stored_value.first);
557 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
559 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
560 VerifyRecordedReset(false);
563 TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
564 base::DictionaryValue root_dict;
565 root_dict.Set("untracked", new base::StringValue("some value"));
566 pref_hash_filter_->FilterUpdate("untracked");
568 // No paths should be stored on FilterUpdate.
569 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
571 // Nor on FilterSerializeData.
572 pref_hash_filter_->FilterSerializeData(&root_dict);
573 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
575 // No transaction should even be started on FilterSerializeData() if there are
576 // no updates to perform.
577 ASSERT_EQ(0u, mock_pref_hash_store_->transactions_performed());
580 TEST_P(PrefHashFilterTest, MultiplePrefsFilterSerializeData) {
581 base::DictionaryValue root_dict;
582 // Ownership of the following values is transfered to |root_dict|.
583 base::Value* int_value1 = new base::FundamentalValue(1);
584 base::Value* int_value2 = new base::FundamentalValue(2);
585 base::Value* int_value3 = new base::FundamentalValue(3);
586 base::Value* int_value4 = new base::FundamentalValue(4);
587 base::DictionaryValue* dict_value = new base::DictionaryValue;
588 dict_value->Set("a", new base::FundamentalValue(true));
589 root_dict.Set(kAtomicPref, int_value1);
590 root_dict.Set(kAtomicPref2, int_value2);
591 root_dict.Set(kAtomicPref3, int_value3);
592 root_dict.Set("untracked", int_value4);
593 root_dict.Set(kSplitPref, dict_value);
595 // Only update kAtomicPref, kAtomicPref3, and kSplitPref.
596 pref_hash_filter_->FilterUpdate(kAtomicPref);
597 pref_hash_filter_->FilterUpdate(kAtomicPref3);
598 pref_hash_filter_->FilterUpdate(kSplitPref);
599 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
601 // Update kAtomicPref3 again, nothing should be stored still.
602 base::Value* int_value5 = new base::FundamentalValue(5);
603 root_dict.Set(kAtomicPref3, int_value5);
604 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
606 // On FilterSerializeData, only kAtomicPref, kAtomicPref3, and kSplitPref
607 // should get a new hash.
608 pref_hash_filter_->FilterSerializeData(&root_dict);
609 ASSERT_EQ(3u, mock_pref_hash_store_->stored_paths_count());
610 MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic1 =
611 mock_pref_hash_store_->stored_value(kAtomicPref);
612 ASSERT_EQ(int_value1, stored_value_atomic1.first);
613 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
614 stored_value_atomic1.second);
615 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
617 MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic3 =
618 mock_pref_hash_store_->stored_value(kAtomicPref3);
619 ASSERT_EQ(int_value5, stored_value_atomic3.first);
620 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
621 stored_value_atomic3.second);
623 MockPrefHashStore::ValuePtrStrategyPair stored_value_split =
624 mock_pref_hash_store_->stored_value(kSplitPref);
625 ASSERT_EQ(dict_value, stored_value_split.first);
626 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value_split.second);
629 TEST_P(PrefHashFilterTest, EmptyAndUnknown) {
630 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
631 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
632 // NULL values are always trusted by the PrefHashStore.
633 mock_pref_hash_store_->SetCheckResult(
634 kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
635 mock_pref_hash_store_->SetCheckResult(
636 kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
637 DoFilterOnLoad(false);
638 ASSERT_EQ(arraysize(kTestTrackedPrefs),
639 mock_pref_hash_store_->checked_paths_count());
640 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
641 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
643 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
644 mock_pref_hash_store_->stored_value(kAtomicPref);
645 ASSERT_EQ(NULL, stored_atomic_value.first);
646 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
647 stored_atomic_value.second);
649 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
650 mock_pref_hash_store_->stored_value(kSplitPref);
651 ASSERT_EQ(NULL, stored_split_value.first);
652 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
653 stored_split_value.second);
655 // Delegate saw all prefs, two of which had the expected value_state.
656 ASSERT_EQ(arraysize(kTestTrackedPrefs),
657 mock_validation_delegate_.recorded_validations_count());
659 mock_validation_delegate_.CountValidationsOfState(
660 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
661 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
662 mock_validation_delegate_.CountValidationsOfState(
663 PrefHashStoreTransaction::UNCHANGED));
665 const MockValidationDelegate::ValidationEvent* validated_split_pref =
666 mock_validation_delegate_.GetEventForPath(kSplitPref);
667 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
668 validated_split_pref->strategy);
669 EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET,
670 validated_split_pref->reset_action);
671 const MockValidationDelegate::ValidationEvent* validated_atomic_pref =
672 mock_validation_delegate_.GetEventForPath(kAtomicPref);
673 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
674 validated_atomic_pref->strategy);
675 EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET,
676 validated_atomic_pref->reset_action);
679 TEST_P(PrefHashFilterTest, InitialValueUnknown) {
680 // Ownership of these values is transfered to |pref_store_contents_|.
681 base::StringValue* string_value = new base::StringValue("string value");
682 pref_store_contents_->Set(kAtomicPref, string_value);
684 base::DictionaryValue* dict_value = new base::DictionaryValue;
685 dict_value->SetString("a", "foo");
686 dict_value->SetInteger("b", 1234);
687 pref_store_contents_->Set(kSplitPref, dict_value);
689 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
690 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
692 mock_pref_hash_store_->SetCheckResult(
693 kAtomicPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
694 mock_pref_hash_store_->SetCheckResult(
695 kSplitPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
696 // If we are enforcing, expect this to report changes.
697 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
698 ASSERT_EQ(arraysize(kTestTrackedPrefs),
699 mock_pref_hash_store_->checked_paths_count());
700 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
701 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
703 // Delegate saw all prefs, two of which had the expected value_state.
704 ASSERT_EQ(arraysize(kTestTrackedPrefs),
705 mock_validation_delegate_.recorded_validations_count());
707 mock_validation_delegate_.CountValidationsOfState(
708 PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE));
709 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
710 mock_validation_delegate_.CountValidationsOfState(
711 PrefHashStoreTransaction::UNCHANGED));
713 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
714 mock_pref_hash_store_->stored_value(kAtomicPref);
715 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
716 mock_pref_hash_store_->stored_value(kSplitPref);
717 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
718 stored_atomic_value.second);
719 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
720 stored_split_value.second);
721 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
722 // Ensure the prefs were cleared and the hashes for NULL were restored if
723 // the current enforcement level denies seeding.
724 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
725 ASSERT_EQ(NULL, stored_atomic_value.first);
727 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
728 ASSERT_EQ(NULL, stored_split_value.first);
730 VerifyRecordedReset(true);
732 // Otherwise the values should have remained intact and the hashes should
733 // have been updated to match them.
734 const base::Value* atomic_value_in_store;
735 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
736 ASSERT_EQ(string_value, atomic_value_in_store);
737 ASSERT_EQ(string_value, stored_atomic_value.first);
739 const base::Value* split_value_in_store;
740 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
741 ASSERT_EQ(dict_value, split_value_in_store);
742 ASSERT_EQ(dict_value, stored_split_value.first);
744 VerifyRecordedReset(false);
748 TEST_P(PrefHashFilterTest, InitialValueTrustedUnknown) {
749 // Ownership of this value is transfered to |pref_store_contents_|.
750 base::Value* string_value = new base::StringValue("test");
751 pref_store_contents_->Set(kAtomicPref, string_value);
753 base::DictionaryValue* dict_value = new base::DictionaryValue;
754 dict_value->SetString("a", "foo");
755 dict_value->SetInteger("b", 1234);
756 pref_store_contents_->Set(kSplitPref, dict_value);
758 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
759 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
761 mock_pref_hash_store_->SetCheckResult(
762 kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
763 mock_pref_hash_store_->SetCheckResult(
764 kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
765 DoFilterOnLoad(false);
766 ASSERT_EQ(arraysize(kTestTrackedPrefs),
767 mock_pref_hash_store_->checked_paths_count());
768 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
769 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
771 // Delegate saw all prefs, two of which had the expected value_state.
772 ASSERT_EQ(arraysize(kTestTrackedPrefs),
773 mock_validation_delegate_.recorded_validations_count());
775 mock_validation_delegate_.CountValidationsOfState(
776 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
777 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
778 mock_validation_delegate_.CountValidationsOfState(
779 PrefHashStoreTransaction::UNCHANGED));
781 // Seeding is always allowed for trusted unknown values.
782 const base::Value* atomic_value_in_store;
783 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
784 ASSERT_EQ(string_value, atomic_value_in_store);
785 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
786 mock_pref_hash_store_->stored_value(kAtomicPref);
787 ASSERT_EQ(string_value, stored_atomic_value.first);
788 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
789 stored_atomic_value.second);
791 const base::Value* split_value_in_store;
792 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
793 ASSERT_EQ(dict_value, split_value_in_store);
794 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
795 mock_pref_hash_store_->stored_value(kSplitPref);
796 ASSERT_EQ(dict_value, stored_split_value.first);
797 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
798 stored_split_value.second);
801 TEST_P(PrefHashFilterTest, InitialValueChanged) {
802 // Ownership of this value is transfered to |pref_store_contents_|.
803 base::Value* int_value = new base::FundamentalValue(1234);
804 pref_store_contents_->Set(kAtomicPref, int_value);
806 base::DictionaryValue* dict_value = new base::DictionaryValue;
807 dict_value->SetString("a", "foo");
808 dict_value->SetInteger("b", 1234);
809 dict_value->SetInteger("c", 56);
810 dict_value->SetBoolean("d", false);
811 pref_store_contents_->Set(kSplitPref, dict_value);
813 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
814 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
816 mock_pref_hash_store_->SetCheckResult(kAtomicPref,
817 PrefHashStoreTransaction::CHANGED);
818 mock_pref_hash_store_->SetCheckResult(kSplitPref,
819 PrefHashStoreTransaction::CHANGED);
821 std::vector<std::string> mock_invalid_keys;
822 mock_invalid_keys.push_back("a");
823 mock_invalid_keys.push_back("c");
824 mock_pref_hash_store_->SetInvalidKeysResult(kSplitPref, mock_invalid_keys);
826 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
827 ASSERT_EQ(arraysize(kTestTrackedPrefs),
828 mock_pref_hash_store_->checked_paths_count());
829 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
830 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
832 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
833 mock_pref_hash_store_->stored_value(kAtomicPref);
834 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
835 mock_pref_hash_store_->stored_value(kSplitPref);
836 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
837 stored_atomic_value.second);
838 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
839 stored_split_value.second);
840 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
841 // Ensure the atomic pref was cleared and the hash for NULL was restored if
842 // the current enforcement level prevents changes.
843 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
844 ASSERT_EQ(NULL, stored_atomic_value.first);
846 // The split pref on the other hand should only have been stripped of its
848 const base::Value* split_value_in_store;
849 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
850 ASSERT_EQ(2U, dict_value->size());
851 ASSERT_FALSE(dict_value->HasKey("a"));
852 ASSERT_TRUE(dict_value->HasKey("b"));
853 ASSERT_FALSE(dict_value->HasKey("c"));
854 ASSERT_TRUE(dict_value->HasKey("d"));
855 ASSERT_EQ(dict_value, stored_split_value.first);
857 VerifyRecordedReset(true);
859 // Otherwise the value should have remained intact and the hash should have
860 // been updated to match it.
861 const base::Value* atomic_value_in_store;
862 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
863 ASSERT_EQ(int_value, atomic_value_in_store);
864 ASSERT_EQ(int_value, stored_atomic_value.first);
866 const base::Value* split_value_in_store;
867 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
868 ASSERT_EQ(dict_value, split_value_in_store);
869 ASSERT_EQ(4U, dict_value->size());
870 ASSERT_TRUE(dict_value->HasKey("a"));
871 ASSERT_TRUE(dict_value->HasKey("b"));
872 ASSERT_TRUE(dict_value->HasKey("c"));
873 ASSERT_TRUE(dict_value->HasKey("d"));
874 ASSERT_EQ(dict_value, stored_split_value.first);
876 VerifyRecordedReset(false);
880 TEST_P(PrefHashFilterTest, EmptyCleared) {
881 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
882 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
883 mock_pref_hash_store_->SetCheckResult(kAtomicPref,
884 PrefHashStoreTransaction::CLEARED);
885 mock_pref_hash_store_->SetCheckResult(kSplitPref,
886 PrefHashStoreTransaction::CLEARED);
887 DoFilterOnLoad(false);
888 ASSERT_EQ(arraysize(kTestTrackedPrefs),
889 mock_pref_hash_store_->checked_paths_count());
890 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
891 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
893 // Delegate saw all prefs, two of which had the expected value_state.
894 ASSERT_EQ(arraysize(kTestTrackedPrefs),
895 mock_validation_delegate_.recorded_validations_count());
897 mock_validation_delegate_.CountValidationsOfState(
898 PrefHashStoreTransaction::CLEARED));
899 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
900 mock_validation_delegate_.CountValidationsOfState(
901 PrefHashStoreTransaction::UNCHANGED));
903 // Regardless of the enforcement level, the only thing that should be done is
904 // to restore the hash for NULL. The value itself should still be NULL.
905 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
906 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
907 mock_pref_hash_store_->stored_value(kAtomicPref);
908 ASSERT_EQ(NULL, stored_atomic_value.first);
909 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
910 stored_atomic_value.second);
912 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
913 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
914 mock_pref_hash_store_->stored_value(kSplitPref);
915 ASSERT_EQ(NULL, stored_split_value.first);
916 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
917 stored_split_value.second);
920 TEST_P(PrefHashFilterTest, InitialValueUnchangedLegacyId) {
921 // Ownership of these values is transfered to |pref_store_contents_|.
922 base::StringValue* string_value = new base::StringValue("string value");
923 pref_store_contents_->Set(kAtomicPref, string_value);
925 base::DictionaryValue* dict_value = new base::DictionaryValue;
926 dict_value->SetString("a", "foo");
927 dict_value->SetInteger("b", 1234);
928 pref_store_contents_->Set(kSplitPref, dict_value);
930 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
931 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
933 mock_pref_hash_store_->SetCheckResult(
934 kAtomicPref, PrefHashStoreTransaction::SECURE_LEGACY);
935 mock_pref_hash_store_->SetCheckResult(
936 kSplitPref, PrefHashStoreTransaction::SECURE_LEGACY);
937 DoFilterOnLoad(false);
938 ASSERT_EQ(arraysize(kTestTrackedPrefs),
939 mock_pref_hash_store_->checked_paths_count());
940 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
942 // Delegate saw all prefs, two of which had the expected value_state.
943 ASSERT_EQ(arraysize(kTestTrackedPrefs),
944 mock_validation_delegate_.recorded_validations_count());
946 mock_validation_delegate_.CountValidationsOfState(
947 PrefHashStoreTransaction::SECURE_LEGACY));
948 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
949 mock_validation_delegate_.CountValidationsOfState(
950 PrefHashStoreTransaction::UNCHANGED));
952 // Ensure that both the atomic and split hashes were restored.
953 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
955 // In all cases, the values should have remained intact and the hashes should
956 // have been updated to match them.
958 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
959 mock_pref_hash_store_->stored_value(kAtomicPref);
960 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
961 stored_atomic_value.second);
962 const base::Value* atomic_value_in_store;
963 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
964 ASSERT_EQ(string_value, atomic_value_in_store);
965 ASSERT_EQ(string_value, stored_atomic_value.first);
967 MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
968 mock_pref_hash_store_->stored_value(kSplitPref);
969 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
970 stored_split_value.second);
971 const base::Value* split_value_in_store;
972 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
973 ASSERT_EQ(dict_value, split_value_in_store);
974 ASSERT_EQ(dict_value, stored_split_value.first);
976 VerifyRecordedReset(false);
979 TEST_P(PrefHashFilterTest, DontResetReportOnly) {
980 // Ownership of these values is transfered to |pref_store_contents_|.
981 base::Value* int_value1 = new base::FundamentalValue(1);
982 base::Value* int_value2 = new base::FundamentalValue(2);
983 base::Value* report_only_val = new base::FundamentalValue(3);
984 base::DictionaryValue* report_only_split_val = new base::DictionaryValue;
985 report_only_split_val->SetInteger("a", 1234);
986 pref_store_contents_->Set(kAtomicPref, int_value1);
987 pref_store_contents_->Set(kAtomicPref2, int_value2);
988 pref_store_contents_->Set(kReportOnlyPref, report_only_val);
989 pref_store_contents_->Set(kReportOnlySplitPref, report_only_split_val);
991 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
992 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, NULL));
993 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL));
994 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL));
996 mock_pref_hash_store_->SetCheckResult(kAtomicPref,
997 PrefHashStoreTransaction::CHANGED);
998 mock_pref_hash_store_->SetCheckResult(kAtomicPref2,
999 PrefHashStoreTransaction::CHANGED);
1000 mock_pref_hash_store_->SetCheckResult(kReportOnlyPref,
1001 PrefHashStoreTransaction::CHANGED);
1002 mock_pref_hash_store_->SetCheckResult(kReportOnlySplitPref,
1003 PrefHashStoreTransaction::CHANGED);
1005 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
1006 // All prefs should be checked and a new hash should be stored for each tested
1008 ASSERT_EQ(arraysize(kTestTrackedPrefs),
1009 mock_pref_hash_store_->checked_paths_count());
1010 ASSERT_EQ(4u, mock_pref_hash_store_->stored_paths_count());
1011 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
1013 // Delegate saw all prefs, four of which had the expected value_state.
1014 ASSERT_EQ(arraysize(kTestTrackedPrefs),
1015 mock_validation_delegate_.recorded_validations_count());
1017 mock_validation_delegate_.CountValidationsOfState(
1018 PrefHashStoreTransaction::CHANGED));
1019 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 4u,
1020 mock_validation_delegate_.CountValidationsOfState(
1021 PrefHashStoreTransaction::UNCHANGED));
1023 // No matter what the enforcement level is, the report only pref should never
1025 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL));
1026 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL));
1027 ASSERT_EQ(report_only_val,
1028 mock_pref_hash_store_->stored_value(kReportOnlyPref).first);
1029 ASSERT_EQ(report_only_split_val,
1030 mock_pref_hash_store_->stored_value(kReportOnlySplitPref).first);
1032 // All other prefs should have been reset if the enforcement level allows it.
1033 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
1034 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
1035 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref2, NULL));
1036 ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first);
1037 ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first);
1039 VerifyRecordedReset(true);
1041 const base::Value* value_in_store;
1042 const base::Value* value_in_store2;
1043 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &value_in_store));
1044 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, &value_in_store2));
1045 ASSERT_EQ(int_value1, value_in_store);
1046 ASSERT_EQ(int_value1,
1047 mock_pref_hash_store_->stored_value(kAtomicPref).first);
1048 ASSERT_EQ(int_value2, value_in_store2);
1049 ASSERT_EQ(int_value2,
1050 mock_pref_hash_store_->stored_value(kAtomicPref2).first);
1052 VerifyRecordedReset(false);
1056 INSTANTIATE_TEST_CASE_P(
1057 PrefHashFilterTestInstance, PrefHashFilterTest,
1058 testing::Values(PrefHashFilter::NO_ENFORCEMENT,
1059 PrefHashFilter::ENFORCE_ON_LOAD));