| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prefs/pref_hash_store_impl.h" | 5 #include "chrome/browser/prefs/pref_hash_store_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| 11 #include "chrome/browser/prefs/pref_hash_store_impl.h" | 11 #include "chrome/browser/prefs/pref_hash_store_impl.h" |
| 12 #include "chrome/browser/prefs/pref_hash_store_transaction.h" | 12 #include "chrome/browser/prefs/pref_hash_store_transaction.h" |
| 13 #include "chrome/browser/prefs/tracked/dictionary_hash_store_contents.h" |
| 13 #include "chrome/browser/prefs/tracked/hash_store_contents.h" | 14 #include "chrome/browser/prefs/tracked/hash_store_contents.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 16 |
| 16 class MockHashStoreContents : public HashStoreContents { | |
| 17 public: | |
| 18 // Keep the data separate from the API implementation so that it can be owned | |
| 19 // by the test and reused. The API implementation is owned by the | |
| 20 // PrefHashStoreImpl. | |
| 21 struct Data { | |
| 22 Data() : commit_performed(false) {} | |
| 23 | |
| 24 // Returns the current value of |commit_performed| and resets it to false | |
| 25 // immediately after. | |
| 26 bool GetCommitPerformedAndReset() { | |
| 27 bool current_commit_performed = commit_performed; | |
| 28 commit_performed = false; | |
| 29 return current_commit_performed; | |
| 30 } | |
| 31 | |
| 32 scoped_ptr<base::DictionaryValue> contents; | |
| 33 std::string super_mac; | |
| 34 bool commit_performed; | |
| 35 }; | |
| 36 | |
| 37 explicit MockHashStoreContents(Data* data) : data_(data) {} | |
| 38 | |
| 39 // HashStoreContents implementation | |
| 40 virtual std::string hash_store_id() const OVERRIDE { return "store_id"; } | |
| 41 | |
| 42 virtual void Reset() OVERRIDE { | |
| 43 data_->contents.reset(); | |
| 44 data_->super_mac = ""; | |
| 45 } | |
| 46 | |
| 47 virtual bool IsInitialized() const OVERRIDE { return data_->contents; } | |
| 48 | |
| 49 virtual const base::DictionaryValue* GetContents() const OVERRIDE { | |
| 50 return data_->contents.get(); | |
| 51 } | |
| 52 | |
| 53 virtual scoped_ptr<MutableDictionary> GetMutableContents() OVERRIDE { | |
| 54 return scoped_ptr<MutableDictionary>(new MockMutableDictionary(data_)); | |
| 55 } | |
| 56 | |
| 57 virtual std::string GetSuperMac() const OVERRIDE { return data_->super_mac; } | |
| 58 | |
| 59 virtual void SetSuperMac(const std::string& super_mac) OVERRIDE { | |
| 60 data_->super_mac = super_mac; | |
| 61 } | |
| 62 | |
| 63 virtual void CommitPendingWrite() OVERRIDE { | |
| 64 EXPECT_FALSE(data_->commit_performed); | |
| 65 data_->commit_performed = true; | |
| 66 } | |
| 67 | |
| 68 private: | |
| 69 class MockMutableDictionary : public MutableDictionary { | |
| 70 public: | |
| 71 explicit MockMutableDictionary(Data* data) : data_(data) {} | |
| 72 | |
| 73 // MutableDictionary implementation | |
| 74 virtual base::DictionaryValue* operator->() OVERRIDE { | |
| 75 if (!data_->contents) | |
| 76 data_->contents.reset(new base::DictionaryValue); | |
| 77 return data_->contents.get(); | |
| 78 } | |
| 79 | |
| 80 private: | |
| 81 Data* data_; | |
| 82 DISALLOW_COPY_AND_ASSIGN(MockMutableDictionary); | |
| 83 }; | |
| 84 | |
| 85 Data* data_; | |
| 86 | |
| 87 DISALLOW_COPY_AND_ASSIGN(MockHashStoreContents); | |
| 88 }; | |
| 89 | |
| 90 class PrefHashStoreImplTest : public testing::Test { | 17 class PrefHashStoreImplTest : public testing::Test { |
| 91 protected: | 18 protected: |
| 92 scoped_ptr<HashStoreContents> CreateHashStoreContents() { | 19 scoped_ptr<HashStoreContents> CreateHashStoreContents() { |
| 93 return scoped_ptr<HashStoreContents>( | 20 return scoped_ptr<HashStoreContents>( |
| 94 new MockHashStoreContents(&hash_store_data_)); | 21 new DictionaryHashStoreContents(&pref_store_contents_)); |
| 95 } | 22 } |
| 96 | 23 |
| 97 MockHashStoreContents::Data hash_store_data_; | 24 private: |
| 25 base::DictionaryValue pref_store_contents_; |
| 98 }; | 26 }; |
| 99 | 27 |
| 100 TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) { | 28 TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) { |
| 101 base::StringValue string_1("string1"); | 29 base::StringValue string_1("string1"); |
| 102 base::StringValue string_2("string2"); | 30 base::StringValue string_2("string2"); |
| 103 | 31 |
| 104 { | 32 { |
| 105 // 32 NULL bytes is the seed that was used to generate the legacy hash. | 33 // 32 NULL bytes is the seed that was used to generate the legacy hash. |
| 106 PrefHashStoreImpl pref_hash_store( | 34 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 107 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 108 scoped_ptr<PrefHashStoreTransaction> transaction( | 35 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 109 pref_hash_store.BeginTransaction()); | 36 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 110 | 37 |
| 111 // Only NULL should be trusted in the absence of a hash. | 38 // Only NULL should be trusted in the absence of a hash. |
| 112 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 39 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 113 transaction->CheckValue("path1", &string_1)); | 40 transaction->CheckValue("path1", &string_1)); |
| 114 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 41 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 115 transaction->CheckValue("path1", NULL)); | 42 transaction->CheckValue("path1", NULL)); |
| 116 | 43 |
| 117 transaction->StoreHash("path1", &string_1); | 44 transaction->StoreHash("path1", &string_1); |
| 118 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, | 45 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 119 transaction->CheckValue("path1", &string_1)); | 46 transaction->CheckValue("path1", &string_1)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 134 // Manually shove in a legacy hash. | 61 // Manually shove in a legacy hash. |
| 135 (*CreateHashStoreContents()->GetMutableContents())->SetString( | 62 (*CreateHashStoreContents()->GetMutableContents())->SetString( |
| 136 "path1", | 63 "path1", |
| 137 "C503FB7C65EEFD5C07185F616A0AA67923C069909933F362022B1F187E73E9A2"); | 64 "C503FB7C65EEFD5C07185F616A0AA67923C069909933F362022B1F187E73E9A2"); |
| 138 | 65 |
| 139 EXPECT_EQ(PrefHashStoreTransaction::WEAK_LEGACY, | 66 EXPECT_EQ(PrefHashStoreTransaction::WEAK_LEGACY, |
| 140 transaction->CheckValue("path1", &dict)); | 67 transaction->CheckValue("path1", &dict)); |
| 141 transaction->StoreHash("path1", &dict); | 68 transaction->StoreHash("path1", &dict); |
| 142 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, | 69 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 143 transaction->CheckValue("path1", &dict)); | 70 transaction->CheckValue("path1", &dict)); |
| 144 | |
| 145 // Test that the |pref_hash_store| flushes its changes on request post | |
| 146 // transaction. | |
| 147 transaction.reset(); | |
| 148 pref_hash_store.CommitPendingWrite(); | |
| 149 EXPECT_TRUE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 150 } | 71 } |
| 151 | 72 |
| 152 ASSERT_FALSE(CreateHashStoreContents()->GetSuperMac().empty()); | 73 ASSERT_FALSE(CreateHashStoreContents()->GetSuperMac().empty()); |
| 153 | 74 |
| 154 { | 75 { |
| 155 // |pref_hash_store2| should trust its initial hashes dictionary and thus | 76 // |pref_hash_store2| should trust its initial hashes dictionary and thus |
| 156 // trust new unknown values. | 77 // trust new unknown values. |
| 157 PrefHashStoreImpl pref_hash_store2( | 78 PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true); |
| 158 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 159 scoped_ptr<PrefHashStoreTransaction> transaction( | 79 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 160 pref_hash_store2.BeginTransaction()); | 80 pref_hash_store2.BeginTransaction(CreateHashStoreContents())); |
| 161 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 81 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 162 transaction->CheckValue("new_path", &string_1)); | 82 transaction->CheckValue("new_path", &string_1)); |
| 163 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 83 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 164 transaction->CheckValue("new_path", &string_2)); | 84 transaction->CheckValue("new_path", &string_2)); |
| 165 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 85 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 166 transaction->CheckValue("new_path", NULL)); | 86 transaction->CheckValue("new_path", NULL)); |
| 167 | |
| 168 // Test that |pref_hash_store2| doesn't flush its contents to disk when it | |
| 169 // didn't change. | |
| 170 transaction.reset(); | |
| 171 pref_hash_store2.CommitPendingWrite(); | |
| 172 EXPECT_FALSE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 173 } | 87 } |
| 174 | 88 |
| 175 // Manually corrupt the super MAC. | 89 // Manually corrupt the super MAC. |
| 176 hash_store_data_.super_mac = std::string(64, 'A'); | 90 CreateHashStoreContents()->SetSuperMac(std::string(64, 'A')); |
| 177 | 91 |
| 178 { | 92 { |
| 179 // |pref_hash_store3| should no longer trust its initial hashes dictionary | 93 // |pref_hash_store3| should no longer trust its initial hashes dictionary |
| 180 // and thus shouldn't trust non-NULL unknown values. | 94 // and thus shouldn't trust non-NULL unknown values. |
| 181 PrefHashStoreImpl pref_hash_store3( | 95 PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true); |
| 182 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 183 scoped_ptr<PrefHashStoreTransaction> transaction( | 96 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 184 pref_hash_store3.BeginTransaction()); | 97 pref_hash_store3.BeginTransaction(CreateHashStoreContents())); |
| 185 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 98 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 186 transaction->CheckValue("new_path", &string_1)); | 99 transaction->CheckValue("new_path", &string_1)); |
| 187 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 100 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 188 transaction->CheckValue("new_path", &string_2)); | 101 transaction->CheckValue("new_path", &string_2)); |
| 189 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 102 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 190 transaction->CheckValue("new_path", NULL)); | 103 transaction->CheckValue("new_path", NULL)); |
| 191 | |
| 192 // Test that |pref_hash_store3| doesn't flush its contents to disk when it | |
| 193 // didn't change. | |
| 194 transaction.reset(); | |
| 195 pref_hash_store3.CommitPendingWrite(); | |
| 196 EXPECT_FALSE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 197 } | 104 } |
| 198 } | 105 } |
| 199 | 106 |
| 107 TEST_F(PrefHashStoreImplTest, ImportExportOperations) { |
| 108 base::StringValue string_1("string1"); |
| 109 base::StringValue string_2("string2"); |
| 110 |
| 111 // Initial state: no super MAC. |
| 112 { |
| 113 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 114 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 115 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 116 ASSERT_FALSE(transaction->IsSuperMACValid()); |
| 117 |
| 118 ASSERT_FALSE(transaction->HasHash("path1")); |
| 119 |
| 120 // Storing a hash will stamp the super MAC. |
| 121 transaction->StoreHash("path1", &string_1); |
| 122 |
| 123 ASSERT_TRUE(transaction->HasHash("path1")); |
| 124 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 125 transaction->CheckValue("path1", &string_1)); |
| 126 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, |
| 127 transaction->CheckValue("path1", &string_2)); |
| 128 } |
| 129 |
| 130 // Make a copy of the stored hash for future use. |
| 131 const base::Value* hash = NULL; |
| 132 ASSERT_TRUE(CreateHashStoreContents()->GetContents()->Get("path1", &hash)); |
| 133 scoped_ptr<base::Value> path_1_string_1_hash_copy(hash->DeepCopy()); |
| 134 hash = NULL; |
| 135 |
| 136 // Verify that the super MAC was stamped. |
| 137 { |
| 138 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 139 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 140 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 141 ASSERT_TRUE(transaction->IsSuperMACValid()); |
| 142 ASSERT_TRUE(transaction->HasHash("path1")); |
| 143 |
| 144 // Clearing the hash should preserve validity. |
| 145 transaction->ClearHash("path1"); |
| 146 |
| 147 // The effects of the clear should be immediately visible. |
| 148 ASSERT_FALSE(transaction->HasHash("path1")); |
| 149 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 150 transaction->CheckValue("path1", NULL)); |
| 151 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 152 transaction->CheckValue("path1", &string_1)); |
| 153 } |
| 154 |
| 155 // Verify that validity was preserved and that the clear took effect. |
| 156 { |
| 157 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 158 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 159 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 160 ASSERT_TRUE(transaction->IsSuperMACValid()); |
| 161 ASSERT_FALSE(transaction->HasHash("path1")); |
| 162 } |
| 163 |
| 164 // Invalidate the super MAC. |
| 165 CreateHashStoreContents()->SetSuperMac(std::string()); |
| 166 |
| 167 { |
| 168 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 169 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 170 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 171 ASSERT_FALSE(transaction->IsSuperMACValid()); |
| 172 ASSERT_FALSE(transaction->HasHash("path1")); |
| 173 |
| 174 // An import should preserve invalidity. |
| 175 transaction->ImportHash("path1", path_1_string_1_hash_copy.get()); |
| 176 |
| 177 ASSERT_TRUE(transaction->HasHash("path1")); |
| 178 |
| 179 // The imported hash should be usable for validating the original value. |
| 180 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 181 transaction->CheckValue("path1", &string_1)); |
| 182 } |
| 183 |
| 184 // Verify that invalidity was preserved and that the import took effect. |
| 185 { |
| 186 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 187 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 188 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 189 ASSERT_FALSE(transaction->IsSuperMACValid()); |
| 190 ASSERT_TRUE(transaction->HasHash("path1")); |
| 191 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 192 transaction->CheckValue("path1", &string_1)); |
| 193 |
| 194 // After clearing the hash, non-null values are UNTRUSTED_UNKNOWN. |
| 195 transaction->ClearHash("path1"); |
| 196 |
| 197 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 198 transaction->CheckValue("path1", NULL)); |
| 199 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 200 transaction->CheckValue("path1", &string_1)); |
| 201 } |
| 202 |
| 203 { |
| 204 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 205 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 206 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 207 ASSERT_FALSE(transaction->IsSuperMACValid()); |
| 208 |
| 209 // Test StampSuperMac. |
| 210 transaction->StampSuperMac(); |
| 211 } |
| 212 |
| 213 // Verify that the store is now valid. |
| 214 { |
| 215 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 216 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 217 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 218 ASSERT_TRUE(transaction->IsSuperMACValid()); |
| 219 |
| 220 // Store the hash of a different value to test an "over-import". |
| 221 transaction->StoreHash("path1", &string_2); |
| 222 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, |
| 223 transaction->CheckValue("path1", &string_1)); |
| 224 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 225 transaction->CheckValue("path1", &string_2)); |
| 226 } |
| 227 |
| 228 { |
| 229 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 230 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 231 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 232 ASSERT_TRUE(transaction->IsSuperMACValid()); |
| 233 |
| 234 // "Over-import". An import should preserve validity. |
| 235 transaction->ImportHash("path1", path_1_string_1_hash_copy.get()); |
| 236 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 237 transaction->CheckValue("path1", &string_1)); |
| 238 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, |
| 239 transaction->CheckValue("path1", &string_2)); |
| 240 } |
| 241 |
| 242 // Verify that validity was preserved and the "over-import" took effect. |
| 243 { |
| 244 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 245 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 246 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 247 ASSERT_TRUE(transaction->IsSuperMACValid()); |
| 248 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 249 transaction->CheckValue("path1", &string_1)); |
| 250 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, |
| 251 transaction->CheckValue("path1", &string_2)); |
| 252 } |
| 253 } |
| 254 |
| 200 TEST_F(PrefHashStoreImplTest, SuperMACDisabled) { | 255 TEST_F(PrefHashStoreImplTest, SuperMACDisabled) { |
| 201 base::StringValue string_1("string1"); | 256 base::StringValue string_1("string1"); |
| 202 base::StringValue string_2("string2"); | 257 base::StringValue string_2("string2"); |
| 203 | 258 |
| 204 { | 259 { |
| 205 // Pass |use_super_mac| => false. | 260 // Pass |use_super_mac| => false. |
| 206 PrefHashStoreImpl pref_hash_store( | 261 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", false); |
| 207 std::string(32, 0), "device_id", CreateHashStoreContents(), false); | |
| 208 scoped_ptr<PrefHashStoreTransaction> transaction( | 262 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 209 pref_hash_store.BeginTransaction()); | 263 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 210 | 264 |
| 211 transaction->StoreHash("path1", &string_2); | 265 transaction->StoreHash("path1", &string_2); |
| 212 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, | 266 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 213 transaction->CheckValue("path1", &string_2)); | 267 transaction->CheckValue("path1", &string_2)); |
| 214 } | 268 } |
| 215 | 269 |
| 216 ASSERT_TRUE(CreateHashStoreContents()->GetSuperMac().empty()); | 270 ASSERT_TRUE(CreateHashStoreContents()->GetSuperMac().empty()); |
| 217 | 271 |
| 218 { | 272 { |
| 219 PrefHashStoreImpl pref_hash_store2( | 273 PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", false); |
| 220 std::string(32, 0), "device_id", CreateHashStoreContents(), false); | |
| 221 scoped_ptr<PrefHashStoreTransaction> transaction( | 274 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 222 pref_hash_store2.BeginTransaction()); | 275 pref_hash_store2.BeginTransaction(CreateHashStoreContents())); |
| 223 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 276 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 224 transaction->CheckValue("new_path", &string_1)); | 277 transaction->CheckValue("new_path", &string_1)); |
| 225 } | 278 } |
| 226 } | 279 } |
| 227 | 280 |
| 228 TEST_F(PrefHashStoreImplTest, SplitHashStoreAndCheck) { | 281 TEST_F(PrefHashStoreImplTest, SplitHashStoreAndCheck) { |
| 229 base::DictionaryValue dict; | 282 base::DictionaryValue dict; |
| 230 dict.Set("a", new base::StringValue("to be replaced")); | 283 dict.Set("a", new base::StringValue("to be replaced")); |
| 231 dict.Set("b", new base::StringValue("same")); | 284 dict.Set("b", new base::StringValue("same")); |
| 232 dict.Set("o", new base::StringValue("old")); | 285 dict.Set("o", new base::StringValue("old")); |
| 233 | 286 |
| 234 base::DictionaryValue modified_dict; | 287 base::DictionaryValue modified_dict; |
| 235 modified_dict.Set("a", new base::StringValue("replaced")); | 288 modified_dict.Set("a", new base::StringValue("replaced")); |
| 236 modified_dict.Set("b", new base::StringValue("same")); | 289 modified_dict.Set("b", new base::StringValue("same")); |
| 237 modified_dict.Set("c", new base::StringValue("new")); | 290 modified_dict.Set("c", new base::StringValue("new")); |
| 238 | 291 |
| 239 base::DictionaryValue empty_dict; | 292 base::DictionaryValue empty_dict; |
| 240 | 293 |
| 241 std::vector<std::string> invalid_keys; | 294 std::vector<std::string> invalid_keys; |
| 242 | 295 |
| 243 { | 296 { |
| 244 PrefHashStoreImpl pref_hash_store( | 297 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 245 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 246 scoped_ptr<PrefHashStoreTransaction> transaction( | 298 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 247 pref_hash_store.BeginTransaction()); | 299 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 248 | 300 |
| 249 // No hashes stored yet and hashes dictionary is empty (and thus not | 301 // No hashes stored yet and hashes dictionary is empty (and thus not |
| 250 // trusted). | 302 // trusted). |
| 251 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 303 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 252 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); | 304 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); |
| 253 EXPECT_TRUE(invalid_keys.empty()); | 305 EXPECT_TRUE(invalid_keys.empty()); |
| 254 | 306 |
| 255 transaction->StoreSplitHash("path1", &dict); | 307 transaction->StoreSplitHash("path1", &dict); |
| 256 | 308 |
| 257 // Verify match post storage. | 309 // Verify match post storage. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 // Verify old dict no longer matches. | 353 // Verify old dict no longer matches. |
| 302 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, | 354 EXPECT_EQ(PrefHashStoreTransaction::CHANGED, |
| 303 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); | 355 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); |
| 304 std::vector<std::string> expected_invalid_keys2; | 356 std::vector<std::string> expected_invalid_keys2; |
| 305 expected_invalid_keys2.push_back("a"); | 357 expected_invalid_keys2.push_back("a"); |
| 306 expected_invalid_keys2.push_back("o"); | 358 expected_invalid_keys2.push_back("o"); |
| 307 expected_invalid_keys2.push_back("c"); | 359 expected_invalid_keys2.push_back("c"); |
| 308 EXPECT_EQ(expected_invalid_keys2, invalid_keys); | 360 EXPECT_EQ(expected_invalid_keys2, invalid_keys); |
| 309 invalid_keys.clear(); | 361 invalid_keys.clear(); |
| 310 | 362 |
| 311 // Test that the |pref_hash_store| flushes its changes on request. | |
| 312 transaction.reset(); | |
| 313 pref_hash_store.CommitPendingWrite(); | |
| 314 EXPECT_TRUE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 315 } | 363 } |
| 316 | 364 |
| 317 { | 365 { |
| 318 // |pref_hash_store2| should trust its initial hashes dictionary and thus | 366 // |pref_hash_store2| should trust its initial hashes dictionary and thus |
| 319 // trust new unknown values. | 367 // trust new unknown values. |
| 320 PrefHashStoreImpl pref_hash_store2( | 368 PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true); |
| 321 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 322 scoped_ptr<PrefHashStoreTransaction> transaction( | 369 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 323 pref_hash_store2.BeginTransaction()); | 370 pref_hash_store2.BeginTransaction(CreateHashStoreContents())); |
| 324 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 371 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 325 transaction->CheckSplitValue("new_path", &dict, &invalid_keys)); | 372 transaction->CheckSplitValue("new_path", &dict, &invalid_keys)); |
| 326 EXPECT_TRUE(invalid_keys.empty()); | 373 EXPECT_TRUE(invalid_keys.empty()); |
| 327 | |
| 328 // Test that |pref_hash_store2| doesn't flush its contents to disk when it | |
| 329 // didn't change. | |
| 330 transaction.reset(); | |
| 331 pref_hash_store2.CommitPendingWrite(); | |
| 332 EXPECT_FALSE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 333 } | 374 } |
| 334 | 375 |
| 335 // Manually corrupt the super MAC. | 376 // Manually corrupt the super MAC. |
| 336 hash_store_data_.super_mac = std::string(64, 'A'); | 377 CreateHashStoreContents()->SetSuperMac(std::string(64, 'A')); |
| 337 | 378 |
| 338 { | 379 { |
| 339 // |pref_hash_store3| should no longer trust its initial hashes dictionary | 380 // |pref_hash_store3| should no longer trust its initial hashes dictionary |
| 340 // and thus shouldn't trust unknown values. | 381 // and thus shouldn't trust unknown values. |
| 341 PrefHashStoreImpl pref_hash_store3( | 382 PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true); |
| 342 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 343 scoped_ptr<PrefHashStoreTransaction> transaction( | 383 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 344 pref_hash_store3.BeginTransaction()); | 384 pref_hash_store3.BeginTransaction(CreateHashStoreContents())); |
| 345 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, | 385 EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE, |
| 346 transaction->CheckSplitValue("new_path", &dict, &invalid_keys)); | 386 transaction->CheckSplitValue("new_path", &dict, &invalid_keys)); |
| 347 EXPECT_TRUE(invalid_keys.empty()); | 387 EXPECT_TRUE(invalid_keys.empty()); |
| 348 | |
| 349 // Test that |pref_hash_store3| doesn't flush its contents to disk when it | |
| 350 // didn't change. | |
| 351 transaction.reset(); | |
| 352 pref_hash_store3.CommitPendingWrite(); | |
| 353 EXPECT_FALSE(hash_store_data_.GetCommitPerformedAndReset()); | |
| 354 } | 388 } |
| 355 } | 389 } |
| 356 | 390 |
| 357 TEST_F(PrefHashStoreImplTest, EmptyAndNULLSplitDict) { | 391 TEST_F(PrefHashStoreImplTest, EmptyAndNULLSplitDict) { |
| 358 base::DictionaryValue empty_dict; | 392 base::DictionaryValue empty_dict; |
| 359 | 393 |
| 360 std::vector<std::string> invalid_keys; | 394 std::vector<std::string> invalid_keys; |
| 361 | 395 |
| 362 { | 396 { |
| 363 PrefHashStoreImpl pref_hash_store( | 397 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 364 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 365 scoped_ptr<PrefHashStoreTransaction> transaction( | 398 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 366 pref_hash_store.BeginTransaction()); | 399 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 367 | 400 |
| 368 // Store hashes for a random dict to be overwritten below. | 401 // Store hashes for a random dict to be overwritten below. |
| 369 base::DictionaryValue initial_dict; | 402 base::DictionaryValue initial_dict; |
| 370 initial_dict.Set("a", new base::StringValue("foo")); | 403 initial_dict.Set("a", new base::StringValue("foo")); |
| 371 transaction->StoreSplitHash("path1", &initial_dict); | 404 transaction->StoreSplitHash("path1", &initial_dict); |
| 372 | 405 |
| 373 // Verify stored empty dictionary matches NULL and empty dictionary back. | 406 // Verify stored empty dictionary matches NULL and empty dictionary back. |
| 374 transaction->StoreSplitHash("path1", &empty_dict); | 407 transaction->StoreSplitHash("path1", &empty_dict); |
| 375 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, | 408 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 376 transaction->CheckSplitValue("path1", NULL, &invalid_keys)); | 409 transaction->CheckSplitValue("path1", NULL, &invalid_keys)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 390 transaction->CheckSplitValue("path1", &empty_dict, &invalid_keys)); | 423 transaction->CheckSplitValue("path1", &empty_dict, &invalid_keys)); |
| 391 EXPECT_TRUE(invalid_keys.empty()); | 424 EXPECT_TRUE(invalid_keys.empty()); |
| 392 } | 425 } |
| 393 | 426 |
| 394 { | 427 { |
| 395 // |pref_hash_store2| should trust its initial hashes dictionary (and thus | 428 // |pref_hash_store2| should trust its initial hashes dictionary (and thus |
| 396 // trust new unknown values) even though the last action done was to clear | 429 // trust new unknown values) even though the last action done was to clear |
| 397 // the hashes for path1 by setting its value to NULL (this is a regression | 430 // the hashes for path1 by setting its value to NULL (this is a regression |
| 398 // test ensuring that the internal action of clearing some hashes does | 431 // test ensuring that the internal action of clearing some hashes does |
| 399 // update the stored hash of hashes). | 432 // update the stored hash of hashes). |
| 400 PrefHashStoreImpl pref_hash_store2( | 433 PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true); |
| 401 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 402 scoped_ptr<PrefHashStoreTransaction> transaction( | 434 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 403 pref_hash_store2.BeginTransaction()); | 435 pref_hash_store2.BeginTransaction(CreateHashStoreContents())); |
| 404 | 436 |
| 405 base::DictionaryValue tested_dict; | 437 base::DictionaryValue tested_dict; |
| 406 tested_dict.Set("a", new base::StringValue("foo")); | 438 tested_dict.Set("a", new base::StringValue("foo")); |
| 407 tested_dict.Set("b", new base::StringValue("bar")); | 439 tested_dict.Set("b", new base::StringValue("bar")); |
| 408 EXPECT_EQ( | 440 EXPECT_EQ( |
| 409 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 441 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 410 transaction->CheckSplitValue("new_path", &tested_dict, &invalid_keys)); | 442 transaction->CheckSplitValue("new_path", &tested_dict, &invalid_keys)); |
| 411 EXPECT_TRUE(invalid_keys.empty()); | 443 EXPECT_TRUE(invalid_keys.empty()); |
| 412 } | 444 } |
| 413 } | 445 } |
| 414 | 446 |
| 415 // Test that the PrefHashStore returns TRUSTED_UNKNOWN_VALUE when checking for | 447 // Test that the PrefHashStore returns TRUSTED_UNKNOWN_VALUE when checking for |
| 416 // a split preference even if there is an existing atomic preference's hash | 448 // a split preference even if there is an existing atomic preference's hash |
| 417 // stored. There is no point providing a migration path for preferences | 449 // stored. There is no point providing a migration path for preferences |
| 418 // switching strategies after their initial release as split preferences are | 450 // switching strategies after their initial release as split preferences are |
| 419 // turned into split preferences specifically because the atomic hash isn't | 451 // turned into split preferences specifically because the atomic hash isn't |
| 420 // considered useful. | 452 // considered useful. |
| 421 TEST_F(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) { | 453 TEST_F(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) { |
| 422 base::StringValue string("string1"); | 454 base::StringValue string("string1"); |
| 423 | 455 |
| 424 base::DictionaryValue dict; | 456 base::DictionaryValue dict; |
| 425 dict.Set("a", new base::StringValue("foo")); | 457 dict.Set("a", new base::StringValue("foo")); |
| 426 dict.Set("d", new base::StringValue("bad")); | 458 dict.Set("d", new base::StringValue("bad")); |
| 427 dict.Set("b", new base::StringValue("bar")); | 459 dict.Set("b", new base::StringValue("bar")); |
| 428 dict.Set("c", new base::StringValue("baz")); | 460 dict.Set("c", new base::StringValue("baz")); |
| 429 | 461 |
| 430 { | 462 { |
| 431 PrefHashStoreImpl pref_hash_store( | 463 PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true); |
| 432 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 433 scoped_ptr<PrefHashStoreTransaction> transaction( | 464 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 434 pref_hash_store.BeginTransaction()); | 465 pref_hash_store.BeginTransaction(CreateHashStoreContents())); |
| 435 | 466 |
| 436 transaction->StoreHash("path1", &string); | 467 transaction->StoreHash("path1", &string); |
| 437 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, | 468 EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED, |
| 438 transaction->CheckValue("path1", &string)); | 469 transaction->CheckValue("path1", &string)); |
| 439 } | 470 } |
| 440 | 471 |
| 441 { | 472 { |
| 442 // Load a new |pref_hash_store2| in which the hashes dictionary is trusted. | 473 // Load a new |pref_hash_store2| in which the hashes dictionary is trusted. |
| 443 PrefHashStoreImpl pref_hash_store2( | 474 PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true); |
| 444 std::string(32, 0), "device_id", CreateHashStoreContents(), true); | |
| 445 scoped_ptr<PrefHashStoreTransaction> transaction( | 475 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 446 pref_hash_store2.BeginTransaction()); | 476 pref_hash_store2.BeginTransaction(CreateHashStoreContents())); |
| 447 std::vector<std::string> invalid_keys; | 477 std::vector<std::string> invalid_keys; |
| 448 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, | 478 EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE, |
| 449 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); | 479 transaction->CheckSplitValue("path1", &dict, &invalid_keys)); |
| 450 EXPECT_TRUE(invalid_keys.empty()); | 480 EXPECT_TRUE(invalid_keys.empty()); |
| 451 } | 481 } |
| 452 } | 482 } |
| OLD | NEW |