This source file includes following definitions.
- commit_performed_
- transactions_performed
- commit_performed
- checked_paths_count
- stored_paths_count
- checked_value
- stored_value
- SetCheckResult
- SetInvalidKeysResult
- BeginTransaction
- CommitPendingWrite
- RecordCheckValue
- RecordStoreHash
- CheckValue
- StoreHash
- CheckSplitValue
- StoreSplitHash
- GetConfiguration
- SetUp
- InitializePrefHashFilter
- RecordedReset
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
- TEST_P
#include "chrome/browser/prefs/pref_hash_filter.h"
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/testing_pref_store.h"
#include "base/values.h"
#include "chrome/browser/prefs/pref_hash_store.h"
#include "chrome/browser/prefs/pref_hash_store_transaction.h"
#include "chrome/common/pref_names.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kAtomicPref[] = "atomic_pref";
const char kAtomicPref2[] = "atomic_pref2";
const char kAtomicPref3[] = "pref3";
const char kReportOnlyPref[] = "report_only";
const char kReportOnlySplitPref[] = "report_only_split_pref";
const char kSplitPref[] = "split_pref";
const PrefHashFilter::TrackedPreferenceMetadata kTestTrackedPrefs[] = {
{
0, kAtomicPref, PrefHashFilter::ENFORCE_ON_LOAD,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC
},
{
1, kReportOnlyPref, PrefHashFilter::NO_ENFORCEMENT,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC
},
{
2, kSplitPref, PrefHashFilter::ENFORCE_ON_LOAD,
PrefHashFilter::TRACKING_STRATEGY_SPLIT
},
{
3, kReportOnlySplitPref, PrefHashFilter::NO_ENFORCEMENT,
PrefHashFilter::TRACKING_STRATEGY_SPLIT
},
{
4, kAtomicPref2, PrefHashFilter::ENFORCE_ON_LOAD,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC
},
{
5, kAtomicPref3, PrefHashFilter::ENFORCE_ON_LOAD,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC
},
};
}
class MockPrefHashStore : public PrefHashStore {
public:
typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy>
ValuePtrStrategyPair;
MockPrefHashStore() : transactions_performed_(0),
transaction_active_(false),
commit_performed_(false) {}
virtual ~MockPrefHashStore() {
EXPECT_FALSE(transaction_active_);
}
void SetCheckResult(const std::string& path,
PrefHashStoreTransaction::ValueState result);
void SetInvalidKeysResult(
const std::string& path,
const std::vector<std::string>& invalid_keys_result);
size_t transactions_performed() { return transactions_performed_; }
bool commit_performed() { return commit_performed_; }
size_t checked_paths_count() const {
return checked_values_.size();
}
size_t stored_paths_count() const {
return stored_values_.size();
}
ValuePtrStrategyPair checked_value(const std::string& path) const {
std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
checked_values_.find(path);
if (value != checked_values_.end())
return value->second;
return std::make_pair(
reinterpret_cast<void*>(0xBAD),
static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
}
ValuePtrStrategyPair stored_value(const std::string& path) const {
std::map<std::string, ValuePtrStrategyPair>::const_iterator value =
stored_values_.find(path);
if (value != stored_values_.end())
return value->second;
return std::make_pair(
reinterpret_cast<void*>(0xBAD),
static_cast<PrefHashFilter::PrefTrackingStrategy>(-1));
}
virtual scoped_ptr<PrefHashStoreTransaction> BeginTransaction() OVERRIDE;
virtual void CommitPendingWrite() OVERRIDE;
private:
class MockPrefHashStoreTransaction : public PrefHashStoreTransaction {
public:
explicit MockPrefHashStoreTransaction(MockPrefHashStore* outer)
: outer_(outer) {}
virtual ~MockPrefHashStoreTransaction() {
outer_->transaction_active_ = false;
++outer_->transactions_performed_;
}
virtual PrefHashStoreTransaction::ValueState CheckValue(
const std::string& path, const base::Value* value) const OVERRIDE;
virtual void StoreHash(const std::string& path,
const base::Value* new_value) OVERRIDE;
virtual PrefHashStoreTransaction::ValueState CheckSplitValue(
const std::string& path,
const base::DictionaryValue* initial_split_value,
std::vector<std::string>* invalid_keys) const OVERRIDE;
virtual void StoreSplitHash(
const std::string& path,
const base::DictionaryValue* split_value) OVERRIDE;
private:
MockPrefHashStore* outer_;
DISALLOW_COPY_AND_ASSIGN(MockPrefHashStoreTransaction);
};
PrefHashStoreTransaction::ValueState RecordCheckValue(
const std::string& path,
const base::Value* value,
PrefHashFilter::PrefTrackingStrategy strategy);
void RecordStoreHash(const std::string& path,
const base::Value* new_value,
PrefHashFilter::PrefTrackingStrategy strategy);
std::map<std::string, PrefHashStoreTransaction::ValueState> check_results_;
std::map<std::string, std::vector<std::string> > invalid_keys_results_;
std::map<std::string, ValuePtrStrategyPair> checked_values_;
std::map<std::string, ValuePtrStrategyPair> stored_values_;
size_t transactions_expected_;
size_t transactions_performed_;
bool transaction_active_;
bool commit_performed_;
DISALLOW_COPY_AND_ASSIGN(MockPrefHashStore);
};
void MockPrefHashStore::SetCheckResult(
const std::string& path, PrefHashStoreTransaction::ValueState result) {
check_results_.insert(std::make_pair(path, result));
}
void MockPrefHashStore::SetInvalidKeysResult(
const std::string& path,
const std::vector<std::string>& invalid_keys_result) {
std::map<std::string,
PrefHashStoreTransaction::ValueState>::const_iterator result =
check_results_.find(path);
ASSERT_TRUE(result != check_results_.end());
ASSERT_EQ(PrefHashStoreTransaction::CHANGED, result->second);
invalid_keys_results_.insert(std::make_pair(path, invalid_keys_result));
}
scoped_ptr<PrefHashStoreTransaction> MockPrefHashStore::BeginTransaction() {
EXPECT_FALSE(transaction_active_);
return scoped_ptr<PrefHashStoreTransaction>(
new MockPrefHashStoreTransaction(this));
}
void MockPrefHashStore::CommitPendingWrite() {
EXPECT_FALSE(commit_performed_);
commit_performed_ = true;
}
PrefHashStoreTransaction::ValueState MockPrefHashStore::RecordCheckValue(
const std::string& path,
const base::Value* value,
PrefHashFilter::PrefTrackingStrategy strategy) {
EXPECT_TRUE(checked_values_.insert(
std::make_pair(path, std::make_pair(value, strategy))).second);
std::map<std::string,
PrefHashStoreTransaction::ValueState>::const_iterator result =
check_results_.find(path);
if (result != check_results_.end())
return result->second;
return PrefHashStoreTransaction::UNCHANGED;
}
void MockPrefHashStore::RecordStoreHash(
const std::string& path,
const base::Value* new_value,
PrefHashFilter::PrefTrackingStrategy strategy) {
EXPECT_TRUE(stored_values_.insert(
std::make_pair(path, std::make_pair(new_value, strategy))).second);
}
PrefHashStoreTransaction::ValueState
MockPrefHashStore::MockPrefHashStoreTransaction::CheckValue(
const std::string& path, const base::Value* value) const {
return outer_->RecordCheckValue(path, value,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
}
void MockPrefHashStore::MockPrefHashStoreTransaction::StoreHash(
const std::string& path,
const base::Value* new_value) {
outer_->RecordStoreHash(path, new_value,
PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
}
PrefHashStoreTransaction::ValueState
MockPrefHashStore::MockPrefHashStoreTransaction::CheckSplitValue(
const std::string& path,
const base::DictionaryValue* initial_split_value,
std::vector<std::string>* invalid_keys) const {
EXPECT_TRUE(invalid_keys && invalid_keys->empty());
std::map<std::string, std::vector<std::string> >::const_iterator
invalid_keys_result = outer_->invalid_keys_results_.find(path);
if (invalid_keys_result != outer_->invalid_keys_results_.end()) {
invalid_keys->insert(invalid_keys->begin(),
invalid_keys_result->second.begin(),
invalid_keys_result->second.end());
}
return outer_->RecordCheckValue(path, initial_split_value,
PrefHashFilter::TRACKING_STRATEGY_SPLIT);
}
void MockPrefHashStore::MockPrefHashStoreTransaction::StoreSplitHash(
const std::string& path,
const base::DictionaryValue* new_value) {
outer_->RecordStoreHash(path, new_value,
PrefHashFilter::TRACKING_STRATEGY_SPLIT);
}
std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration(
PrefHashFilter::EnforcementLevel max_enforcement_level) {
std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration(
kTestTrackedPrefs, kTestTrackedPrefs + arraysize(kTestTrackedPrefs));
for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
configuration.begin();
it != configuration.end();
++it) {
if (it->enforcement_level > max_enforcement_level)
it->enforcement_level = max_enforcement_level;
}
return configuration;
}
class PrefHashFilterTest
: public testing::TestWithParam<PrefHashFilter::EnforcementLevel> {
public:
PrefHashFilterTest() : mock_pref_hash_store_(NULL) {}
virtual void SetUp() OVERRIDE {
InitializePrefHashFilter(GetConfiguration(GetParam()));
}
protected:
void InitializePrefHashFilter(const std::vector<
PrefHashFilter::TrackedPreferenceMetadata>& configuration) {
scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
new MockPrefHashStore);
mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
pref_hash_filter_.reset(
new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
configuration,
arraysize(kTestTrackedPrefs)));
}
bool RecordedReset() {
return pref_store_contents_.Get(prefs::kPreferenceResetTime, NULL);
}
MockPrefHashStore* mock_pref_hash_store_;
base::DictionaryValue pref_store_contents_;
scoped_ptr<PrefHashFilter> pref_hash_filter_;
DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
};
TEST_P(PrefHashFilterTest, EmptyAndUnchanged) {
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
for (size_t i = 0; i < arraysize(kTestTrackedPrefs); ++i) {
ASSERT_EQ(NULL, mock_pref_hash_store_->checked_value(
kTestTrackedPrefs[i].name).first);
}
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_FALSE(RecordedReset());
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, FilterTrackedPrefUpdate) {
base::DictionaryValue root_dict;
base::Value* string_value = base::Value::CreateStringValue("string value");
root_dict.Set(kAtomicPref, string_value);
pref_hash_filter_->FilterUpdate(kAtomicPref);
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
pref_hash_filter_->FilterSerializeData(&root_dict);
ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
MockPrefHashStore::ValuePtrStrategyPair stored_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(string_value, stored_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_FALSE(RecordedReset());
EXPECT_TRUE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
base::DictionaryValue root_dict;
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->SetString("a", "foo");
dict_value->SetInteger("b", 1234);
root_dict.Set(kSplitPref, dict_value);
pref_hash_filter_->FilterUpdate(kSplitPref);
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
pref_hash_filter_->FilterSerializeData(&root_dict);
ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
MockPrefHashStore::ValuePtrStrategyPair stored_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(dict_value, stored_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_FALSE(RecordedReset());
EXPECT_TRUE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
base::DictionaryValue root_dict;
root_dict.Set("untracked", base::Value::CreateStringValue("some value"));
pref_hash_filter_->FilterUpdate("untracked");
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
pref_hash_filter_->FilterSerializeData(&root_dict);
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(0u, mock_pref_hash_store_->transactions_performed());
}
TEST_P(PrefHashFilterTest, MultiplePrefsFilterSerializeData) {
base::DictionaryValue root_dict;
base::Value* int_value1 = base::Value::CreateIntegerValue(1);
base::Value* int_value2 = base::Value::CreateIntegerValue(2);
base::Value* int_value3 = base::Value::CreateIntegerValue(3);
base::Value* int_value4 = base::Value::CreateIntegerValue(4);
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->Set("a", base::Value::CreateBooleanValue(true));
root_dict.Set(kAtomicPref, int_value1);
root_dict.Set(kAtomicPref2, int_value2);
root_dict.Set(kAtomicPref3, int_value3);
root_dict.Set("untracked", int_value4);
root_dict.Set(kSplitPref, dict_value);
pref_hash_filter_->FilterUpdate(kAtomicPref);
pref_hash_filter_->FilterUpdate(kAtomicPref3);
pref_hash_filter_->FilterUpdate(kSplitPref);
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
base::Value* int_value5 = base::Value::CreateIntegerValue(5);
root_dict.Set(kAtomicPref3, int_value5);
ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
pref_hash_filter_->FilterSerializeData(&root_dict);
ASSERT_EQ(3u, mock_pref_hash_store_->stored_paths_count());
MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic1 =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(int_value1, stored_value_atomic1.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_value_atomic1.second);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic3 =
mock_pref_hash_store_->stored_value(kAtomicPref3);
ASSERT_EQ(int_value5, stored_value_atomic3.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_value_atomic3.second);
MockPrefHashStore::ValuePtrStrategyPair stored_value_split =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(dict_value, stored_value_split.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value_split.second);
EXPECT_TRUE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, EmptyAndUnknown) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_FALSE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(
kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
mock_pref_hash_store_->SetCheckResult(
kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(NULL, stored_atomic_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(NULL, stored_split_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, InitialValueUnknown) {
base::StringValue* string_value = new base::StringValue("string value");
pref_store_contents_.Set(kAtomicPref, string_value);
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->SetString("a", "foo");
dict_value->SetInteger("b", 1234);
pref_store_contents_.Set(kSplitPref, dict_value);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(
kAtomicPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
mock_pref_hash_store_->SetCheckResult(
kSplitPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_EQ(NULL, stored_atomic_value.first);
ASSERT_FALSE(pref_store_contents_.Get(kSplitPref, NULL));
ASSERT_EQ(NULL, stored_split_value.first);
ASSERT_TRUE(RecordedReset());
} else {
const base::Value* atomic_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &atomic_value_in_store));
ASSERT_EQ(string_value, atomic_value_in_store);
ASSERT_EQ(string_value, stored_atomic_value.first);
const base::Value* split_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, &split_value_in_store));
ASSERT_EQ(dict_value, split_value_in_store);
ASSERT_EQ(dict_value, stored_split_value.first);
ASSERT_FALSE(RecordedReset());
}
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, InitialValueTrustedUnknown) {
base::Value* string_value = base::Value::CreateStringValue("test");
pref_store_contents_.Set(kAtomicPref, string_value);
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->SetString("a", "foo");
dict_value->SetInteger("b", 1234);
pref_store_contents_.Set(kSplitPref, dict_value);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(
kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
mock_pref_hash_store_->SetCheckResult(
kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
const base::Value* atomic_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &atomic_value_in_store));
ASSERT_EQ(string_value, atomic_value_in_store);
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(string_value, stored_atomic_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
const base::Value* split_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, &split_value_in_store));
ASSERT_EQ(dict_value, split_value_in_store);
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(dict_value, stored_split_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, InitialValueChanged) {
base::Value* int_value = base::Value::CreateIntegerValue(1234);
pref_store_contents_.Set(kAtomicPref, int_value);
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->SetString("a", "foo");
dict_value->SetInteger("b", 1234);
dict_value->SetInteger("c", 56);
dict_value->SetBoolean("d", false);
pref_store_contents_.Set(kSplitPref, dict_value);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(kAtomicPref,
PrefHashStoreTransaction::CHANGED);
mock_pref_hash_store_->SetCheckResult(kSplitPref,
PrefHashStoreTransaction::CHANGED);
std::vector<std::string> mock_invalid_keys;
mock_invalid_keys.push_back("a");
mock_invalid_keys.push_back("c");
mock_pref_hash_store_->SetInvalidKeysResult(kSplitPref, mock_invalid_keys);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_EQ(NULL, stored_atomic_value.first);
const base::Value* split_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, &split_value_in_store));
ASSERT_EQ(2U, dict_value->size());
ASSERT_FALSE(dict_value->HasKey("a"));
ASSERT_TRUE(dict_value->HasKey("b"));
ASSERT_FALSE(dict_value->HasKey("c"));
ASSERT_TRUE(dict_value->HasKey("d"));
ASSERT_EQ(dict_value, stored_split_value.first);
ASSERT_TRUE(RecordedReset());
} else {
const base::Value* atomic_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &atomic_value_in_store));
ASSERT_EQ(int_value, atomic_value_in_store);
ASSERT_EQ(int_value, stored_atomic_value.first);
const base::Value* split_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, &split_value_in_store));
ASSERT_EQ(dict_value, split_value_in_store);
ASSERT_EQ(4U, dict_value->size());
ASSERT_TRUE(dict_value->HasKey("a"));
ASSERT_TRUE(dict_value->HasKey("b"));
ASSERT_TRUE(dict_value->HasKey("c"));
ASSERT_TRUE(dict_value->HasKey("d"));
ASSERT_EQ(dict_value, stored_split_value.first);
ASSERT_FALSE(RecordedReset());
}
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, EmptyCleared) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_FALSE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(kAtomicPref,
PrefHashStoreTransaction::CLEARED);
mock_pref_hash_store_->SetCheckResult(kSplitPref,
PrefHashStoreTransaction::CLEARED);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(NULL, stored_atomic_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
ASSERT_FALSE(pref_store_contents_.Get(kSplitPref, NULL));
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(NULL, stored_split_value.first);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, InitialValueMigrated) {
base::ListValue* list_value = new base::ListValue;
list_value->Append(base::Value::CreateStringValue("test"));
pref_store_contents_.Set(kAtomicPref, list_value);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
mock_pref_hash_store_->SetCheckResult(kAtomicPref,
PrefHashStoreTransaction::WEAK_LEGACY);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_EQ(NULL, stored_atomic_value.first);
ASSERT_TRUE(RecordedReset());
} else {
const base::Value* atomic_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &atomic_value_in_store));
ASSERT_EQ(list_value, atomic_value_in_store);
ASSERT_EQ(list_value, stored_atomic_value.first);
ASSERT_FALSE(RecordedReset());
}
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, InitialValueUnchangedLegacyId) {
base::StringValue* string_value = new base::StringValue("string value");
pref_store_contents_.Set(kAtomicPref, string_value);
base::DictionaryValue* dict_value = new base::DictionaryValue;
dict_value->SetString("a", "foo");
dict_value->SetInteger("b", 1234);
pref_store_contents_.Set(kSplitPref, dict_value);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(
kAtomicPref, PrefHashStoreTransaction::SECURE_LEGACY);
mock_pref_hash_store_->SetCheckResult(
kSplitPref, PrefHashStoreTransaction::SECURE_LEGACY);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
mock_pref_hash_store_->stored_value(kAtomicPref);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
stored_atomic_value.second);
const base::Value* atomic_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &atomic_value_in_store));
ASSERT_EQ(string_value, atomic_value_in_store);
ASSERT_EQ(string_value, stored_atomic_value.first);
MockPrefHashStore::ValuePtrStrategyPair stored_split_value =
mock_pref_hash_store_->stored_value(kSplitPref);
ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT,
stored_split_value.second);
const base::Value* split_value_in_store;
ASSERT_TRUE(pref_store_contents_.Get(kSplitPref, &split_value_in_store));
ASSERT_EQ(dict_value, split_value_in_store);
ASSERT_EQ(dict_value, stored_split_value.first);
ASSERT_FALSE(RecordedReset());
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, DontResetReportOnly) {
base::Value* int_value1 = base::Value::CreateIntegerValue(1);
base::Value* int_value2 = base::Value::CreateIntegerValue(2);
base::Value* report_only_val = base::Value::CreateIntegerValue(3);
base::DictionaryValue* report_only_split_val = new base::DictionaryValue;
report_only_split_val->SetInteger("a", 1234);
pref_store_contents_.Set(kAtomicPref, int_value1);
pref_store_contents_.Set(kAtomicPref2, int_value2);
pref_store_contents_.Set(kReportOnlyPref, report_only_val);
pref_store_contents_.Set(kReportOnlySplitPref, report_only_split_val);
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref2, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kReportOnlyPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kReportOnlySplitPref, NULL));
mock_pref_hash_store_->SetCheckResult(kAtomicPref,
PrefHashStoreTransaction::CHANGED);
mock_pref_hash_store_->SetCheckResult(kAtomicPref2,
PrefHashStoreTransaction::CHANGED);
mock_pref_hash_store_->SetCheckResult(kReportOnlyPref,
PrefHashStoreTransaction::CHANGED);
mock_pref_hash_store_->SetCheckResult(kReportOnlySplitPref,
PrefHashStoreTransaction::CHANGED);
pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
ASSERT_EQ(arraysize(kTestTrackedPrefs),
mock_pref_hash_store_->checked_paths_count());
ASSERT_EQ(4u, mock_pref_hash_store_->stored_paths_count());
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
ASSERT_TRUE(pref_store_contents_.Get(kReportOnlyPref, NULL));
ASSERT_TRUE(pref_store_contents_.Get(kReportOnlySplitPref, NULL));
ASSERT_EQ(report_only_val,
mock_pref_hash_store_->stored_value(kReportOnlyPref).first);
ASSERT_EQ(report_only_split_val,
mock_pref_hash_store_->stored_value(kReportOnlySplitPref).first);
if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref, NULL));
ASSERT_FALSE(pref_store_contents_.Get(kAtomicPref2, NULL));
ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first);
ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first);
ASSERT_TRUE(RecordedReset());
} else {
const base::Value* value_in_store;
const base::Value* value_in_store2;
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref, &value_in_store));
ASSERT_TRUE(pref_store_contents_.Get(kAtomicPref2, &value_in_store2));
ASSERT_EQ(int_value1, value_in_store);
ASSERT_EQ(int_value1,
mock_pref_hash_store_->stored_value(kAtomicPref).first);
ASSERT_EQ(int_value2, value_in_store2);
ASSERT_EQ(int_value2,
mock_pref_hash_store_->stored_value(kAtomicPref2).first);
ASSERT_FALSE(RecordedReset());
}
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
TEST_P(PrefHashFilterTest, MigrateValuesTest) {
std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration =
GetConfiguration(GetParam());
std::vector<PrefHashFilter::TrackedPreferenceMetadata>
migration_configuration;
for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
configuration.begin();
it != configuration.end();
++it) {
if (it->enforcement_level >= PrefHashFilter::ENFORCE_ON_LOAD)
migration_configuration.push_back(*it);
}
InitializePrefHashFilter(migration_configuration);
scoped_refptr<TestingPrefStore> source(new TestingPrefStore);
scoped_refptr<TestingPrefStore> destination(new TestingPrefStore);
source->SetString(kAtomicPref, "foobar");
source->SetString(kAtomicPref2, "foobar2");
destination->SetString(kAtomicPref2, "foobar2 preexisting");
destination->SetString(kAtomicPref3, "foobar3");
source->SetString(kReportOnlyPref, "helloworld");
mock_pref_hash_store_->SetCheckResult(kAtomicPref,
PrefHashStoreTransaction::UNCHANGED);
mock_pref_hash_store_->SetCheckResult(kAtomicPref2,
PrefHashStoreTransaction::UNCHANGED);
mock_pref_hash_store_->SetCheckResult(kAtomicPref3,
PrefHashStoreTransaction::UNCHANGED);
mock_pref_hash_store_->SetCheckResult(kReportOnlyPref,
PrefHashStoreTransaction::UNCHANGED);
pref_hash_filter_->MigrateValues(source, destination);
ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
std::string value;
ASSERT_FALSE(source->GetValue(kAtomicPref, NULL));
ASSERT_FALSE(source->GetValue(kAtomicPref2, NULL));
ASSERT_FALSE(source->GetValue(kAtomicPref3, NULL));
ASSERT_TRUE(source->GetString(kReportOnlyPref, &value));
ASSERT_EQ("helloworld", value);
ASSERT_TRUE(destination->GetString(kAtomicPref, &value));
ASSERT_EQ("foobar", value);
ASSERT_TRUE(destination->GetString(kAtomicPref2, &value));
ASSERT_EQ("foobar2 preexisting", value);
ASSERT_TRUE(destination->GetString(kAtomicPref3, &value));
ASSERT_EQ("foobar3", value);
ASSERT_FALSE(destination->GetValue(kReportOnlyPref, NULL));
} else {
std::string value;
ASSERT_TRUE(source->GetString(kAtomicPref, &value));
ASSERT_EQ("foobar", value);
ASSERT_TRUE(source->GetString(kAtomicPref2, &value));
ASSERT_EQ("foobar2", value);
ASSERT_FALSE(source->GetString(kAtomicPref3, &value));
ASSERT_TRUE(source->GetString(kReportOnlyPref, &value));
ASSERT_EQ("helloworld", value);
ASSERT_FALSE(destination->GetValue(kAtomicPref, NULL));
ASSERT_TRUE(destination->GetString(kAtomicPref2, &value));
ASSERT_EQ("foobar2 preexisting", value);
ASSERT_TRUE(destination->GetValue(kAtomicPref3, NULL));
ASSERT_FALSE(destination->GetValue(kReportOnlyPref, NULL));
}
EXPECT_FALSE(mock_pref_hash_store_->commit_performed());
}
INSTANTIATE_TEST_CASE_P(
PrefHashFilterTestInstance, PrefHashFilterTest,
testing::Values(PrefHashFilter::NO_ENFORCEMENT,
PrefHashFilter::ENFORCE_ON_LOAD));