blob: 35df71e92e72bce04b5437dd85dd372f6c78e106 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2020 The Chromium Authors
Karthika Paia264586a2020-10-27 23:32:012// 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/variations/variations_test_utils.h"
6
Karthika Paia264586a2020-10-27 23:32:017#include "base/base64.h"
Caitlin Fischer6920a082021-06-29 05:25:248#include "base/command_line.h"
Karthika Paia264586a2020-10-27 23:32:019#include "base/feature_list.h"
Roger McFarlane3da6db2732021-10-06 13:41:0410#include "components/metrics/clean_exit_beacon.h"
11#include "components/metrics/metrics_pref_names.h"
12#include "components/prefs/pref_service.h"
Steven Holtef08a3362022-09-15 07:33:0613#include "components/variations/client_filterable_state.h"
Luc Nguyen1180c662022-02-08 20:38:5914#include "components/variations/field_trial_config/fieldtrial_testing_config.h"
Roger McFarlane3da6db2732021-10-06 13:41:0415#include "components/variations/pref_names.h"
Karthika Paia264586a2020-10-27 23:32:0116#include "components/variations/proto/client_variations.pb.h"
Karthika Paia264586a2020-10-27 23:32:0117#include "components/variations/variations_associated_data.h"
Caitlin Fischer6920a082021-06-29 05:25:2418#include "components/variations/variations_switches.h"
Caitlin Fischerd7651aed2021-07-13 03:20:4019#include "third_party/zlib/google/compression_utils.h"
Karthika Paia264586a2020-10-27 23:32:0120
21namespace variations {
Roger McFarlane3da6db2732021-10-06 13:41:0422namespace {
Karthika Paia264586a2020-10-27 23:32:0123
Steven Holtee34ff1a2022-09-15 00:06:5624// kTestSeed is a simple VariationsSeed containing:
25// serial_number: "test"
26// study: {
27// name: "UMA-Uniformity-Trial-50-Percent"
28// consistency: PERMANENT
29// experiment: {
30// name: "default"
31// probability_weight: 1
32// }
33// experiment: {
34// name: "group_01"
35// probability_weight: 1
36// }
37// }
38
39const char* kTestSeed_StudyNames[] = {"UMA-Uniformity-Trial-50-Percent"};
Roger McFarlane3da6db2732021-10-06 13:41:0440
41const char kTestSeed_Base64UncompressedData[] =
Steven Holtee34ff1a2022-09-15 00:06:5642 "CgR0ZXN0Ej4KH1VNQS1Vbmlmb3JtaXR5LVRyaWFsLTUwLVBlcmNlbnQ4AUoLCgdkZWZhdWx0EA"
43 "FKDAoIZ3JvdXBfMDEQAQ==";
Caitlin Fischer7b55ee12021-07-14 16:05:2944
Roger McFarlane3da6db2732021-10-06 13:41:0445const char kTestSeed_Base64CompressedData[] =
Steven Holtee34ff1a2022-09-15 00:06:5646 "H4sIAAAAAAAA/+JiKUktLhGy45IP9XXUDc3LTMsvys0sqdQNKcpMzNE1NdANSC1KTs0rsWD04u"
47 "ZiT0lNSyzNKRFg9OLh4kgvyi8tiDcwFGAEBAAA//90/JgERgAAAA==";
Caitlin Fischer6920a082021-06-29 05:25:2448
Roger McFarlane3da6db2732021-10-06 13:41:0449const char kTestSeed_Base64Signature[] =
Steven Holtee34ff1a2022-09-15 00:06:5650 "MEUCIQD5AEAzk5qEuE3xOZl+xSZR15Ac1RJpsXMiou7i5W0sMAIgRn++ngh03HaMGC+Pjl9NOu"
51 "Doxf83qsSwycF2PSS1nYQ=";
Caitlin Fischer6920a082021-06-29 05:25:2452
Roger McFarlane3da6db2732021-10-06 13:41:0453const char* kCrashingSeed_StudyNames[] = {"CrashingStudy"};
54
Steven Holtee34ff1a2022-09-15 00:06:5655// kCrashingSeed is a VariationsSeed that triggers a crash for testing:
56// serial_number: "35ed2d9e354b414befdf930a734094019c0162f1"
57// study: {
58// name: "CrashingStudy"
59// consistency: PERMANENT
60// experiment: {
61// name: "EnabledLaunch"
62// probability_weight: 100
63// feature_association: {
64// enable_feature: "ForceFieldTrialSetupCrashForTesting"
65// }
66// }
67// experiment: {
68// name: "ForcedOn_ForceFieldTrialSetupCrashForTesting"
69// probability_weight: 0
70// feature_association: {
71// forcing_feature_on: "ForceFieldTrialSetupCrashForTesting"
72// }
73// }
74// experiment: {
75// name: "ForcedOff_ForceFieldTrialSetupCrashForTesting"
76// probability_weight: 0
77// feature_association: {
78// forcing_feature_off: "ForceFieldTrialSetupCrashForTesting"
79// }
80// }
81// filter: {
82// min_version: "91.*"
83// channel: CANARY
84// channel: DEV
85// channel: BETA
86// channel: STABLE
87// platform: PLATFORM_ANDROID
88// platform: PLATFORM_IOS
89// platform: PLATFORM_ANDROID_WEBVIEW
90// platform: PLATFORM_WINDOWS
91// platform: PLATFORM_MAC
92// platform: PLATFORM_LINUX
93// platform: PLATFORM_CHROMEOS
94// platform: PLATFORM_CHROMEOS_LACROS
95// }
96// }
97// version: "hash/4aa56a1dc30dfc767615248d6fee29830198b276"
98
Roger McFarlane3da6db2732021-10-06 13:41:0499const char kCrashingSeed_Base64UncompressedData[] =
100 "CigzNWVkMmQ5ZTM1NGI0MTRiZWZkZjkzMGE3MzQwOTQwMTljMDE2MmYxEp4CCg1DcmFzaGluZ1"
101 "N0dWR5OAFKOAoNRW5hYmxlZExhdW5jaBBkYiUKI0ZvcmNlRmllbGRUcmlhbFNldHVwQ3Jhc2hG"
102 "b3JUZXN0aW5nSlcKLEZvcmNlZE9uX0ZvcmNlRmllbGRUcmlhbFNldHVwQ3Jhc2hGb3JUZXN0aW"
103 "5nEABiJRojRm9yY2VGaWVsZFRyaWFsU2V0dXBDcmFzaEZvclRlc3RpbmdKWAotRm9yY2VkT2Zm"
104 "X0ZvcmNlRmllbGRUcmlhbFNldHVwQ3Jhc2hGb3JUZXN0aW5nEABiJSIjRm9yY2VGaWVsZFRyaW"
105 "FsU2V0dXBDcmFzaEZvclRlc3RpbmdSHhIEOTEuKiAAIAEgAiADKAQoBSgGKAAoASgCKAMoCSIt"
106 "aGFzaC80YWE1NmExZGMzMGRmYzc2NzYxNTI0OGQ2ZmVlMjk4MzAxOThiMjc2";
107
108const char kCrashingSeed_Base64CompressedData[] =
109 "H4sIAAAAAAAAAI3QwUvDMBTH8babwgKDsaMHKZNBEKdJk6bJWbbDEAQ30JskeS+2UKp07cF/"
110 "Zn+rZfgH9Py+73P4ESpyhAwMilw6yaXDAMEIZgshmZGMG8+4ygJfnhMyf27tqayar0PXw6+"
111 "O95rMt411NcKL7RtfLsCtyd3uu/W4q7CGY1vZ+oBd/"
112 "3P5HA5HPHUDsH8nD5cMXpvPEf0icuubUfAH2fzDIYyVV2Pkt9vl1PDH+zRK4zRJJ3RKr+"
113 "g1jWhMEzqhs9WmHPonaW2uLAcvGARfqELxPJMaVEDMjBbDotplhfoDs9NLbnoBAAA=";
114
115const char kCrashingSeed_Base64Signature[] =
116 "MEQCIEn1+VsBfNA93dxzpk+BLhdO91kMQnofxfTK5Uo8vDi8AiAnTCFCIPgEGWNOKzuKfNWn6"
117 "emB6pnGWjSTbI/pvfxHnw==";
118
Luc Nguyen1180c662022-02-08 20:38:59119// Create mock testing config equivalent to:
120// {
121// "UnitTest": [
122// {
123// "platforms": [
124// "android",
125// "android_weblayer",
126// "android_webview",
127// "chromeos",
128// "chromeos_lacros",
129// "fuchsia",
130// "ios",
131// "linux",
132// "mac",
133// "windows"
134// ],
135// "experiments": [
136// {
137// "name": "Enabled",
138// "params": {
139// "x": "1"
140// },
141// "enable_features": [
142// "UnitTestEnabled"
143// ]
144// }
145// ]
146// }
147// ]
148// }
149
150const Study::Platform array_kFieldTrialConfig_platforms_0[] = {
151 Study::PLATFORM_ANDROID,
152 Study::PLATFORM_ANDROID_WEBLAYER,
153 Study::PLATFORM_ANDROID_WEBVIEW,
154 Study::PLATFORM_CHROMEOS,
155 Study::PLATFORM_CHROMEOS_LACROS,
156 Study::PLATFORM_FUCHSIA,
157 Study::PLATFORM_IOS,
158 Study::PLATFORM_LINUX,
159 Study::PLATFORM_MAC,
160 Study::PLATFORM_WINDOWS,
161};
162
163const char* enable_features_0[] = {"UnitTestEnabled"};
164const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_0[] = {
165 {
166 "x",
167 "1",
168 },
169};
170
171const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = {
172 {/*name=*/"Enabled",
173 /*platforms=*/array_kFieldTrialConfig_platforms_0,
174 /*platforms_size=*/10,
175 /*form_factors=*/{},
176 /*form_factors_size=*/0,
177 /*is_low_end_device=*/absl::nullopt,
178 /*min_os_version=*/nullptr,
179 /*params=*/array_kFieldTrialConfig_params_0,
180 /*params_size=*/1,
181 /*enable_features=*/enable_features_0,
182 /*enable_features_size=*/1,
183 /*disable_features=*/nullptr,
184 /*disable_features_size=*/0,
185 /*forcing_flag=*/nullptr,
186 /*override_ui_string=*/nullptr,
187 /*override_ui_string_size=*/0},
188};
189
190const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {
191 {/*name=*/"UnitTest",
192 /*experiments=*/array_kFieldTrialConfig_experiments_0,
193 /*experiments_size=*/1},
194};
195
Roger McFarlane3da6db2732021-10-06 13:41:04196} // namespace
197
198const SignedSeedData kTestSeedData{
199 kTestSeed_StudyNames, kTestSeed_Base64UncompressedData,
200 kTestSeed_Base64CompressedData, kTestSeed_Base64Signature};
201
202const SignedSeedData kCrashingSeedData{
203 kCrashingSeed_StudyNames, kCrashingSeed_Base64UncompressedData,
204 kCrashingSeed_Base64CompressedData, kCrashingSeed_Base64Signature};
205
206const SignedSeedPrefKeys kSafeSeedPrefKeys{prefs::kVariationsSafeCompressedSeed,
207 prefs::kVariationsSafeSeedSignature};
208
209const SignedSeedPrefKeys kRegularSeedPrefKeys{prefs::kVariationsCompressedSeed,
210 prefs::kVariationsSeedSignature};
211
212SignedSeedData::SignedSeedData(base::span<const char*> in_study_names,
213 const char* in_base64_uncompressed_data,
214 const char* in_base64_compressed_data,
215 const char* in_base64_signature)
216 : study_names(std::move(in_study_names)),
217 base64_uncompressed_data(in_base64_uncompressed_data),
218 base64_compressed_data(in_base64_compressed_data),
219 base64_signature(in_base64_signature) {}
220
221SignedSeedData::~SignedSeedData() = default;
222
223SignedSeedData::SignedSeedData(const SignedSeedData&) = default;
224SignedSeedData::SignedSeedData(SignedSeedData&&) = default;
225SignedSeedData& SignedSeedData::operator=(const SignedSeedData&) = default;
226SignedSeedData& SignedSeedData::operator=(SignedSeedData&&) = default;
Caitlin Fischerd7651aed2021-07-13 03:20:40227
Caitlin Fischer6920a082021-06-29 05:25:24228void DisableTestingConfig() {
229 base::CommandLine::ForCurrentProcess()->AppendSwitch(
230 switches::kDisableFieldTrialTestingConfig);
231}
232
Luc Nguyen1180c662022-02-08 20:38:59233void EnableTestingConfig() {
234 base::CommandLine::ForCurrentProcess()->AppendSwitch(
235 switches::kEnableFieldTrialTestingConfig);
236}
237
Karthika Paia264586a2020-10-27 23:32:01238bool ExtractVariationIds(const std::string& variations,
239 std::set<VariationID>* variation_ids,
240 std::set<VariationID>* trigger_ids) {
241 std::string serialized_proto;
242 if (!base::Base64Decode(variations, &serialized_proto))
243 return false;
244 ClientVariations proto;
245 if (!proto.ParseFromString(serialized_proto))
246 return false;
247 for (int i = 0; i < proto.variation_id_size(); ++i)
248 variation_ids->insert(proto.variation_id(i));
249 for (int i = 0; i < proto.trigger_variation_id_size(); ++i)
250 trigger_ids->insert(proto.trigger_variation_id(i));
251 return true;
252}
253
254scoped_refptr<base::FieldTrial> CreateTrialAndAssociateId(
255 const std::string& trial_name,
256 const std::string& default_group_name,
257 IDCollectionKey key,
258 VariationID id) {
259 AssociateGoogleVariationID(key, trial_name, default_group_name, id);
260 scoped_refptr<base::FieldTrial> trial(
261 base::FieldTrialList::CreateFieldTrial(trial_name, default_group_name));
262 DCHECK(trial);
263
264 if (trial) {
265 // Ensure the trial is registered under the correct key so we can look it
266 // up.
Steven Holtef1551602022-09-03 06:38:38267 trial->Activate();
Karthika Paia264586a2020-10-27 23:32:01268 }
269
270 return trial;
271}
272
Roger McFarlane3da6db2732021-10-06 13:41:04273void SimulateCrash(PrefService* local_state) {
274 local_state->SetBoolean(metrics::prefs::kStabilityExitedCleanly, false);
275 metrics::CleanExitBeacon::SkipCleanShutdownStepsForTesting();
276}
277
278void WriteSeedData(PrefService* local_state,
279 const SignedSeedData& seed_data,
280 const SignedSeedPrefKeys& pref_keys) {
281 local_state->SetString(pref_keys.base64_compressed_data_key,
282 seed_data.base64_compressed_data);
283 local_state->SetString(pref_keys.base64_signature_key,
284 seed_data.base64_signature);
285 local_state->CommitPendingWrite();
286}
287
288bool FieldTrialListHasAllStudiesFrom(const SignedSeedData& seed_data) {
289 return base::ranges::all_of(seed_data.study_names, [](const char* study) {
290 return base::FieldTrialList::TrialExists(study);
291 });
292}
293
Luc Nguyen1180c662022-02-08 20:38:59294void ResetVariations() {
295 testing::ClearAllVariationIDs();
296 testing::ClearAllVariationParams();
297}
298
299const FieldTrialTestingConfig kTestingConfig = {
300 array_kFieldTrialConfig_studies,
301 1,
302};
303
Steven Holtef08a3362022-09-15 07:33:06304std::unique_ptr<ClientFilterableState> CreateDummyClientFilterableState() {
305 auto client_state = std::make_unique<ClientFilterableState>(
306 base::BindOnce([] { return false; }));
307 client_state->locale = "en-CA";
308 client_state->reference_date = base::Time::Now();
309 client_state->version = base::Version("20.0.0.0");
310 client_state->channel = Study::STABLE;
311 client_state->form_factor = Study::PHONE;
312 client_state->platform = Study::PLATFORM_ANDROID;
313 return client_state;
314}
315
Steven Holtea84bc222022-09-29 07:11:46316MockEntropyProviders::MockEntropyProviders(
317 MockEntropyProviders::Results results,
Steven Holte896279f2022-10-21 20:32:30318 uint32_t low_entropy_domain)
Steven Holtea84bc222022-09-29 07:11:46319 : EntropyProviders(results.high_entropy.has_value() ? "client_id" : "",
Steven Holte896279f2022-10-21 20:32:30320 {0, low_entropy_domain}),
Steven Holtea84bc222022-09-29 07:11:46321 low_provider_(results.low_entropy),
322 high_provider_(results.high_entropy.value_or(0)) {}
323
324MockEntropyProviders::~MockEntropyProviders() = default;
325
326const base::FieldTrial::EntropyProvider& MockEntropyProviders::low_entropy()
327 const {
328 return low_provider_;
329}
330
331const base::FieldTrial::EntropyProvider& MockEntropyProviders::default_entropy()
332 const {
333 if (default_entropy_is_high_entropy()) {
334 return high_provider_;
335 }
336 return low_provider_;
337}
338
Caitlin Fischer6920a082021-06-29 05:25:24339} // namespace variations