Home | History | Annotate | Download | only in prefs
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/prefs/pref_hash_store_impl.h"
      6 
      7 #include <string>
      8 
      9 #include "base/macros.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/prefs/pref_hash_store_impl.h"
     12 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
     13 #include "chrome/browser/prefs/tracked/dictionary_hash_store_contents.h"
     14 #include "chrome/browser/prefs/tracked/hash_store_contents.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_UNKNOWN_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     // Manually shove in a legacy hash.
     62     (*CreateHashStoreContents()->GetMutableContents())->SetString(
     63         "path1",
     64         "C503FB7C65EEFD5C07185F616A0AA67923C069909933F362022B1F187E73E9A2");
     65 
     66     EXPECT_EQ(PrefHashStoreTransaction::WEAK_LEGACY,
     67               transaction->CheckValue("path1", &dict));
     68     transaction->StoreHash("path1", &dict);
     69     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
     70               transaction->CheckValue("path1", &dict));
     71   }
     72 
     73   ASSERT_FALSE(CreateHashStoreContents()->GetSuperMac().empty());
     74 
     75   {
     76     // |pref_hash_store2| should trust its initial hashes dictionary and thus
     77     // trust new unknown values.
     78     PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
     79     scoped_ptr<PrefHashStoreTransaction> transaction(
     80         pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
     81     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
     82               transaction->CheckValue("new_path", &string_1));
     83     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
     84               transaction->CheckValue("new_path", &string_2));
     85     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
     86               transaction->CheckValue("new_path", NULL));
     87   }
     88 
     89   // Manually corrupt the super MAC.
     90   CreateHashStoreContents()->SetSuperMac(std::string(64, 'A'));
     91 
     92   {
     93     // |pref_hash_store3| should no longer trust its initial hashes dictionary
     94     // and thus shouldn't trust non-NULL unknown values.
     95     PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true);
     96     scoped_ptr<PrefHashStoreTransaction> transaction(
     97         pref_hash_store3.BeginTransaction(CreateHashStoreContents()));
     98     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
     99               transaction->CheckValue("new_path", &string_1));
    100     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
    101               transaction->CheckValue("new_path", &string_2));
    102     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
    103               transaction->CheckValue("new_path", NULL));
    104   }
    105 }
    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 
    255 TEST_F(PrefHashStoreImplTest, SuperMACDisabled) {
    256   base::StringValue string_1("string1");
    257   base::StringValue string_2("string2");
    258 
    259   {
    260     // Pass |use_super_mac| => false.
    261     PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", false);
    262     scoped_ptr<PrefHashStoreTransaction> transaction(
    263         pref_hash_store.BeginTransaction(CreateHashStoreContents()));
    264 
    265     transaction->StoreHash("path1", &string_2);
    266     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    267               transaction->CheckValue("path1", &string_2));
    268   }
    269 
    270   ASSERT_TRUE(CreateHashStoreContents()->GetSuperMac().empty());
    271 
    272   {
    273     PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", false);
    274     scoped_ptr<PrefHashStoreTransaction> transaction(
    275         pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
    276     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
    277               transaction->CheckValue("new_path", &string_1));
    278   }
    279 }
    280 
    281 TEST_F(PrefHashStoreImplTest, SplitHashStoreAndCheck) {
    282   base::DictionaryValue dict;
    283   dict.Set("a", new base::StringValue("to be replaced"));
    284   dict.Set("b", new base::StringValue("same"));
    285   dict.Set("o", new base::StringValue("old"));
    286 
    287   base::DictionaryValue modified_dict;
    288   modified_dict.Set("a", new base::StringValue("replaced"));
    289   modified_dict.Set("b", new base::StringValue("same"));
    290   modified_dict.Set("c", new base::StringValue("new"));
    291 
    292   base::DictionaryValue empty_dict;
    293 
    294   std::vector<std::string> invalid_keys;
    295 
    296   {
    297     PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
    298     scoped_ptr<PrefHashStoreTransaction> transaction(
    299         pref_hash_store.BeginTransaction(CreateHashStoreContents()));
    300 
    301     // No hashes stored yet and hashes dictionary is empty (and thus not
    302     // trusted).
    303     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
    304               transaction->CheckSplitValue("path1", &dict, &invalid_keys));
    305     EXPECT_TRUE(invalid_keys.empty());
    306 
    307     transaction->StoreSplitHash("path1", &dict);
    308 
    309     // Verify match post storage.
    310     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    311               transaction->CheckSplitValue("path1", &dict, &invalid_keys));
    312     EXPECT_TRUE(invalid_keys.empty());
    313 
    314     // Verify new path is still unknown.
    315     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
    316               transaction->CheckSplitValue("path2", &dict, &invalid_keys));
    317     EXPECT_TRUE(invalid_keys.empty());
    318 
    319     // Verify NULL or empty dicts are declared as having been cleared.
    320     EXPECT_EQ(PrefHashStoreTransaction::CLEARED,
    321               transaction->CheckSplitValue("path1", NULL, &invalid_keys));
    322     EXPECT_TRUE(invalid_keys.empty());
    323     EXPECT_EQ(
    324         PrefHashStoreTransaction::CLEARED,
    325         transaction->CheckSplitValue("path1", &empty_dict, &invalid_keys));
    326     EXPECT_TRUE(invalid_keys.empty());
    327 
    328     // Verify changes are properly detected.
    329     EXPECT_EQ(
    330         PrefHashStoreTransaction::CHANGED,
    331         transaction->CheckSplitValue("path1", &modified_dict, &invalid_keys));
    332     std::vector<std::string> expected_invalid_keys1;
    333     expected_invalid_keys1.push_back("a");
    334     expected_invalid_keys1.push_back("c");
    335     expected_invalid_keys1.push_back("o");
    336     EXPECT_EQ(expected_invalid_keys1, invalid_keys);
    337     invalid_keys.clear();
    338 
    339     // Verify |dict| still matches post check.
    340     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    341               transaction->CheckSplitValue("path1", &dict, &invalid_keys));
    342     EXPECT_TRUE(invalid_keys.empty());
    343 
    344     // Store hash for |modified_dict|.
    345     transaction->StoreSplitHash("path1", &modified_dict);
    346 
    347     // Verify |modified_dict| is now the one that verifies correctly.
    348     EXPECT_EQ(
    349         PrefHashStoreTransaction::UNCHANGED,
    350         transaction->CheckSplitValue("path1", &modified_dict, &invalid_keys));
    351     EXPECT_TRUE(invalid_keys.empty());
    352 
    353     // Verify old dict no longer matches.
    354     EXPECT_EQ(PrefHashStoreTransaction::CHANGED,
    355               transaction->CheckSplitValue("path1", &dict, &invalid_keys));
    356     std::vector<std::string> expected_invalid_keys2;
    357     expected_invalid_keys2.push_back("a");
    358     expected_invalid_keys2.push_back("o");
    359     expected_invalid_keys2.push_back("c");
    360     EXPECT_EQ(expected_invalid_keys2, invalid_keys);
    361     invalid_keys.clear();
    362 
    363   }
    364 
    365   {
    366     // |pref_hash_store2| should trust its initial hashes dictionary and thus
    367     // trust new unknown values.
    368     PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
    369     scoped_ptr<PrefHashStoreTransaction> transaction(
    370         pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
    371     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
    372               transaction->CheckSplitValue("new_path", &dict, &invalid_keys));
    373     EXPECT_TRUE(invalid_keys.empty());
    374   }
    375 
    376   // Manually corrupt the super MAC.
    377   CreateHashStoreContents()->SetSuperMac(std::string(64, 'A'));
    378 
    379   {
    380     // |pref_hash_store3| should no longer trust its initial hashes dictionary
    381     // and thus shouldn't trust unknown values.
    382     PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true);
    383     scoped_ptr<PrefHashStoreTransaction> transaction(
    384         pref_hash_store3.BeginTransaction(CreateHashStoreContents()));
    385     EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
    386               transaction->CheckSplitValue("new_path", &dict, &invalid_keys));
    387     EXPECT_TRUE(invalid_keys.empty());
    388   }
    389 }
    390 
    391 TEST_F(PrefHashStoreImplTest, EmptyAndNULLSplitDict) {
    392   base::DictionaryValue empty_dict;
    393 
    394   std::vector<std::string> invalid_keys;
    395 
    396   {
    397     PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
    398     scoped_ptr<PrefHashStoreTransaction> transaction(
    399         pref_hash_store.BeginTransaction(CreateHashStoreContents()));
    400 
    401     // Store hashes for a random dict to be overwritten below.
    402     base::DictionaryValue initial_dict;
    403     initial_dict.Set("a", new base::StringValue("foo"));
    404     transaction->StoreSplitHash("path1", &initial_dict);
    405 
    406     // Verify stored empty dictionary matches NULL and empty dictionary back.
    407     transaction->StoreSplitHash("path1", &empty_dict);
    408     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    409               transaction->CheckSplitValue("path1", NULL, &invalid_keys));
    410     EXPECT_TRUE(invalid_keys.empty());
    411     EXPECT_EQ(
    412         PrefHashStoreTransaction::UNCHANGED,
    413         transaction->CheckSplitValue("path1", &empty_dict, &invalid_keys));
    414     EXPECT_TRUE(invalid_keys.empty());
    415 
    416     // Same when storing NULL directly.
    417     transaction->StoreSplitHash("path1", NULL);
    418     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    419               transaction->CheckSplitValue("path1", NULL, &invalid_keys));
    420     EXPECT_TRUE(invalid_keys.empty());
    421     EXPECT_EQ(
    422         PrefHashStoreTransaction::UNCHANGED,
    423         transaction->CheckSplitValue("path1", &empty_dict, &invalid_keys));
    424     EXPECT_TRUE(invalid_keys.empty());
    425   }
    426 
    427   {
    428     // |pref_hash_store2| should trust its initial hashes dictionary (and thus
    429     // trust new unknown values) even though the last action done was to clear
    430     // the hashes for path1 by setting its value to NULL (this is a regression
    431     // test ensuring that the internal action of clearing some hashes does
    432     // update the stored hash of hashes).
    433     PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
    434     scoped_ptr<PrefHashStoreTransaction> transaction(
    435         pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
    436 
    437     base::DictionaryValue tested_dict;
    438     tested_dict.Set("a", new base::StringValue("foo"));
    439     tested_dict.Set("b", new base::StringValue("bar"));
    440     EXPECT_EQ(
    441         PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
    442         transaction->CheckSplitValue("new_path", &tested_dict, &invalid_keys));
    443     EXPECT_TRUE(invalid_keys.empty());
    444   }
    445 }
    446 
    447 // Test that the PrefHashStore returns TRUSTED_UNKNOWN_VALUE when checking for
    448 // a split preference even if there is an existing atomic preference's hash
    449 // stored. There is no point providing a migration path for preferences
    450 // switching strategies after their initial release as split preferences are
    451 // turned into split preferences specifically because the atomic hash isn't
    452 // considered useful.
    453 TEST_F(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) {
    454   base::StringValue string("string1");
    455 
    456   base::DictionaryValue dict;
    457   dict.Set("a", new base::StringValue("foo"));
    458   dict.Set("d", new base::StringValue("bad"));
    459   dict.Set("b", new base::StringValue("bar"));
    460   dict.Set("c", new base::StringValue("baz"));
    461 
    462   {
    463     PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
    464     scoped_ptr<PrefHashStoreTransaction> transaction(
    465         pref_hash_store.BeginTransaction(CreateHashStoreContents()));
    466 
    467     transaction->StoreHash("path1", &string);
    468     EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
    469               transaction->CheckValue("path1", &string));
    470   }
    471 
    472   {
    473     // Load a new |pref_hash_store2| in which the hashes dictionary is trusted.
    474     PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
    475     scoped_ptr<PrefHashStoreTransaction> transaction(
    476         pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
    477     std::vector<std::string> invalid_keys;
    478     EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
    479               transaction->CheckSplitValue("path1", &dict, &invalid_keys));
    480     EXPECT_TRUE(invalid_keys.empty());
    481   }
    482 }
    483