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