| OLD | NEW |
| (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 "components/user_prefs/tracked/pref_hash_calculator.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/macros.h" | |
| 11 #include "base/memory/ptr_util.h" | |
| 12 #include "base/strings/string_util.h" | |
| 13 #include "base/values.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 | |
| 16 TEST(PrefHashCalculatorTest, TestCurrentAlgorithm) { | |
| 17 base::Value string_value_1("string value 1"); | |
| 18 base::Value string_value_2("string value 2"); | |
| 19 base::DictionaryValue dictionary_value_1; | |
| 20 dictionary_value_1.SetInteger("int value", 1); | |
| 21 dictionary_value_1.Set("nested empty map", new base::DictionaryValue); | |
| 22 base::DictionaryValue dictionary_value_1_equivalent; | |
| 23 dictionary_value_1_equivalent.SetInteger("int value", 1); | |
| 24 base::DictionaryValue dictionary_value_2; | |
| 25 dictionary_value_2.SetInteger("int value", 2); | |
| 26 | |
| 27 PrefHashCalculator calc1("seed1", "deviceid", "legacydeviceid"); | |
| 28 PrefHashCalculator calc1_dup("seed1", "deviceid", "legacydeviceid"); | |
| 29 PrefHashCalculator calc2("seed2", "deviceid", "legacydeviceid"); | |
| 30 PrefHashCalculator calc3("seed1", "deviceid2", "legacydeviceid"); | |
| 31 | |
| 32 // Two calculators with same seed produce same hash. | |
| 33 ASSERT_EQ(calc1.Calculate("pref_path", &string_value_1), | |
| 34 calc1_dup.Calculate("pref_path", &string_value_1)); | |
| 35 ASSERT_EQ(PrefHashCalculator::VALID, | |
| 36 calc1_dup.Validate("pref_path", &string_value_1, | |
| 37 calc1.Calculate("pref_path", &string_value_1))); | |
| 38 | |
| 39 // Different seeds, different hashes. | |
| 40 ASSERT_NE(calc1.Calculate("pref_path", &string_value_1), | |
| 41 calc2.Calculate("pref_path", &string_value_1)); | |
| 42 ASSERT_EQ(PrefHashCalculator::INVALID, | |
| 43 calc2.Validate("pref_path", &string_value_1, | |
| 44 calc1.Calculate("pref_path", &string_value_1))); | |
| 45 | |
| 46 // Different device IDs, different hashes. | |
| 47 ASSERT_NE(calc1.Calculate("pref_path", &string_value_1), | |
| 48 calc3.Calculate("pref_path", &string_value_1)); | |
| 49 | |
| 50 // Different values, different hashes. | |
| 51 ASSERT_NE(calc1.Calculate("pref_path", &string_value_1), | |
| 52 calc1.Calculate("pref_path", &string_value_2)); | |
| 53 | |
| 54 // Different paths, different hashes. | |
| 55 ASSERT_NE(calc1.Calculate("pref_path", &string_value_1), | |
| 56 calc1.Calculate("pref_path_2", &string_value_1)); | |
| 57 | |
| 58 // Works for dictionaries. | |
| 59 ASSERT_EQ(calc1.Calculate("pref_path", &dictionary_value_1), | |
| 60 calc1.Calculate("pref_path", &dictionary_value_1)); | |
| 61 ASSERT_NE(calc1.Calculate("pref_path", &dictionary_value_1), | |
| 62 calc1.Calculate("pref_path", &dictionary_value_2)); | |
| 63 | |
| 64 // Empty dictionary children are pruned. | |
| 65 ASSERT_EQ(calc1.Calculate("pref_path", &dictionary_value_1), | |
| 66 calc1.Calculate("pref_path", &dictionary_value_1_equivalent)); | |
| 67 | |
| 68 // NULL value is supported. | |
| 69 ASSERT_FALSE(calc1.Calculate("pref_path", NULL).empty()); | |
| 70 } | |
| 71 | |
| 72 // Tests the output against a known value to catch unexpected algorithm changes. | |
| 73 // The test hashes below must NEVER be updated, the serialization algorithm used | |
| 74 // must always be able to generate data that will produce these exact hashes. | |
| 75 TEST(PrefHashCalculatorTest, CatchHashChanges) { | |
| 76 static const char kSeed[] = "0123456789ABCDEF0123456789ABCDEF"; | |
| 77 static const char kDeviceId[] = "test_device_id1"; | |
| 78 | |
| 79 std::unique_ptr<base::Value> null_value = base::Value::CreateNullValue(); | |
| 80 std::unique_ptr<base::Value> bool_value(new base::Value(false)); | |
| 81 std::unique_ptr<base::Value> int_value(new base::Value(1234567890)); | |
| 82 std::unique_ptr<base::Value> double_value(new base::Value(123.0987654321)); | |
| 83 std::unique_ptr<base::Value> string_value( | |
| 84 new base::Value("testing with special chars:\n<>{}:^^@#$\\/")); | |
| 85 | |
| 86 // For legacy reasons, we have to support pruning of empty lists/dictionaries | |
| 87 // and nested empty ists/dicts in the hash generation algorithm. | |
| 88 std::unique_ptr<base::DictionaryValue> nested_empty_dict( | |
| 89 new base::DictionaryValue); | |
| 90 nested_empty_dict->Set("a", new base::DictionaryValue); | |
| 91 nested_empty_dict->Set("b", new base::ListValue); | |
| 92 std::unique_ptr<base::ListValue> nested_empty_list(new base::ListValue); | |
| 93 nested_empty_list->Append(base::MakeUnique<base::DictionaryValue>()); | |
| 94 nested_empty_list->Append(base::MakeUnique<base::ListValue>()); | |
| 95 nested_empty_list->Append(nested_empty_dict->CreateDeepCopy()); | |
| 96 | |
| 97 // A dictionary with an empty dictionary, an empty list, and nested empty | |
| 98 // dictionaries/lists in it. | |
| 99 std::unique_ptr<base::DictionaryValue> dict_value(new base::DictionaryValue); | |
| 100 dict_value->Set("a", new base::Value("foo")); | |
| 101 dict_value->Set("d", new base::ListValue); | |
| 102 dict_value->Set("b", new base::DictionaryValue); | |
| 103 dict_value->Set("c", new base::Value("baz")); | |
| 104 dict_value->Set("e", nested_empty_dict.release()); | |
| 105 dict_value->Set("f", nested_empty_list.release()); | |
| 106 | |
| 107 std::unique_ptr<base::ListValue> list_value(new base::ListValue); | |
| 108 list_value->AppendBoolean(true); | |
| 109 list_value->AppendInteger(100); | |
| 110 list_value->AppendDouble(1.0); | |
| 111 | |
| 112 ASSERT_EQ(base::Value::Type::NONE, null_value->GetType()); | |
| 113 ASSERT_EQ(base::Value::Type::BOOLEAN, bool_value->GetType()); | |
| 114 ASSERT_EQ(base::Value::Type::INTEGER, int_value->GetType()); | |
| 115 ASSERT_EQ(base::Value::Type::DOUBLE, double_value->GetType()); | |
| 116 ASSERT_EQ(base::Value::Type::STRING, string_value->GetType()); | |
| 117 ASSERT_EQ(base::Value::Type::DICTIONARY, dict_value->GetType()); | |
| 118 ASSERT_EQ(base::Value::Type::LIST, list_value->GetType()); | |
| 119 | |
| 120 // Test every value type independently. Intentionally omits Type::BINARY which | |
| 121 // isn't even allowed in JSONWriter's input. | |
| 122 static const char kExpectedNullValue[] = | |
| 123 "82A9F3BBC7F9FF84C76B033C854E79EEB162783FA7B3E99FF9372FA8E12C44F7"; | |
| 124 EXPECT_EQ(PrefHashCalculator::VALID, | |
| 125 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 126 .Validate("pref.path", null_value.get(), kExpectedNullValue)); | |
| 127 | |
| 128 static const char kExpectedBooleanValue[] = | |
| 129 "A520D8F43EA307B0063736DC9358C330539D0A29417580514C8B9862632C4CCC"; | |
| 130 EXPECT_EQ( | |
| 131 PrefHashCalculator::VALID, | |
| 132 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 133 .Validate("pref.path", bool_value.get(), kExpectedBooleanValue)); | |
| 134 | |
| 135 static const char kExpectedIntegerValue[] = | |
| 136 "8D60DA1F10BF5AA29819D2D66D7CCEF9AABC5DA93C11A0D2BD21078D63D83682"; | |
| 137 EXPECT_EQ(PrefHashCalculator::VALID, | |
| 138 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 139 .Validate("pref.path", int_value.get(), kExpectedIntegerValue)); | |
| 140 | |
| 141 static const char kExpectedDoubleValue[] = | |
| 142 "C9D94772516125BEEDAE68C109D44BC529E719EE020614E894CC7FB4098C545D"; | |
| 143 EXPECT_EQ( | |
| 144 PrefHashCalculator::VALID, | |
| 145 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 146 .Validate("pref.path", double_value.get(), kExpectedDoubleValue)); | |
| 147 | |
| 148 static const char kExpectedStringValue[] = | |
| 149 "05ACCBD3B05C45C36CD06190F63EC577112311929D8380E26E5F13182EB68318"; | |
| 150 EXPECT_EQ( | |
| 151 PrefHashCalculator::VALID, | |
| 152 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 153 .Validate("pref.path", string_value.get(), kExpectedStringValue)); | |
| 154 | |
| 155 static const char kExpectedDictValue[] = | |
| 156 "7A84DCC710D796C771F789A4DA82C952095AA956B6F1667EE42D0A19ECAA3C4A"; | |
| 157 EXPECT_EQ(PrefHashCalculator::VALID, | |
| 158 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 159 .Validate("pref.path", dict_value.get(), kExpectedDictValue)); | |
| 160 | |
| 161 static const char kExpectedListValue[] = | |
| 162 "8D5A25972DF5AE20D041C780E7CA54E40F614AD53513A0724EE8D62D4F992740"; | |
| 163 EXPECT_EQ(PrefHashCalculator::VALID, | |
| 164 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 165 .Validate("pref.path", list_value.get(), kExpectedListValue)); | |
| 166 | |
| 167 // Also test every value type together in the same dictionary. | |
| 168 base::DictionaryValue everything; | |
| 169 everything.Set("null", null_value.release()); | |
| 170 everything.Set("bool", bool_value.release()); | |
| 171 everything.Set("int", int_value.release()); | |
| 172 everything.Set("double", double_value.release()); | |
| 173 everything.Set("string", string_value.release()); | |
| 174 everything.Set("list", list_value.release()); | |
| 175 everything.Set("dict", dict_value.release()); | |
| 176 static const char kExpectedEverythingValue[] = | |
| 177 "B97D09BE7005693574DCBDD03D8D9E44FB51F4008B73FB56A49A9FA671A1999B"; | |
| 178 EXPECT_EQ(PrefHashCalculator::VALID, | |
| 179 PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") | |
| 180 .Validate("pref.path", &everything, kExpectedEverythingValue)); | |
| 181 } | |
| 182 | |
| 183 TEST(PrefHashCalculatorTest, TestCompatibilityWithLegacyDeviceId) { | |
| 184 static const char kSeed[] = "0123456789ABCDEF0123456789ABCDEF"; | |
| 185 static const char kNewDeviceId[] = "new_test_device_id1"; | |
| 186 static const char kLegacyDeviceId[] = "test_device_id1"; | |
| 187 | |
| 188 // As in PrefHashCalculatorTest.CatchHashChanges. | |
| 189 const base::Value string_value("testing with special chars:\n<>{}:^^@#$\\/"); | |
| 190 static const char kExpectedValue[] = | |
| 191 "05ACCBD3B05C45C36CD06190F63EC577112311929D8380E26E5F13182EB68318"; | |
| 192 | |
| 193 EXPECT_EQ(PrefHashCalculator::VALID_SECURE_LEGACY, | |
| 194 PrefHashCalculator(kSeed, kNewDeviceId, kLegacyDeviceId) | |
| 195 .Validate("pref.path", &string_value, kExpectedValue)); | |
| 196 } | |
| OLD | NEW |