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

Side by Side Diff: chrome/browser/metrics/variations/variations_seed_store_unittest.cc

Issue 1271123003: Componentize VariationsSeedStore and its unittest (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@componentize_variations_prefs
Patch Set: 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 2014 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/metrics/variations/variations_seed_store.h"
6
7 #include "base/base64.h"
8 #include "base/prefs/testing_pref_service.h"
9 #include "components/metrics/compression_utils.h"
10 #include "components/variations/pref_names.h"
11 #include "components/variations/proto/study.pb.h"
12 #include "components/variations/proto/variations_seed.pb.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace chrome_variations {
16
17 namespace {
18
19 class TestVariationsSeedStore : public VariationsSeedStore {
20 public:
21 explicit TestVariationsSeedStore(PrefService* local_state)
22 : VariationsSeedStore(local_state) {}
23 ~TestVariationsSeedStore() override {}
24
25 bool StoreSeedForTesting(const std::string& seed_data) {
26 return StoreSeedData(seed_data, std::string(), base::Time::Now(), NULL);
27 }
28
29 VariationsSeedStore::VerifySignatureResult VerifySeedSignature(
30 const std::string& seed_bytes,
31 const std::string& base64_seed_signature) override {
32 return VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE;
33 }
34
35 private:
36 DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore);
37 };
38
39
40 // Populates |seed| with simple test data. The resulting seed will contain one
41 // study called "test", which contains one experiment called "abc" with
42 // probability weight 100. |seed|'s study field will be cleared before adding
43 // the new study.
44 variations::VariationsSeed CreateTestSeed() {
45 variations::VariationsSeed seed;
46 variations::Study* study = seed.add_study();
47 study->set_name("test");
48 study->set_default_experiment_name("abc");
49 variations::Study_Experiment* experiment = study->add_experiment();
50 experiment->set_name("abc");
51 experiment->set_probability_weight(100);
52 seed.set_serial_number("123");
53 return seed;
54 }
55
56 // Serializes |seed| to protobuf binary format.
57 std::string SerializeSeed(const variations::VariationsSeed& seed) {
58 std::string serialized_seed;
59 seed.SerializeToString(&serialized_seed);
60 return serialized_seed;
61 }
62
63 // Compresses |data| using Gzip compression and returns the result.
64 std::string Compress(const std::string& data) {
65 std::string compressed;
66 const bool result = metrics::GzipCompress(data, &compressed);
67 EXPECT_TRUE(result);
68 return compressed;
69 }
70
71 // Serializes |seed| to compressed base64-encoded protobuf binary format.
72 std::string SerializeSeedBase64(const variations::VariationsSeed& seed) {
73 std::string serialized_seed = SerializeSeed(seed);
74 std::string base64_serialized_seed;
75 base::Base64Encode(Compress(serialized_seed), &base64_serialized_seed);
76 return base64_serialized_seed;
77 }
78
79 // Checks whether the pref with name |pref_name| is at its default value in
80 // |prefs|.
81 bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
82 const char* pref_name) {
83 return prefs.FindPreference(pref_name)->IsDefaultValue();
84 }
85
86 } // namespace
87
88 TEST(VariationsSeedStoreTest, LoadSeed) {
89 // Store good seed data to test if loading from prefs works.
90 const variations::VariationsSeed seed = CreateTestSeed();
91 const std::string base64_seed = SerializeSeedBase64(seed);
92
93 TestingPrefServiceSimple prefs;
94 VariationsSeedStore::RegisterPrefs(prefs.registry());
95 prefs.SetString(metrics::prefs::kVariationsCompressedSeed, base64_seed);
96
97 TestVariationsSeedStore seed_store(&prefs);
98
99 variations::VariationsSeed loaded_seed;
100 // Check that loading a seed works correctly.
101 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed));
102
103 // Check that the loaded data is the same as the original.
104 EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
105 // Make sure the pref hasn't been changed.
106 EXPECT_FALSE(
107 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsCompressedSeed));
108 EXPECT_EQ(base64_seed,
109 prefs.GetString(metrics::prefs::kVariationsCompressedSeed));
110
111 // Check that loading a bad seed returns false and clears the pref.
112 prefs.SetString(metrics::prefs::kVariationsCompressedSeed,
113 "this should fail");
114 EXPECT_FALSE(
115 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsCompressedSeed));
116 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
117 EXPECT_TRUE(
118 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsCompressedSeed));
119 EXPECT_TRUE(PrefHasDefaultValue(prefs, metrics::prefs::kVariationsSeedDate));
120 EXPECT_TRUE(
121 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsSeedSignature));
122
123 // Check that having no seed in prefs results in a return value of false.
124 prefs.ClearPref(metrics::prefs::kVariationsCompressedSeed);
125 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
126 }
127
128 TEST(VariationsSeedStoreTest, GetInvalidSignature) {
129 const variations::VariationsSeed seed = CreateTestSeed();
130 const std::string base64_seed = SerializeSeedBase64(seed);
131
132 TestingPrefServiceSimple prefs;
133 VariationsSeedStore::RegisterPrefs(prefs.registry());
134 prefs.SetString(metrics::prefs::kVariationsSeed, base64_seed);
135
136 // The below seed and signature pair were generated using the server's
137 // private key.
138 const std::string base64_seed_data =
139 "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p"
140 "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB"
141 "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0"
142 "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf"
143 "MDgQAUoMCghncm91cF8wORAB";
144 const std::string base64_seed_signature =
145 "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
146 "96JkMYgzTkHPwbv7K/CmgA==";
147 const std::string base64_seed_signature_invalid =
148 "AEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
149 "96JkMYgzTkHPwbv7K/CmgA==";
150
151 // Set seed and valid signature in prefs.
152 prefs.SetString(metrics::prefs::kVariationsSeed, base64_seed_data);
153 prefs.SetString(metrics::prefs::kVariationsSeedSignature,
154 base64_seed_signature);
155
156 VariationsSeedStore seed_store(&prefs);
157 variations::VariationsSeed loaded_seed;
158 seed_store.LoadSeed(&loaded_seed);
159 std::string invalid_signature = seed_store.GetInvalidSignature();
160 // Valid signature so we get an empty string.
161 EXPECT_EQ(std::string(), invalid_signature);
162
163 prefs.SetString(metrics::prefs::kVariationsSeedSignature,
164 base64_seed_signature_invalid);
165 seed_store.LoadSeed(&loaded_seed);
166 // Invalid signature, so we should get the signature itself, except on mobile
167 // where we should get an empty string because verification is not enabled.
168 invalid_signature = seed_store.GetInvalidSignature();
169 #if defined(OS_IOS) || defined(OS_ANDROID)
170 EXPECT_EQ(std::string(), invalid_signature);
171 #else
172 EXPECT_EQ(base64_seed_signature_invalid, invalid_signature);
173 #endif
174
175 prefs.SetString(metrics::prefs::kVariationsSeedSignature, std::string());
176 seed_store.LoadSeed(&loaded_seed);
177 invalid_signature = seed_store.GetInvalidSignature();
178 // Empty signature, not considered invalid.
179 EXPECT_EQ(std::string(), invalid_signature);
180 }
181
182 TEST(VariationsSeedStoreTest, StoreSeedData) {
183 const variations::VariationsSeed seed = CreateTestSeed();
184 const std::string serialized_seed = SerializeSeed(seed);
185
186 TestingPrefServiceSimple prefs;
187 VariationsSeedStore::RegisterPrefs(prefs.registry());
188
189 TestVariationsSeedStore seed_store(&prefs);
190
191 EXPECT_TRUE(seed_store.StoreSeedForTesting(serialized_seed));
192 // Make sure the pref was actually set.
193 EXPECT_FALSE(
194 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsCompressedSeed));
195
196 std::string loaded_compressed_seed =
197 prefs.GetString(metrics::prefs::kVariationsCompressedSeed);
198 std::string decoded_compressed_seed;
199 ASSERT_TRUE(base::Base64Decode(loaded_compressed_seed,
200 &decoded_compressed_seed));
201 // Make sure the stored seed from pref is the same as the seed we created.
202 EXPECT_EQ(Compress(serialized_seed), decoded_compressed_seed);
203
204 // Check if trying to store a bad seed leaves the pref unchanged.
205 prefs.ClearPref(metrics::prefs::kVariationsCompressedSeed);
206 EXPECT_FALSE(seed_store.StoreSeedForTesting("should fail"));
207 EXPECT_TRUE(
208 PrefHasDefaultValue(prefs, metrics::prefs::kVariationsCompressedSeed));
209 }
210
211 TEST(VariationsSeedStoreTest, StoreSeedData_ParsedSeed) {
212 const variations::VariationsSeed seed = CreateTestSeed();
213 const std::string serialized_seed = SerializeSeed(seed);
214
215 TestingPrefServiceSimple prefs;
216 VariationsSeedStore::RegisterPrefs(prefs.registry());
217 TestVariationsSeedStore seed_store(&prefs);
218
219 variations::VariationsSeed parsed_seed;
220 EXPECT_TRUE(seed_store.StoreSeedData(serialized_seed, std::string(),
221 base::Time::Now(), &parsed_seed));
222 EXPECT_EQ(serialized_seed, SerializeSeed(parsed_seed));
223 }
224
225 TEST(VariationsSeedStoreTest, StoreSeedData_CountryCode) {
226 TestingPrefServiceSimple prefs;
227 VariationsSeedStore::RegisterPrefs(prefs.registry());
228 TestVariationsSeedStore seed_store(&prefs);
229
230 variations::VariationsSeed seed = CreateTestSeed();
231 seed.set_country_code("test_country");
232 EXPECT_TRUE(seed_store.StoreSeedData(SerializeSeed(seed), std::string(),
233 base::Time::Now(), nullptr));
234 EXPECT_EQ("test_country",
235 prefs.GetString(metrics::prefs::kVariationsCountry));
236 }
237
238 TEST(VariationsSeedStoreTest, VerifySeedSignature) {
239 // The below seed and signature pair were generated using the server's
240 // private key.
241 const std::string base64_seed_data =
242 "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p"
243 "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB"
244 "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0"
245 "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf"
246 "MDgQAUoMCghncm91cF8wORAB";
247 const std::string base64_seed_signature =
248 "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
249 "96JkMYgzTkHPwbv7K/CmgA==";
250
251 std::string seed_data;
252 EXPECT_TRUE(base::Base64Decode(base64_seed_data, &seed_data));
253
254 VariationsSeedStore seed_store(NULL);
255
256 #if defined(OS_IOS) || defined(OS_ANDROID)
257 // Signature verification is not enabled on mobile.
258 if (seed_store.VerifySeedSignature(seed_data, base64_seed_signature) ==
259 VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE) {
260 return;
261 }
262 #endif
263
264 // The above inputs should be valid.
265 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_VALID,
266 seed_store.VerifySeedSignature(seed_data, base64_seed_signature));
267
268 // If there's no signature, the corresponding result should be returned.
269 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_MISSING,
270 seed_store.VerifySeedSignature(seed_data, std::string()));
271
272 // Using non-base64 encoded value as signature (e.g. seed data) should fail.
273 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_DECODE_FAILED,
274 seed_store.VerifySeedSignature(seed_data, seed_data));
275
276 // Using a different signature (e.g. the base64 seed data) should fail.
277 #if defined(USE_OPENSSL)
278 // OpenSSL doesn't distinguish signature decode failure from the
279 // signature not matching.
280 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED,
281 seed_store.VerifySeedSignature(seed_data, base64_seed_data));
282 #else
283 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SIGNATURE,
284 seed_store.VerifySeedSignature(seed_data, base64_seed_data));
285 #endif
286
287 // Using a different seed should not match the signature.
288 seed_data[0] = 'x';
289 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED,
290 seed_store.VerifySeedSignature(seed_data, base64_seed_signature));
291 }
292
293 } // namespace chrome_variations
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698