Move variations component code to variations namespace.
[chromium-blink-merge.git] / chrome / browser / metrics / variations / variations_seed_store_unittest.cc
blob6f42c807bf3360a0ef55cdc61ad66638707468b4
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.
5 #include "chrome/browser/metrics/variations/variations_seed_store.h"
7 #include "base/base64.h"
8 #include "base/prefs/testing_pref_service.h"
9 #include "base/sha1.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/variations/proto/study.pb.h"
14 #include "components/variations/proto/variations_seed.pb.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace chrome_variations {
19 namespace {
21 class TestVariationsSeedStore : public VariationsSeedStore {
22 public:
23 explicit TestVariationsSeedStore(PrefService* local_state)
24 : VariationsSeedStore(local_state) {}
25 virtual ~TestVariationsSeedStore() {}
27 bool StoreSeedForTesting(const std::string& seed_data) {
28 return StoreSeedData(seed_data, std::string(), base::Time::Now(), NULL);
31 virtual VariationsSeedStore::VerifySignatureResult VerifySeedSignature(
32 const std::string& seed_bytes,
33 const std::string& base64_seed_signature) OVERRIDE {
34 return VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE;
37 private:
38 DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore);
42 // Populates |seed| with simple test data. The resulting seed will contain one
43 // study called "test", which contains one experiment called "abc" with
44 // probability weight 100. |seed|'s study field will be cleared before adding
45 // the new study.
46 variations::VariationsSeed CreateTestSeed() {
47 variations::VariationsSeed seed;
48 variations::Study* study = seed.add_study();
49 study->set_name("test");
50 study->set_default_experiment_name("abc");
51 variations::Study_Experiment* experiment = study->add_experiment();
52 experiment->set_name("abc");
53 experiment->set_probability_weight(100);
54 seed.set_serial_number("123");
55 return seed;
58 // Serializes |seed| to protobuf binary format.
59 std::string SerializeSeed(const variations::VariationsSeed& seed) {
60 std::string serialized_seed;
61 seed.SerializeToString(&serialized_seed);
62 return serialized_seed;
65 // Serializes |seed| to base64-encoded protobuf binary format.
66 std::string SerializeSeedBase64(const variations::VariationsSeed& seed,
67 std::string* hash) {
68 std::string serialized_seed = SerializeSeed(seed);
69 if (hash != NULL) {
70 std::string sha1 = base::SHA1HashString(serialized_seed);
71 *hash = base::HexEncode(sha1.data(), sha1.size());
73 std::string base64_serialized_seed;
74 base::Base64Encode(serialized_seed, &base64_serialized_seed);
75 return base64_serialized_seed;
78 // Checks whether the pref with name |pref_name| is at its default value in
79 // |prefs|.
80 bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
81 const char* pref_name) {
82 return prefs.FindPreference(pref_name)->IsDefaultValue();
85 } // namespace
87 TEST(VariationsSeedStoreTest, LoadSeed) {
88 // Store good seed data to test if loading from prefs works.
89 const variations::VariationsSeed seed = CreateTestSeed();
90 std::string seed_hash;
91 const std::string base64_seed = SerializeSeedBase64(seed, &seed_hash);
93 TestingPrefServiceSimple prefs;
94 VariationsSeedStore::RegisterPrefs(prefs.registry());
95 prefs.SetString(prefs::kVariationsSeed, base64_seed);
97 TestVariationsSeedStore seed_store(&prefs);
99 variations::VariationsSeed loaded_seed;
100 // Check that loading a seed without a hash pref set works correctly.
101 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed));
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(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
107 EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsSeed));
109 // Check that loading a seed with the correct hash works.
110 prefs.SetString(prefs::kVariationsSeedHash, seed_hash);
111 loaded_seed.Clear();
112 EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed));
113 EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
115 // Check that loading a bad seed returns false and clears the pref.
116 prefs.ClearPref(prefs::kVariationsSeed);
117 prefs.SetString(prefs::kVariationsSeed, "this should fail");
118 EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
119 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
120 EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
121 EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
122 EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
124 // Check that having no seed in prefs results in a return value of false.
125 prefs.ClearPref(prefs::kVariationsSeed);
126 EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed));
129 TEST(VariationsSeedStoreTest, StoreSeedData) {
130 const variations::VariationsSeed seed = CreateTestSeed();
131 const std::string serialized_seed = SerializeSeed(seed);
133 TestingPrefServiceSimple prefs;
134 VariationsSeedStore::RegisterPrefs(prefs.registry());
136 TestVariationsSeedStore seed_store(&prefs);
138 EXPECT_TRUE(seed_store.StoreSeedForTesting(serialized_seed));
139 // Make sure the pref was actually set.
140 EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
142 std::string loaded_serialized_seed = prefs.GetString(prefs::kVariationsSeed);
143 std::string decoded_serialized_seed;
144 ASSERT_TRUE(base::Base64Decode(loaded_serialized_seed,
145 &decoded_serialized_seed));
146 // Make sure the stored seed from pref is the same as the seed we created.
147 EXPECT_EQ(serialized_seed, decoded_serialized_seed);
149 // Check if trying to store a bad seed leaves the pref unchanged.
150 prefs.ClearPref(prefs::kVariationsSeed);
151 EXPECT_FALSE(seed_store.StoreSeedForTesting("should fail"));
152 EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeed));
155 TEST(VariationsSeedStoreTest, StoreSeedData_ParsedSeed) {
156 const variations::VariationsSeed seed = CreateTestSeed();
157 const std::string serialized_seed = SerializeSeed(seed);
159 TestingPrefServiceSimple prefs;
160 VariationsSeedStore::RegisterPrefs(prefs.registry());
161 TestVariationsSeedStore seed_store(&prefs);
163 variations::VariationsSeed parsed_seed;
164 EXPECT_TRUE(seed_store.StoreSeedData(serialized_seed, std::string(),
165 base::Time::Now(), &parsed_seed));
166 EXPECT_EQ(serialized_seed, SerializeSeed(parsed_seed));
169 TEST(VariationsSeedStoreTest, VerifySeedSignature) {
170 // The below seed and signature pair were generated using the server's
171 // private key.
172 const std::string base64_seed_data =
173 "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p"
174 "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB"
175 "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0"
176 "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf"
177 "MDgQAUoMCghncm91cF8wORAB";
178 const std::string base64_seed_signature =
179 "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
180 "96JkMYgzTkHPwbv7K/CmgA==";
182 std::string seed_data;
183 EXPECT_TRUE(base::Base64Decode(base64_seed_data, &seed_data));
185 VariationsSeedStore seed_store(NULL);
187 #if defined(OS_IOS) || defined(OS_ANDROID)
188 // Signature verification is not enabled on mobile.
189 if (seed_store.VerifySeedSignature(seed_data, base64_seed_signature) ==
190 VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_ENUM_SIZE) {
191 return;
193 #endif
195 // The above inputs should be valid.
196 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_VALID,
197 seed_store.VerifySeedSignature(seed_data, base64_seed_signature));
199 // If there's no signature, the corresponding result should be returned.
200 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_MISSING,
201 seed_store.VerifySeedSignature(seed_data, std::string()));
203 // Using non-base64 encoded value as signature (e.g. seed data) should fail.
204 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_DECODE_FAILED,
205 seed_store.VerifySeedSignature(seed_data, seed_data));
207 // Using a different signature (e.g. the base64 seed data) should fail.
208 #if defined(USE_OPENSSL)
209 // OpenSSL doesn't distinguish signature decode failure from the
210 // signature not matching.
211 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED,
212 seed_store.VerifySeedSignature(seed_data, base64_seed_data));
213 #else
214 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SIGNATURE,
215 seed_store.VerifySeedSignature(seed_data, base64_seed_data));
216 #endif
218 // Using a different seed should not match the signature.
219 seed_data[0] = 'x';
220 EXPECT_EQ(VariationsSeedStore::VARIATIONS_SEED_SIGNATURE_INVALID_SEED,
221 seed_store.VerifySeedSignature(seed_data, base64_seed_signature));
224 } // namespace chrome_variations