Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: chrome/browser/prefs/tracked/pref_hash_store_impl_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698