Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / pref_hash_filter_unittest.cc
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.
4
5 #include "chrome/browser/prefs/pref_hash_filter.h"
6
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
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"
31
32 namespace {
33
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";
41
42 const PrefHashFilter::TrackedPreferenceMetadata kTestTrackedPrefs[] = {
43   {
44     0, kAtomicPref, PrefHashFilter::ENFORCE_ON_LOAD,
45     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
46   },
47   {
48     1, kReportOnlyPref, PrefHashFilter::NO_ENFORCEMENT,
49     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
50   },
51   {
52     2, kSplitPref, PrefHashFilter::ENFORCE_ON_LOAD,
53     PrefHashFilter::TRACKING_STRATEGY_SPLIT
54   },
55   {
56     3, kReportOnlySplitPref, PrefHashFilter::NO_ENFORCEMENT,
57     PrefHashFilter::TRACKING_STRATEGY_SPLIT
58   },
59   {
60     4, kAtomicPref2, PrefHashFilter::ENFORCE_ON_LOAD,
61     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
62   },
63   {
64     5, kAtomicPref3, PrefHashFilter::ENFORCE_ON_LOAD,
65     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
66   },
67   {
68     6, kAtomicPref4, PrefHashFilter::ENFORCE_ON_LOAD,
69     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
70   },
71 };
72
73 }  // namespace
74
75 // A PrefHashStore that allows simulation of CheckValue results and captures
76 // checked and stored values.
77 class MockPrefHashStore : public PrefHashStore {
78  public:
79   typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy>
80       ValuePtrStrategyPair;
81
82   MockPrefHashStore()
83       : stamp_super_mac_result_(false),
84         is_super_mac_valid_result_(false),
85         transactions_performed_(0),
86         transaction_active_(false) {}
87
88   virtual ~MockPrefHashStore() {
89     EXPECT_FALSE(transaction_active_);
90   }
91
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);
96
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);
103
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;
108   }
109
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;
114   }
115
116   // Returns the number of transactions that were performed.
117   size_t transactions_performed() { return transactions_performed_; }
118
119   // Returns the number of paths checked.
120   size_t checked_paths_count() const {
121     return checked_values_.size();
122   }
123
124   // Returns the number of paths stored.
125   size_t stored_paths_count() const {
126     return stored_values_.size();
127   }
128
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));
140   }
141
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));
153   }
154
155   // PrefHashStore implementation.
156   virtual scoped_ptr<PrefHashStoreTransaction> BeginTransaction(
157       scoped_ptr<HashStoreContents> storage) OVERRIDE;
158
159  private:
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 {
165    public:
166     explicit MockPrefHashStoreTransaction(MockPrefHashStore* outer)
167         : outer_(outer) {}
168
169     virtual ~MockPrefHashStoreTransaction() {
170       outer_->transaction_active_ = false;
171       ++outer_->transactions_performed_;
172     }
173
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;
192
193    private:
194     MockPrefHashStore* outer_;
195
196     DISALLOW_COPY_AND_ASSIGN(MockPrefHashStoreTransaction);
197   };
198
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);
204
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);
209
210   std::map<std::string, PrefHashStoreTransaction::ValueState> check_results_;
211   std::map<std::string, std::vector<std::string> > invalid_keys_results_;
212
213   bool stamp_super_mac_result_;
214   bool is_super_mac_valid_result_;
215
216   std::map<std::string, ValuePtrStrategyPair> checked_values_;
217   std::map<std::string, ValuePtrStrategyPair> stored_values_;
218
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_;
222
223   // Number of transactions that were performed via this MockPrefHashStore.
224   // Verified to match |transactions_expected_| when this MockPrefHashStore is
225   // deleted.
226   size_t transactions_performed_;
227
228   // Whether a transaction is currently active (only one transaction should be
229   // active at a time).
230   bool transaction_active_;
231
232   DISALLOW_COPY_AND_ASSIGN(MockPrefHashStore);
233 };
234
235 void MockPrefHashStore::SetCheckResult(
236     const std::string& path, PrefHashStoreTransaction::ValueState result) {
237   check_results_.insert(std::make_pair(path, result));
238 }
239
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);
249
250   invalid_keys_results_.insert(std::make_pair(path, invalid_keys_result));
251 }
252
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));
258 }
259
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
265   // checked.
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;
274 }
275
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);
282 }
283
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);
289 }
290
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);
296 }
297
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());
304
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());
311   }
312
313   return outer_->RecordCheckValue(path, initial_split_value,
314                                   PrefHashFilter::TRACKING_STRATEGY_SPLIT);
315 }
316
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);
322 }
323
324 bool MockPrefHashStore::MockPrefHashStoreTransaction::HasHash(
325     const std::string& path) const  {
326   ADD_FAILURE() << "Unexpected call.";
327   return false;
328 }
329
330 void MockPrefHashStore::MockPrefHashStoreTransaction::ImportHash(
331     const std::string& path,
332     const base::Value* hash)  {
333   ADD_FAILURE() << "Unexpected call.";
334 }
335
336 void MockPrefHashStore::MockPrefHashStoreTransaction::ClearHash(
337     const std::string& path)  {
338   // Allow this to be called by PrefHashFilter's deprecated tracked prefs
339   // cleanup tasks.
340 }
341
342 bool MockPrefHashStore::MockPrefHashStoreTransaction::IsSuperMACValid() const {
343   return outer_->is_super_mac_valid_result_;
344 }
345
346 bool MockPrefHashStore::MockPrefHashStoreTransaction::StampSuperMac() {
347   return outer_->stamp_super_mac_result_;
348 }
349
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();
357        ++it) {
358     if (it->enforcement_level > max_enforcement_level)
359       it->enforcement_level = max_enforcement_level;
360   }
361   return configuration;
362 }
363
364 class PrefHashFilterTest
365     : public testing::TestWithParam<PrefHashFilter::EnforcementLevel> {
366  public:
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) {}
371
372   virtual void SetUp() OVERRIDE {
373     base::StatisticsRecorder::Initialize();
374     Reset();
375   }
376
377  protected:
378   // Reset the PrefHashFilter instance.
379   void Reset() {
380     // Construct a PrefHashFilter and MockPrefHashStore for the test.
381     InitializePrefHashFilter(GetConfiguration(GetParam()));
382   }
383
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>(),
394         configuration,
395         base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)),
396         &mock_validation_delegate_,
397         arraysize(kTestTrackedPrefs),
398         true));
399   }
400
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));
407   }
408
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());
418   }
419
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_;
425
426  private:
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);
435   }
436
437   void RecordReset() {
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;
442   }
443
444   bool reset_recorded_;
445
446   DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
447 };
448
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);
461   }
462   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
463   VerifyRecordedReset(false);
464
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));
471 }
472
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());
479 }
480
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);
486
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());
490
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);
498
499   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
500   VerifyRecordedReset(false);
501 }
502
503 TEST_P(PrefHashFilterTest, ReportSuperMacValidity) {
504   // Do this once just to force the histogram to be defined.
505   DoFilterOnLoad(false);
506
507   base::HistogramBase* histogram = base::StatisticsRecorder::FindHistogram(
508       "Settings.HashesDictionaryTrusted");
509   ASSERT_TRUE(histogram);
510
511   base::HistogramBase::Count initial_untrusted =
512       histogram->SnapshotSamples()->GetCount(0);
513   base::HistogramBase::Count initial_trusted =
514       histogram->SnapshotSamples()->GetCount(1);
515
516   Reset();
517
518   // Run with an invalid super MAC.
519   mock_pref_hash_store_->set_is_super_mac_valid_result(false);
520
521   DoFilterOnLoad(false);
522
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));
526
527   Reset();
528
529   // Run with a valid super MAC.
530   mock_pref_hash_store_->set_is_super_mac_valid_result(true);
531
532   DoFilterOnLoad(false);
533
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));
537 }
538
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);
546
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());
550
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);
558
559   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
560   VerifyRecordedReset(false);
561 }
562
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");
567
568   // No paths should be stored on FilterUpdate.
569   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
570
571   // Nor on FilterSerializeData.
572   pref_hash_filter_->FilterSerializeData(&root_dict);
573   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
574
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());
578 }
579
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);
594
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());
600
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());
605
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());
616
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);
622
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);
627 }
628
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());
642
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);
648
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);
654
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());
658   ASSERT_EQ(2u,
659             mock_validation_delegate_.CountValidationsOfState(
660                 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
661   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
662             mock_validation_delegate_.CountValidationsOfState(
663                 PrefHashStoreTransaction::UNCHANGED));
664
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);
677 }
678
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);
683
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);
688
689   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
690   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
691
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());
702
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());
706   ASSERT_EQ(2u,
707             mock_validation_delegate_.CountValidationsOfState(
708                 PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE));
709   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
710             mock_validation_delegate_.CountValidationsOfState(
711                 PrefHashStoreTransaction::UNCHANGED));
712
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);
726
727     ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
728     ASSERT_EQ(NULL, stored_split_value.first);
729
730     VerifyRecordedReset(true);
731   } else {
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);
738
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);
743
744     VerifyRecordedReset(false);
745   }
746 }
747
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);
752
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);
757
758   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
759   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
760
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());
770
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());
774   ASSERT_EQ(2u,
775             mock_validation_delegate_.CountValidationsOfState(
776                 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
777   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
778             mock_validation_delegate_.CountValidationsOfState(
779                 PrefHashStoreTransaction::UNCHANGED));
780
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);
790
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);
799 }
800
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);
805
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);
812
813   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
814   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
815
816   mock_pref_hash_store_->SetCheckResult(kAtomicPref,
817                                         PrefHashStoreTransaction::CHANGED);
818   mock_pref_hash_store_->SetCheckResult(kSplitPref,
819                                         PrefHashStoreTransaction::CHANGED);
820
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);
825
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());
831
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);
845
846     // The split pref on the other hand should only have been stripped of its
847     // invalid keys.
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);
856
857     VerifyRecordedReset(true);
858   } else {
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);
865
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);
875
876     VerifyRecordedReset(false);
877   }
878 }
879
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());
892
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());
896   ASSERT_EQ(2u,
897             mock_validation_delegate_.CountValidationsOfState(
898                 PrefHashStoreTransaction::CLEARED));
899   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
900             mock_validation_delegate_.CountValidationsOfState(
901                 PrefHashStoreTransaction::UNCHANGED));
902
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);
911
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);
918 }
919
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);
924
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);
929
930   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
931   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
932
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());
941
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());
945   ASSERT_EQ(2u,
946             mock_validation_delegate_.CountValidationsOfState(
947                 PrefHashStoreTransaction::SECURE_LEGACY));
948   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
949             mock_validation_delegate_.CountValidationsOfState(
950                 PrefHashStoreTransaction::UNCHANGED));
951
952   // Ensure that both the atomic and split hashes were restored.
953   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
954
955   // In all cases, the values should have remained intact and the hashes should
956   // have been updated to match them.
957
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);
966
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);
975
976   VerifyRecordedReset(false);
977 }
978
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);
990
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));
995
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);
1004
1005   DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
1006   // All prefs should be checked and a new hash should be stored for each tested
1007   // pref.
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());
1012
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());
1016   ASSERT_EQ(4u,
1017             mock_validation_delegate_.CountValidationsOfState(
1018                 PrefHashStoreTransaction::CHANGED));
1019   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 4u,
1020             mock_validation_delegate_.CountValidationsOfState(
1021                 PrefHashStoreTransaction::UNCHANGED));
1022
1023   // No matter what the enforcement level is, the report only pref should never
1024   // be reset.
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);
1031
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);
1038
1039     VerifyRecordedReset(true);
1040   } else {
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);
1051
1052     VerifyRecordedReset(false);
1053   }
1054 }
1055
1056 INSTANTIATE_TEST_CASE_P(
1057     PrefHashFilterTestInstance, PrefHashFilterTest,
1058     testing::Values(PrefHashFilter::NO_ENFORCEMENT,
1059                     PrefHashFilter::ENFORCE_ON_LOAD));