| Index: chrome/browser/prefs/pref_hash_store_impl_unittest.cc
|
| diff --git a/chrome/browser/prefs/pref_hash_store_impl_unittest.cc b/chrome/browser/prefs/pref_hash_store_impl_unittest.cc
|
| index 823269157756d7dabdca46d6446d873678e7a314..2ddce469a92f1b785fbe6d7a26636336043fe512 100644
|
| --- a/chrome/browser/prefs/pref_hash_store_impl_unittest.cc
|
| +++ b/chrome/browser/prefs/pref_hash_store_impl_unittest.cc
|
| @@ -14,7 +14,7 @@
|
| #include "chrome/common/pref_names.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| -TEST(PrefHashStoreImplTest, TestCase) {
|
| +TEST(PrefHashStoreImplTest, AtomicHashStoreAndCheck) {
|
| base::StringValue string_1("string1");
|
| base::StringValue string_2("string2");
|
|
|
| @@ -23,7 +23,7 @@ TEST(PrefHashStoreImplTest, TestCase) {
|
|
|
| // 32 NULL bytes is the seed that was used to generate the legacy hash.
|
| PrefHashStoreImpl pref_hash_store(
|
| - "store_id", std::string(32,0), "device_id", &local_state);
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
|
|
| // Only NULL should be trusted in the absence of a hash.
|
| EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE,
|
| @@ -95,3 +95,198 @@ TEST(PrefHashStoreImplTest, TestCase) {
|
| EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE,
|
| pref_hash_store3.CheckValue("new_path", NULL));
|
| }
|
| +
|
| +TEST(PrefHashStoreImplTest, SplitHashStoreAndCheck) {
|
| + base::DictionaryValue dict;
|
| + dict.Set("a", new base::StringValue("to be replaced"));
|
| + dict.Set("b", new base::StringValue("same"));
|
| + dict.Set("o", new base::StringValue("old"));
|
| +
|
| + base::DictionaryValue modified_dict;
|
| + modified_dict.Set("a", new base::StringValue("replaced"));
|
| + modified_dict.Set("b", new base::StringValue("same"));
|
| + modified_dict.Set("c", new base::StringValue("new"));
|
| +
|
| + base::DictionaryValue empty_dict;
|
| +
|
| + TestingPrefServiceSimple local_state;
|
| + PrefHashStoreImpl::RegisterPrefs(local_state.registry());
|
| +
|
| + PrefHashStoreImpl pref_hash_store(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| +
|
| + std::vector<std::string> invalid_keys;
|
| +
|
| + // No hashes stored yet and hashes dictionary is empty (and thus not trusted).
|
| + EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + pref_hash_store.StoreSplitHash("path1", &dict);
|
| +
|
| + // Verify match post storage.
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Verify new path is still unknown.
|
| + EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store.CheckSplitValue("path2", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Verify NULL or empty dicts are declared as having been cleared.
|
| + EXPECT_EQ(PrefHashStore::CLEARED,
|
| + pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| + EXPECT_EQ(PrefHashStore::CLEARED,
|
| + pref_hash_store.CheckSplitValue("path1", &empty_dict,
|
| + &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Verify changes are properly detected.
|
| + EXPECT_EQ(PrefHashStore::CHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &modified_dict,
|
| + &invalid_keys));
|
| + std::vector<std::string> expected_invalid_keys1;
|
| + expected_invalid_keys1.push_back("a");
|
| + expected_invalid_keys1.push_back("c");
|
| + EXPECT_EQ(expected_invalid_keys1, invalid_keys);
|
| + invalid_keys.clear();
|
| +
|
| + // Verify |dict| still matches post check.
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Store hash for |modified_dict|.
|
| + pref_hash_store.StoreSplitHash("path1", &modified_dict);
|
| +
|
| + // Verify |modified_dict| is now the one that verifies correctly.
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &modified_dict,
|
| + &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Verify old dict no longer matches.
|
| + EXPECT_EQ(PrefHashStore::CHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys));
|
| + std::vector<std::string> expected_invalid_keys2;
|
| + expected_invalid_keys2.push_back("a");
|
| + expected_invalid_keys2.push_back("o");
|
| + EXPECT_EQ(expected_invalid_keys2, invalid_keys);
|
| + invalid_keys.clear();
|
| +
|
| + // |pref_hash_store2| should trust its initial hashes dictionary and thus
|
| + // trust new unknown values.
|
| + PrefHashStoreImpl pref_hash_store2(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| + EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store2.CheckSplitValue("new_path", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + {
|
| + // Manually corrupt the hash of hashes for "store_id".
|
| + DictionaryPrefUpdate update(&local_state, prefs::kProfilePreferenceHashes);
|
| + base::DictionaryValue* hash_of_hashes_dict = NULL;
|
| + ASSERT_TRUE(update->GetDictionaryWithoutPathExpansion(
|
| + internals::kHashOfHashesPref, &hash_of_hashes_dict));
|
| + hash_of_hashes_dict->SetString("store_id", std::string(64, 'A'));
|
| + // This shouldn't have increased the number of existing hash of hashes.
|
| + ASSERT_EQ(1U, hash_of_hashes_dict->size());
|
| + }
|
| +
|
| + // |pref_hash_store3| should no longer trust its initial hashes dictionary and
|
| + // thus shouldn't trust unknown values.
|
| + PrefHashStoreImpl pref_hash_store3(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| + EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store3.CheckSplitValue("new_path", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +}
|
| +
|
| +TEST(PrefHashStoreImplTest, EmptyAndNULLSplitDict) {
|
| + base::DictionaryValue empty_dict;
|
| +
|
| + TestingPrefServiceSimple local_state;
|
| + PrefHashStoreImpl::RegisterPrefs(local_state.registry());
|
| +
|
| + PrefHashStoreImpl pref_hash_store(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| +
|
| + // Store hashes for a random dict to be overwritten below.
|
| + base::DictionaryValue initial_dict;
|
| + initial_dict.Set("a", new base::StringValue("foo"));
|
| + pref_hash_store.StoreSplitHash("path1", &initial_dict);
|
| +
|
| + std::vector<std::string> invalid_keys;
|
| +
|
| + // Verify stored empty dictionary matches NULL and empty dictionary back.
|
| + pref_hash_store.StoreSplitHash("path1", &empty_dict);
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &empty_dict,
|
| + &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // Same when storing NULL directly.
|
| + pref_hash_store.StoreSplitHash("path1", NULL);
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckSplitValue("path1", &empty_dict,
|
| + &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +
|
| + // |pref_hash_store2| should trust its initial hashes dictionary (and thus
|
| + // trust new unknown values) even though the last action done on local_state
|
| + // was to clear the hashes for path1 by setting its value to NULL (this is a
|
| + // regression test ensuring that the internal action of clearing some hashes
|
| + // does update the stored hash of hashes).
|
| + PrefHashStoreImpl pref_hash_store2(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| +
|
| + base::DictionaryValue tested_dict;
|
| + tested_dict.Set("a", new base::StringValue("foo"));
|
| + tested_dict.Set("b", new base::StringValue("bar"));
|
| + EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store2.CheckSplitValue("new_path", &tested_dict,
|
| + &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +}
|
| +
|
| +// Test that the PrefHashStore returns TRUSTED_UNKNOWN_VALUE when checking for
|
| +// a split preference even if there is an existing atomic preference's hash
|
| +// stored. There is no point providing a migration path for preferences
|
| +// switching strategies after their initial release as split preferences are
|
| +// turned into split preferences specifically because the atomic hash isn't
|
| +// considered useful.
|
| +TEST(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) {
|
| + base::StringValue string("string1");
|
| +
|
| + base::DictionaryValue dict;
|
| + dict.Set("a", new base::StringValue("foo"));
|
| + dict.Set("d", new base::StringValue("bad"));
|
| + dict.Set("b", new base::StringValue("bar"));
|
| + dict.Set("c", new base::StringValue("baz"));
|
| +
|
| + TestingPrefServiceSimple local_state;
|
| + PrefHashStoreImpl::RegisterPrefs(local_state.registry());
|
| +
|
| + PrefHashStoreImpl pref_hash_store(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| +
|
| + pref_hash_store.StoreHash("path1", &string);
|
| + EXPECT_EQ(PrefHashStore::UNCHANGED,
|
| + pref_hash_store.CheckValue("path1", &string));
|
| +
|
| + // Load a new |pref_hash_store2| in which the hashes dictionary is trusted.
|
| + PrefHashStoreImpl pref_hash_store2(
|
| + "store_id", std::string(32, 0), "device_id", &local_state);
|
| + std::vector<std::string> invalid_keys;
|
| + EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE,
|
| + pref_hash_store2.CheckSplitValue("path1", &dict, &invalid_keys));
|
| + EXPECT_TRUE(invalid_keys.empty());
|
| +}
|
|
|