3b5e8218f1936d3d7892d8ec9e00e9d076fce572
[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/prefs/testing_pref_store.h"
21 #include "base/values.h"
22 #include "chrome/browser/prefs/mock_validation_delegate.h"
23 #include "chrome/browser/prefs/pref_hash_store.h"
24 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
25 #include "chrome/browser/prefs/tracked/hash_store_contents.h"
26 #include "chrome/common/pref_names.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace {
30
31 const char kAtomicPref[] = "atomic_pref";
32 const char kAtomicPref2[] = "atomic_pref2";
33 const char kAtomicPref3[] = "pref3";
34 const char kAtomicPref4[] = "pref4";
35 const char kReportOnlyPref[] = "report_only";
36 const char kReportOnlySplitPref[] = "report_only_split_pref";
37 const char kSplitPref[] = "split_pref";
38
39 const PrefHashFilter::TrackedPreferenceMetadata kTestTrackedPrefs[] = {
40   {
41     0, kAtomicPref, PrefHashFilter::ENFORCE_ON_LOAD,
42     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
43   },
44   {
45     1, kReportOnlyPref, PrefHashFilter::NO_ENFORCEMENT,
46     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
47   },
48   {
49     2, kSplitPref, PrefHashFilter::ENFORCE_ON_LOAD,
50     PrefHashFilter::TRACKING_STRATEGY_SPLIT
51   },
52   {
53     3, kReportOnlySplitPref, PrefHashFilter::NO_ENFORCEMENT,
54     PrefHashFilter::TRACKING_STRATEGY_SPLIT
55   },
56   {
57     4, kAtomicPref2, PrefHashFilter::ENFORCE_ON_LOAD,
58     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
59   },
60   {
61     5, kAtomicPref3, PrefHashFilter::ENFORCE_ON_LOAD,
62     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
63   },
64   {
65     6, kAtomicPref4, PrefHashFilter::ENFORCE_ON_LOAD,
66     PrefHashFilter::TRACKING_STRATEGY_ATOMIC
67   },
68 };
69
70 }  // namespace
71
72 // A PrefHashStore that allows simulation of CheckValue results and captures
73 // checked and stored values.
74 class MockPrefHashStore : public PrefHashStore {
75  public:
76   typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy>
77       ValuePtrStrategyPair;
78
79   MockPrefHashStore()
80       : transactions_performed_(0), transaction_active_(false) {}
81
82   virtual ~MockPrefHashStore() {
83     EXPECT_FALSE(transaction_active_);
84   }
85
86   // Set the result that will be returned when |path| is passed to
87   // |CheckValue/CheckSplitValue|.
88   void SetCheckResult(const std::string& path,
89                       PrefHashStoreTransaction::ValueState result);
90
91   // Set the invalid_keys that will be returned when |path| is passed to
92   // |CheckSplitValue|. SetCheckResult should already have been called for
93   // |path| with |result == CHANGED| for this to make any sense.
94   void SetInvalidKeysResult(
95       const std::string& path,
96       const std::vector<std::string>& invalid_keys_result);
97
98   // Returns the number of transactions that were performed.
99   size_t transactions_performed() { return transactions_performed_; }
100
101   // Returns the number of paths checked.
102   size_t checked_paths_count() const {
103     return checked_values_.size();
104   }
105
106   // Returns the number of paths stored.
107   size_t stored_paths_count() const {
108     return stored_values_.size();
109   }
110
111   // Returns the pointer value and strategy that was passed to
112   // |CheckHash/CheckSplitHash| for |path|. The returned pointer could since
113   // have been freed and is thus not safe to dereference.
114   ValuePtrStrategyPair checked_value(const std::string& path) const {
115     std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
116         checked_values_.find(path);
117     if (value != checked_values_.end())
118       return value->second;
119     return std::make_pair(
120                reinterpret_cast<void*>(0xBAD),
121                static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
122   }
123
124   // Returns the pointer value that was passed to |StoreHash/StoreSplitHash| for
125   // |path|. The returned pointer could since have been freed and is thus not
126   // safe to dereference.
127   ValuePtrStrategyPair stored_value(const std::string& path) const {
128     std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
129         stored_values_.find(path);
130     if (value != stored_values_.end())
131       return value->second;
132     return std::make_pair(
133                reinterpret_cast<void*>(0xBAD),
134                static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
135   }
136
137   // PrefHashStore implementation.
138   virtual scoped_ptr<PrefHashStoreTransaction> BeginTransaction(
139       scoped_ptr<HashStoreContents> storage) OVERRIDE;
140
141  private:
142   // A MockPrefHashStoreTransaction is handed to the caller on
143   // MockPrefHashStore::BeginTransaction(). It then stores state in its
144   // underlying MockPrefHashStore about calls it receives from that same caller
145   // which can later be verified in tests.
146   class MockPrefHashStoreTransaction : public PrefHashStoreTransaction {
147    public:
148     explicit MockPrefHashStoreTransaction(MockPrefHashStore* outer)
149         : outer_(outer) {}
150
151     virtual ~MockPrefHashStoreTransaction() {
152       outer_->transaction_active_ = false;
153       ++outer_->transactions_performed_;
154     }
155
156     // PrefHashStoreTransaction implementation.
157     virtual PrefHashStoreTransaction::ValueState CheckValue(
158         const std::string& path, const base::Value* value) const OVERRIDE;
159     virtual void StoreHash(const std::string& path,
160                            const base::Value* new_value) OVERRIDE;
161     virtual PrefHashStoreTransaction::ValueState CheckSplitValue(
162         const std::string& path,
163         const base::DictionaryValue* initial_split_value,
164         std::vector<std::string>* invalid_keys) const OVERRIDE;
165     virtual void StoreSplitHash(
166         const std::string& path,
167         const base::DictionaryValue* split_value) OVERRIDE;
168     virtual bool HasHash(const std::string& path) const OVERRIDE;
169     virtual void ImportHash(const std::string& path,
170                             const base::Value* hash) OVERRIDE;
171     virtual void ClearHash(const std::string& path) OVERRIDE;
172     virtual bool IsSuperMACValid() const OVERRIDE;
173     virtual bool StampSuperMac() OVERRIDE;
174
175    private:
176     MockPrefHashStore* outer_;
177
178     DISALLOW_COPY_AND_ASSIGN(MockPrefHashStoreTransaction);
179   };
180
181   // Records a call to this mock's CheckValue/CheckSplitValue methods.
182   PrefHashStoreTransaction::ValueState RecordCheckValue(
183       const std::string& path,
184       const base::Value* value,
185       PrefHashFilter::PrefTrackingStrategy strategy);
186
187   // Records a call to this mock's StoreHash/StoreSplitHash methods.
188   void RecordStoreHash(const std::string& path,
189                        const base::Value* new_value,
190                        PrefHashFilter::PrefTrackingStrategy strategy);
191
192   std::map<std::string, PrefHashStoreTransaction::ValueState> check_results_;
193   std::map<std::string, std::vector<std::string> > invalid_keys_results_;
194   std::map<std::string, ValuePtrStrategyPair> checked_values_;
195   std::map<std::string, ValuePtrStrategyPair> stored_values_;
196
197   // Number of transactions that are expected to be performed in the scope of
198   // this test (defaults to 1).
199   size_t transactions_expected_;
200
201   // Number of transactions that were performed via this MockPrefHashStore.
202   // Verified to match |transactions_expected_| when this MockPrefHashStore is
203   // deleted.
204   size_t transactions_performed_;
205
206   // Whether a transaction is currently active (only one transaction should be
207   // active at a time).
208   bool transaction_active_;
209
210   DISALLOW_COPY_AND_ASSIGN(MockPrefHashStore);
211 };
212
213 void MockPrefHashStore::SetCheckResult(
214     const std::string& path, PrefHashStoreTransaction::ValueState result) {
215   check_results_.insert(std::make_pair(path, result));
216 }
217
218 void MockPrefHashStore::SetInvalidKeysResult(
219     const std::string& path,
220     const std::vector<std::string>& invalid_keys_result) {
221   // Ensure |check_results_| has a CHANGED entry for |path|.
222   std::map<std::string,
223           PrefHashStoreTransaction::ValueState>::const_iterator result =
224       check_results_.find(path);
225   ASSERT_TRUE(result != check_results_.end());
226   ASSERT_EQ(PrefHashStoreTransaction::CHANGED, result->second);
227
228   invalid_keys_results_.insert(std::make_pair(path, invalid_keys_result));
229 }
230
231 scoped_ptr<PrefHashStoreTransaction> MockPrefHashStore::BeginTransaction(
232     scoped_ptr<HashStoreContents> storage) {
233   EXPECT_FALSE(transaction_active_);
234   return scoped_ptr<PrefHashStoreTransaction>(
235       new MockPrefHashStoreTransaction(this));
236 }
237
238 PrefHashStoreTransaction::ValueState MockPrefHashStore::RecordCheckValue(
239     const std::string& path,
240     const base::Value* value,
241     PrefHashFilter::PrefTrackingStrategy strategy) {
242   // Record that |path| was checked and validate that it wasn't previously
243   // checked.
244   EXPECT_TRUE(checked_values_.insert(
245       std::make_pair(path, std::make_pair(value, strategy))).second);
246   std::map<std::string,
247            PrefHashStoreTransaction::ValueState>::const_iterator result =
248       check_results_.find(path);
249   if (result != check_results_.end())
250     return result->second;
251   return PrefHashStoreTransaction::UNCHANGED;
252 }
253
254 void MockPrefHashStore::RecordStoreHash(
255     const std::string& path,
256     const base::Value* new_value,
257     PrefHashFilter::PrefTrackingStrategy strategy) {
258   EXPECT_TRUE(stored_values_.insert(
259       std::make_pair(path, std::make_pair(new_value, strategy))).second);
260 }
261
262 PrefHashStoreTransaction::ValueState
263 MockPrefHashStore::MockPrefHashStoreTransaction::CheckValue(
264     const std::string& path, const base::Value* value) const {
265   return outer_->RecordCheckValue(path, value,
266                                   PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
267 }
268
269 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreHash(
270     const std::string& path,
271     const base::Value* new_value) {
272   outer_->RecordStoreHash(path, new_value,
273                           PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
274 }
275
276 PrefHashStoreTransaction::ValueState
277 MockPrefHashStore::MockPrefHashStoreTransaction::CheckSplitValue(
278     const std::string& path,
279     const base::DictionaryValue* initial_split_value,
280     std::vector<std::string>* invalid_keys) const {
281   EXPECT_TRUE(invalid_keys && invalid_keys->empty());
282
283   std::map<std::string, std::vector<std::string> >::const_iterator
284       invalid_keys_result = outer_->invalid_keys_results_.find(path);
285   if (invalid_keys_result != outer_->invalid_keys_results_.end()) {
286     invalid_keys->insert(invalid_keys->begin(),
287                          invalid_keys_result->second.begin(),
288                          invalid_keys_result->second.end());
289   }
290
291   return outer_->RecordCheckValue(path, initial_split_value,
292                                   PrefHashFilter::TRACKING_STRATEGY_SPLIT);
293 }
294
295 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreSplitHash(
296     const std::string& path,
297     const base::DictionaryValue* new_value) {
298   outer_->RecordStoreHash(path, new_value,
299                           PrefHashFilter::TRACKING_STRATEGY_SPLIT);
300 }
301
302 bool MockPrefHashStore::MockPrefHashStoreTransaction::HasHash(
303     const std::string& path) const  {
304   ADD_FAILURE() << "Unexpected call.";
305   return false;
306 }
307
308 void MockPrefHashStore::MockPrefHashStoreTransaction::ImportHash(
309     const std::string& path,
310     const base::Value* hash)  {
311   ADD_FAILURE() << "Unexpected call.";
312 }
313
314 void MockPrefHashStore::MockPrefHashStoreTransaction::ClearHash(
315     const std::string& path)  {
316   ADD_FAILURE() << "Unexpected call.";
317 }
318
319 bool MockPrefHashStore::MockPrefHashStoreTransaction::IsSuperMACValid() const {
320   // TODO(erikwright): Test that the result of this method is reported to
321   // Settings.HashesDictionaryTrusted.
322   return false;
323 }
324
325 bool MockPrefHashStore::MockPrefHashStoreTransaction::StampSuperMac() {
326   // TODO(erikwright): Test that, when there are no other changes to the store,
327   // the result of this method determines the value of |prefs_altered| in the
328   // |post_filter_on_load_callback| invocation.
329   return false;
330 }
331
332 std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration(
333     PrefHashFilter::EnforcementLevel max_enforcement_level) {
334   std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration(
335       kTestTrackedPrefs, kTestTrackedPrefs + arraysize(kTestTrackedPrefs));
336   for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
337            configuration.begin();
338        it != configuration.end();
339        ++it) {
340     if (it->enforcement_level > max_enforcement_level)
341       it->enforcement_level = max_enforcement_level;
342   }
343   return configuration;
344 }
345
346 class PrefHashFilterTest
347     : public testing::TestWithParam<PrefHashFilter::EnforcementLevel> {
348  public:
349   PrefHashFilterTest() : mock_pref_hash_store_(NULL),
350                          pref_store_contents_(new base::DictionaryValue),
351                          last_filter_on_load_modified_prefs_(false) {}
352
353   virtual void SetUp() OVERRIDE {
354     // Construct a PrefHashFilter and MockPrefHashStore for the test.
355     InitializePrefHashFilter(GetConfiguration(GetParam()));
356   }
357
358  protected:
359   // Initializes |pref_hash_filter_| with a PrefHashFilter that uses a
360   // MockPrefHashStore. The raw pointer to the MockPrefHashStore (owned by the
361   // PrefHashFilter) is stored in |mock_pref_hash_store_|.
362   void InitializePrefHashFilter(const std::vector<
363       PrefHashFilter::TrackedPreferenceMetadata>& configuration) {
364     scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
365         new MockPrefHashStore);
366     mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
367     pref_hash_filter_.reset(
368         new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
369                            configuration,
370                            &mock_validation_delegate_,
371                            arraysize(kTestTrackedPrefs),
372                            true));
373   }
374
375   bool RecordedReset() {
376     return pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL);
377   }
378
379   // Calls FilterOnLoad() on |pref_hash_Filter_|. |pref_store_contents_| is
380   // handed off, but should be given back to us synchronously through
381   // GetPrefsBack() as there is no FilterOnLoadInterceptor installed on
382   // |pref_hash_filter_|.
383   void DoFilterOnLoad(bool expect_prefs_modifications) {
384     pref_hash_filter_->FilterOnLoad(
385         base::Bind(&PrefHashFilterTest::GetPrefsBack, base::Unretained(this),
386                    expect_prefs_modifications),
387         pref_store_contents_.Pass());
388   }
389
390   MockPrefHashStore* mock_pref_hash_store_;
391   scoped_ptr<base::DictionaryValue> pref_store_contents_;
392   bool last_filter_on_load_modified_prefs_;
393   MockValidationDelegate mock_validation_delegate_;
394   scoped_ptr<PrefHashFilter> pref_hash_filter_;
395
396  private:
397   // Stores |prefs| back in |pref_store_contents| and ensure
398   // |expected_schedule_write| matches the reported |schedule_write|.
399   void GetPrefsBack(bool expected_schedule_write,
400                     scoped_ptr<base::DictionaryValue> prefs,
401                     bool schedule_write) {
402     pref_store_contents_ = prefs.Pass();
403     EXPECT_TRUE(pref_store_contents_);
404     EXPECT_EQ(expected_schedule_write, schedule_write);
405   }
406
407   DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
408 };
409
410 TEST_P(PrefHashFilterTest, EmptyAndUnchanged) {
411   DoFilterOnLoad(false);
412   // All paths checked.
413   ASSERT_EQ(arraysize(kTestTrackedPrefs),
414             mock_pref_hash_store_->checked_paths_count());
415   // No paths stored, since they all return |UNCHANGED|.
416   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
417   // Since there was nothing in |pref_store_contents_| the checked value should
418   // have been NULL for all tracked preferences.
419   for (size_t i = 0; i < arraysize(kTestTrackedPrefs); ++i) {
420     ASSERT_EQ(NULL, mock_pref_hash_store_->checked_value(
421                         kTestTrackedPrefs[i].name).first);
422   }
423   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
424   ASSERT_FALSE(RecordedReset());
425
426   // Delegate saw all paths, and all unchanged.
427   ASSERT_EQ(arraysize(kTestTrackedPrefs),
428             mock_validation_delegate_.recorded_validations_count());
429   ASSERT_EQ(arraysize(kTestTrackedPrefs),
430             mock_validation_delegate_.CountValidationsOfState(
431                 PrefHashStoreTransaction::UNCHANGED));
432 }
433
434 TEST_P(PrefHashFilterTest, FilterTrackedPrefUpdate) {
435   base::DictionaryValue root_dict;
436   // Ownership of |string_value| is transfered to |root_dict|.
437   base::Value* string_value = base::Value::CreateStringValue("string value");
438   root_dict.Set(kAtomicPref, string_value);
439
440   // No path should be stored on FilterUpdate.
441   pref_hash_filter_->FilterUpdate(kAtomicPref);
442   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
443
444   // One path should be stored on FilterSerializeData.
445   pref_hash_filter_->FilterSerializeData(&root_dict);
446   ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
447   MockPrefHashStore::ValuePtrStrategyPair stored_value =
448       mock_pref_hash_store_->stored_value(kAtomicPref);
449   ASSERT_EQ(string_value, stored_value.first);
450   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
451
452   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
453   ASSERT_FALSE(RecordedReset());
454 }
455
456 TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
457   base::DictionaryValue root_dict;
458   // Ownership of |dict_value| is transfered to |root_dict|.
459   base::DictionaryValue* dict_value = new base::DictionaryValue;
460   dict_value->SetString("a", "foo");
461   dict_value->SetInteger("b", 1234);
462   root_dict.Set(kSplitPref, dict_value);
463
464   // No path should be stored on FilterUpdate.
465   pref_hash_filter_->FilterUpdate(kSplitPref);
466   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
467
468   // One path should be stored on FilterSerializeData.
469   pref_hash_filter_->FilterSerializeData(&root_dict);
470   ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
471   MockPrefHashStore::ValuePtrStrategyPair stored_value =
472        mock_pref_hash_store_->stored_value(kSplitPref);
473   ASSERT_EQ(dict_value, stored_value.first);
474   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
475
476   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
477   ASSERT_FALSE(RecordedReset());
478 }
479
480 TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
481   base::DictionaryValue root_dict;
482   root_dict.Set("untracked", base::Value::CreateStringValue("some value"));
483   pref_hash_filter_->FilterUpdate("untracked");
484
485   // No paths should be stored on FilterUpdate.
486   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
487
488   // Nor on FilterSerializeData.
489   pref_hash_filter_->FilterSerializeData(&root_dict);
490   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
491
492   // No transaction should even be started on FilterSerializeData() if there are
493   // no updates to perform.
494   ASSERT_EQ(0u, mock_pref_hash_store_->transactions_performed());
495 }
496
497 TEST_P(PrefHashFilterTest, MultiplePrefsFilterSerializeData) {
498   base::DictionaryValue root_dict;
499   // Ownership of the following values is transfered to |root_dict|.
500   base::Value* int_value1 = base::Value::CreateIntegerValue(1);
501   base::Value* int_value2 = base::Value::CreateIntegerValue(2);
502   base::Value* int_value3 = base::Value::CreateIntegerValue(3);
503   base::Value* int_value4 = base::Value::CreateIntegerValue(4);
504   base::DictionaryValue* dict_value = new base::DictionaryValue;
505   dict_value->Set("a", base::Value::CreateBooleanValue(true));
506   root_dict.Set(kAtomicPref, int_value1);
507   root_dict.Set(kAtomicPref2, int_value2);
508   root_dict.Set(kAtomicPref3, int_value3);
509   root_dict.Set("untracked", int_value4);
510   root_dict.Set(kSplitPref, dict_value);
511
512   // Only update kAtomicPref, kAtomicPref3, and kSplitPref.
513   pref_hash_filter_->FilterUpdate(kAtomicPref);
514   pref_hash_filter_->FilterUpdate(kAtomicPref3);
515   pref_hash_filter_->FilterUpdate(kSplitPref);
516   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
517
518   // Update kAtomicPref3 again, nothing should be stored still.
519   base::Value* int_value5 = base::Value::CreateIntegerValue(5);
520   root_dict.Set(kAtomicPref3, int_value5);
521   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
522
523   // On FilterSerializeData, only kAtomicPref, kAtomicPref3, and kSplitPref
524   // should get a new hash.
525   pref_hash_filter_->FilterSerializeData(&root_dict);
526   ASSERT_EQ(3u, mock_pref_hash_store_->stored_paths_count());
527   MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic1 =
528       mock_pref_hash_store_->stored_value(kAtomicPref);
529   ASSERT_EQ(int_value1, stored_value_atomic1.first);
530   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
531             stored_value_atomic1.second);
532   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
533
534   MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic3 =
535       mock_pref_hash_store_->stored_value(kAtomicPref3);
536   ASSERT_EQ(int_value5, stored_value_atomic3.first);
537   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
538             stored_value_atomic3.second);
539
540   MockPrefHashStore::ValuePtrStrategyPair stored_value_split =
541        mock_pref_hash_store_->stored_value(kSplitPref);
542   ASSERT_EQ(dict_value, stored_value_split.first);
543   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value_split.second);
544 }
545
546 TEST_P(PrefHashFilterTest, EmptyAndUnknown) {
547   ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
548   ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
549   // NULL values are always trusted by the PrefHashStore.
550   mock_pref_hash_store_->SetCheckResult(
551       kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
552   mock_pref_hash_store_->SetCheckResult(
553       kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
554   DoFilterOnLoad(false);
555   ASSERT_EQ(arraysize(kTestTrackedPrefs),
556             mock_pref_hash_store_->checked_paths_count());
557   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
558   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
559
560   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
561        mock_pref_hash_store_->stored_value(kAtomicPref);
562   ASSERT_EQ(NULL, stored_atomic_value.first);
563   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
564             stored_atomic_value.second);
565
566   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
567        mock_pref_hash_store_->stored_value(kSplitPref);
568   ASSERT_EQ(NULL, stored_split_value.first);
569   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
570             stored_split_value.second);
571
572   // Delegate saw all prefs, two of which had the expected value_state.
573   ASSERT_EQ(arraysize(kTestTrackedPrefs),
574             mock_validation_delegate_.recorded_validations_count());
575   ASSERT_EQ(2u,
576             mock_validation_delegate_.CountValidationsOfState(
577                 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
578   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
579             mock_validation_delegate_.CountValidationsOfState(
580                 PrefHashStoreTransaction::UNCHANGED));
581
582   const MockValidationDelegate::ValidationEvent* validated_split_pref =
583       mock_validation_delegate_.GetEventForPath(kSplitPref);
584   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
585             validated_split_pref->strategy);
586   EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET,
587             validated_split_pref->reset_action);
588   const MockValidationDelegate::ValidationEvent* validated_atomic_pref =
589       mock_validation_delegate_.GetEventForPath(kAtomicPref);
590   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
591             validated_atomic_pref->strategy);
592   EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET,
593             validated_atomic_pref->reset_action);
594 }
595
596 TEST_P(PrefHashFilterTest, InitialValueUnknown) {
597   // Ownership of these values is transfered to |pref_store_contents_|.
598   base::StringValue* string_value = new base::StringValue("string value");
599   pref_store_contents_->Set(kAtomicPref, string_value);
600
601   base::DictionaryValue* dict_value = new base::DictionaryValue;
602   dict_value->SetString("a", "foo");
603   dict_value->SetInteger("b", 1234);
604   pref_store_contents_->Set(kSplitPref, dict_value);
605
606   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
607   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
608
609   mock_pref_hash_store_->SetCheckResult(
610       kAtomicPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
611   mock_pref_hash_store_->SetCheckResult(
612       kSplitPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
613   // If we are enforcing, expect this to report changes.
614   DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
615   ASSERT_EQ(arraysize(kTestTrackedPrefs),
616             mock_pref_hash_store_->checked_paths_count());
617   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
618   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
619
620   // Delegate saw all prefs, two of which had the expected value_state.
621   ASSERT_EQ(arraysize(kTestTrackedPrefs),
622             mock_validation_delegate_.recorded_validations_count());
623   ASSERT_EQ(2u,
624             mock_validation_delegate_.CountValidationsOfState(
625                 PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE));
626   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
627             mock_validation_delegate_.CountValidationsOfState(
628                 PrefHashStoreTransaction::UNCHANGED));
629
630   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
631        mock_pref_hash_store_->stored_value(kAtomicPref);
632   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
633        mock_pref_hash_store_->stored_value(kSplitPref);
634   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
635             stored_atomic_value.second);
636   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
637             stored_split_value.second);
638   if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
639     // Ensure the prefs were cleared and the hashes for NULL were restored if
640     // the current enforcement level denies seeding.
641     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
642     ASSERT_EQ(NULL, stored_atomic_value.first);
643
644     ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
645     ASSERT_EQ(NULL, stored_split_value.first);
646
647     ASSERT_TRUE(RecordedReset());
648   } else {
649     // Otherwise the values should have remained intact and the hashes should
650     // have been updated to match them.
651     const base::Value* atomic_value_in_store;
652     ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
653     ASSERT_EQ(string_value, atomic_value_in_store);
654     ASSERT_EQ(string_value, stored_atomic_value.first);
655
656     const base::Value* split_value_in_store;
657     ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
658     ASSERT_EQ(dict_value, split_value_in_store);
659     ASSERT_EQ(dict_value, stored_split_value.first);
660
661     ASSERT_FALSE(RecordedReset());
662   }
663 }
664
665 TEST_P(PrefHashFilterTest, InitialValueTrustedUnknown) {
666   // Ownership of this value is transfered to |pref_store_contents_|.
667   base::Value* string_value = base::Value::CreateStringValue("test");
668   pref_store_contents_->Set(kAtomicPref, string_value);
669
670   base::DictionaryValue* dict_value = new base::DictionaryValue;
671   dict_value->SetString("a", "foo");
672   dict_value->SetInteger("b", 1234);
673   pref_store_contents_->Set(kSplitPref, dict_value);
674
675   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
676   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
677
678   mock_pref_hash_store_->SetCheckResult(
679       kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
680   mock_pref_hash_store_->SetCheckResult(
681       kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
682   DoFilterOnLoad(false);
683   ASSERT_EQ(arraysize(kTestTrackedPrefs),
684             mock_pref_hash_store_->checked_paths_count());
685   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
686   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
687
688   // Delegate saw all prefs, two of which had the expected value_state.
689   ASSERT_EQ(arraysize(kTestTrackedPrefs),
690             mock_validation_delegate_.recorded_validations_count());
691   ASSERT_EQ(2u,
692             mock_validation_delegate_.CountValidationsOfState(
693                 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE));
694   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
695             mock_validation_delegate_.CountValidationsOfState(
696                 PrefHashStoreTransaction::UNCHANGED));
697
698   // Seeding is always allowed for trusted unknown values.
699   const base::Value* atomic_value_in_store;
700   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
701   ASSERT_EQ(string_value, atomic_value_in_store);
702   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
703        mock_pref_hash_store_->stored_value(kAtomicPref);
704   ASSERT_EQ(string_value, stored_atomic_value.first);
705   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
706             stored_atomic_value.second);
707
708   const base::Value* split_value_in_store;
709   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
710   ASSERT_EQ(dict_value, split_value_in_store);
711   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
712        mock_pref_hash_store_->stored_value(kSplitPref);
713   ASSERT_EQ(dict_value, stored_split_value.first);
714   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
715             stored_split_value.second);
716 }
717
718 TEST_P(PrefHashFilterTest, InitialValueChanged) {
719   // Ownership of this value is transfered to |pref_store_contents_|.
720   base::Value* int_value = base::Value::CreateIntegerValue(1234);
721   pref_store_contents_->Set(kAtomicPref, int_value);
722
723   base::DictionaryValue* dict_value = new base::DictionaryValue;
724   dict_value->SetString("a", "foo");
725   dict_value->SetInteger("b", 1234);
726   dict_value->SetInteger("c", 56);
727   dict_value->SetBoolean("d", false);
728   pref_store_contents_->Set(kSplitPref, dict_value);
729
730   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
731   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
732
733   mock_pref_hash_store_->SetCheckResult(kAtomicPref,
734                                         PrefHashStoreTransaction::CHANGED);
735   mock_pref_hash_store_->SetCheckResult(kSplitPref,
736                                         PrefHashStoreTransaction::CHANGED);
737
738   std::vector<std::string> mock_invalid_keys;
739   mock_invalid_keys.push_back("a");
740   mock_invalid_keys.push_back("c");
741   mock_pref_hash_store_->SetInvalidKeysResult(kSplitPref, mock_invalid_keys);
742
743   DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
744   ASSERT_EQ(arraysize(kTestTrackedPrefs),
745             mock_pref_hash_store_->checked_paths_count());
746   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
747   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
748
749   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
750        mock_pref_hash_store_->stored_value(kAtomicPref);
751   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
752        mock_pref_hash_store_->stored_value(kSplitPref);
753   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
754             stored_atomic_value.second);
755   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
756             stored_split_value.second);
757   if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
758     // Ensure the atomic pref was cleared and the hash for NULL was restored if
759     // the current enforcement level prevents changes.
760     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
761     ASSERT_EQ(NULL, stored_atomic_value.first);
762
763     // The split pref on the other hand should only have been stripped of its
764     // invalid keys.
765     const base::Value* split_value_in_store;
766     ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
767     ASSERT_EQ(2U, dict_value->size());
768     ASSERT_FALSE(dict_value->HasKey("a"));
769     ASSERT_TRUE(dict_value->HasKey("b"));
770     ASSERT_FALSE(dict_value->HasKey("c"));
771     ASSERT_TRUE(dict_value->HasKey("d"));
772     ASSERT_EQ(dict_value, stored_split_value.first);
773
774     ASSERT_TRUE(RecordedReset());
775   } else {
776     // Otherwise the value should have remained intact and the hash should have
777     // been updated to match it.
778     const base::Value* atomic_value_in_store;
779     ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
780     ASSERT_EQ(int_value, atomic_value_in_store);
781     ASSERT_EQ(int_value, stored_atomic_value.first);
782
783     const base::Value* split_value_in_store;
784     ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
785     ASSERT_EQ(dict_value, split_value_in_store);
786     ASSERT_EQ(4U, dict_value->size());
787     ASSERT_TRUE(dict_value->HasKey("a"));
788     ASSERT_TRUE(dict_value->HasKey("b"));
789     ASSERT_TRUE(dict_value->HasKey("c"));
790     ASSERT_TRUE(dict_value->HasKey("d"));
791     ASSERT_EQ(dict_value, stored_split_value.first);
792
793     ASSERT_FALSE(RecordedReset());
794   }
795 }
796
797 TEST_P(PrefHashFilterTest, EmptyCleared) {
798   ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
799   ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
800   mock_pref_hash_store_->SetCheckResult(kAtomicPref,
801                                         PrefHashStoreTransaction::CLEARED);
802   mock_pref_hash_store_->SetCheckResult(kSplitPref,
803                                         PrefHashStoreTransaction::CLEARED);
804   DoFilterOnLoad(false);
805   ASSERT_EQ(arraysize(kTestTrackedPrefs),
806             mock_pref_hash_store_->checked_paths_count());
807   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
808   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
809
810   // Delegate saw all prefs, two of which had the expected value_state.
811   ASSERT_EQ(arraysize(kTestTrackedPrefs),
812             mock_validation_delegate_.recorded_validations_count());
813   ASSERT_EQ(2u,
814             mock_validation_delegate_.CountValidationsOfState(
815                 PrefHashStoreTransaction::CLEARED));
816   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
817             mock_validation_delegate_.CountValidationsOfState(
818                 PrefHashStoreTransaction::UNCHANGED));
819
820   // Regardless of the enforcement level, the only thing that should be done is
821   // to restore the hash for NULL. The value itself should still be NULL.
822   ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
823   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
824        mock_pref_hash_store_->stored_value(kAtomicPref);
825   ASSERT_EQ(NULL, stored_atomic_value.first);
826   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
827             stored_atomic_value.second);
828
829   ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
830   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
831        mock_pref_hash_store_->stored_value(kSplitPref);
832   ASSERT_EQ(NULL, stored_split_value.first);
833   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
834             stored_split_value.second);
835 }
836
837 TEST_P(PrefHashFilterTest, InitialValueMigrated) {
838   // Only test atomic prefs, split prefs were introduce after the migration.
839
840   // Ownership of this value is transfered to |pref_store_contents_|.
841   base::ListValue* list_value = new base::ListValue;
842   list_value->Append(base::Value::CreateStringValue("test"));
843   pref_store_contents_->Set(kAtomicPref, list_value);
844
845   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
846
847   mock_pref_hash_store_->SetCheckResult(kAtomicPref,
848                                         PrefHashStoreTransaction::WEAK_LEGACY);
849
850   DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
851   ASSERT_EQ(arraysize(kTestTrackedPrefs),
852             mock_pref_hash_store_->checked_paths_count());
853   ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
854   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
855
856   // Delegate saw all prefs, one of which had the expected value_state.
857   ASSERT_EQ(arraysize(kTestTrackedPrefs),
858             mock_validation_delegate_.recorded_validations_count());
859   ASSERT_EQ(1u,
860             mock_validation_delegate_.CountValidationsOfState(
861                 PrefHashStoreTransaction::WEAK_LEGACY));
862   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 1u,
863             mock_validation_delegate_.CountValidationsOfState(
864                 PrefHashStoreTransaction::UNCHANGED));
865
866   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
867        mock_pref_hash_store_->stored_value(kAtomicPref);
868   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
869             stored_atomic_value.second);
870   if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
871     // Ensure the pref was cleared and the hash for NULL was restored if the
872     // current enforcement level prevents migration.
873     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
874     ASSERT_EQ(NULL, stored_atomic_value.first);
875
876     ASSERT_TRUE(RecordedReset());
877   } else {
878     // Otherwise the value should have remained intact and the hash should have
879     // been updated to match it.
880     const base::Value* atomic_value_in_store;
881     ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
882     ASSERT_EQ(list_value, atomic_value_in_store);
883     ASSERT_EQ(list_value, stored_atomic_value.first);
884
885     ASSERT_FALSE(RecordedReset());
886   }
887 }
888
889 TEST_P(PrefHashFilterTest, InitialValueUnchangedLegacyId) {
890   // Ownership of these values is transfered to |pref_store_contents_|.
891   base::StringValue* string_value = new base::StringValue("string value");
892   pref_store_contents_->Set(kAtomicPref, string_value);
893
894   base::DictionaryValue* dict_value = new base::DictionaryValue;
895   dict_value->SetString("a", "foo");
896   dict_value->SetInteger("b", 1234);
897   pref_store_contents_->Set(kSplitPref, dict_value);
898
899   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
900   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL));
901
902   mock_pref_hash_store_->SetCheckResult(
903       kAtomicPref, PrefHashStoreTransaction::SECURE_LEGACY);
904   mock_pref_hash_store_->SetCheckResult(
905       kSplitPref, PrefHashStoreTransaction::SECURE_LEGACY);
906   DoFilterOnLoad(false);
907   ASSERT_EQ(arraysize(kTestTrackedPrefs),
908             mock_pref_hash_store_->checked_paths_count());
909   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
910
911   // Delegate saw all prefs, two of which had the expected value_state.
912   ASSERT_EQ(arraysize(kTestTrackedPrefs),
913             mock_validation_delegate_.recorded_validations_count());
914   ASSERT_EQ(2u,
915             mock_validation_delegate_.CountValidationsOfState(
916                 PrefHashStoreTransaction::SECURE_LEGACY));
917   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
918             mock_validation_delegate_.CountValidationsOfState(
919                 PrefHashStoreTransaction::UNCHANGED));
920
921   // Ensure that both the atomic and split hashes were restored.
922   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
923
924   // In all cases, the values should have remained intact and the hashes should
925   // have been updated to match them.
926
927   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
928        mock_pref_hash_store_->stored_value(kAtomicPref);
929   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
930             stored_atomic_value.second);
931   const base::Value* atomic_value_in_store;
932   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store));
933   ASSERT_EQ(string_value, atomic_value_in_store);
934   ASSERT_EQ(string_value, stored_atomic_value.first);
935
936   MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
937        mock_pref_hash_store_->stored_value(kSplitPref);
938   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
939             stored_split_value.second);
940   const base::Value* split_value_in_store;
941   ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store));
942   ASSERT_EQ(dict_value, split_value_in_store);
943   ASSERT_EQ(dict_value, stored_split_value.first);
944
945   ASSERT_FALSE(RecordedReset());
946 }
947
948 TEST_P(PrefHashFilterTest, DontResetReportOnly) {
949   // Ownership of these values is transfered to |pref_store_contents_|.
950   base::Value* int_value1 = base::Value::CreateIntegerValue(1);
951   base::Value* int_value2 = base::Value::CreateIntegerValue(2);
952   base::Value* report_only_val = base::Value::CreateIntegerValue(3);
953   base::DictionaryValue* report_only_split_val = new base::DictionaryValue;
954   report_only_split_val->SetInteger("a", 1234);
955   pref_store_contents_->Set(kAtomicPref, int_value1);
956   pref_store_contents_->Set(kAtomicPref2, int_value2);
957   pref_store_contents_->Set(kReportOnlyPref, report_only_val);
958   pref_store_contents_->Set(kReportOnlySplitPref, report_only_split_val);
959
960   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL));
961   ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, NULL));
962   ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL));
963   ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL));
964
965   mock_pref_hash_store_->SetCheckResult(kAtomicPref,
966                                         PrefHashStoreTransaction::CHANGED);
967   mock_pref_hash_store_->SetCheckResult(kAtomicPref2,
968                                         PrefHashStoreTransaction::CHANGED);
969   mock_pref_hash_store_->SetCheckResult(kReportOnlyPref,
970                                         PrefHashStoreTransaction::CHANGED);
971   mock_pref_hash_store_->SetCheckResult(kReportOnlySplitPref,
972                                         PrefHashStoreTransaction::CHANGED);
973
974   DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD);
975   // All prefs should be checked and a new hash should be stored for each tested
976   // pref.
977   ASSERT_EQ(arraysize(kTestTrackedPrefs),
978             mock_pref_hash_store_->checked_paths_count());
979   ASSERT_EQ(4u, mock_pref_hash_store_->stored_paths_count());
980   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
981
982   // Delegate saw all prefs, four of which had the expected value_state.
983   ASSERT_EQ(arraysize(kTestTrackedPrefs),
984             mock_validation_delegate_.recorded_validations_count());
985   ASSERT_EQ(4u,
986             mock_validation_delegate_.CountValidationsOfState(
987                 PrefHashStoreTransaction::CHANGED));
988   ASSERT_EQ(arraysize(kTestTrackedPrefs) - 4u,
989             mock_validation_delegate_.CountValidationsOfState(
990                 PrefHashStoreTransaction::UNCHANGED));
991
992   // No matter what the enforcement level is, the report only pref should never
993   // be reset.
994   ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL));
995   ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL));
996   ASSERT_EQ(report_only_val,
997             mock_pref_hash_store_->stored_value(kReportOnlyPref).first);
998   ASSERT_EQ(report_only_split_val,
999             mock_pref_hash_store_->stored_value(kReportOnlySplitPref).first);
1000
1001   // All other prefs should have been reset if the enforcement level allows it.
1002   if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
1003     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
1004     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref2, NULL));
1005     ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first);
1006     ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first);
1007
1008     ASSERT_TRUE(RecordedReset());
1009   } else {
1010     const base::Value* value_in_store;
1011     const base::Value* value_in_store2;
1012     ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &value_in_store));
1013     ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, &value_in_store2));
1014     ASSERT_EQ(int_value1, value_in_store);
1015     ASSERT_EQ(int_value1,
1016               mock_pref_hash_store_->stored_value(kAtomicPref).first);
1017     ASSERT_EQ(int_value2, value_in_store2);
1018     ASSERT_EQ(int_value2,
1019               mock_pref_hash_store_->stored_value(kAtomicPref2).first);
1020
1021     ASSERT_FALSE(RecordedReset());
1022   }
1023 }
1024
1025 INSTANTIATE_TEST_CASE_P(
1026     PrefHashFilterTestInstance, PrefHashFilterTest,
1027     testing::Values(PrefHashFilter::NO_ENFORCEMENT,
1028                     PrefHashFilter::ENFORCE_ON_LOAD));