Roll src/third_party/WebKit 605a979:06cb9e9 (svn 202556:202558)
[chromium-blink-merge.git] / components / variations / variations_seed_simulator_unittest.cc
blob965c6afba3362f5474b27572f30762b30bd024b1
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 "components/variations/variations_seed_simulator.h"
7 #include <map>
9 #include "base/strings/stringprintf.h"
10 #include "components/variations/processed_study.h"
11 #include "components/variations/proto/study.pb.h"
12 #include "components/variations/variations_associated_data.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace variations {
17 namespace {
19 // An implementation of EntropyProvider that always returns a specific entropy
20 // value, regardless of field trial.
21 class TestEntropyProvider : public base::FieldTrial::EntropyProvider {
22 public:
23 explicit TestEntropyProvider(double entropy_value)
24 : entropy_value_(entropy_value) {}
25 ~TestEntropyProvider() override {}
27 // base::FieldTrial::EntropyProvider implementation:
28 double GetEntropyForTrial(const std::string& trial_name,
29 uint32 randomization_seed) const override {
30 return entropy_value_;
33 private:
34 const double entropy_value_;
36 DISALLOW_COPY_AND_ASSIGN(TestEntropyProvider);
39 // Creates and activates a single-group field trial with name |trial_name| and
40 // group |group_name| and variations |params| (if not NULL).
41 void CreateTrial(const std::string& trial_name,
42 const std::string& group_name,
43 const std::map<std::string, std::string>* params) {
44 base::FieldTrialList::CreateFieldTrial(trial_name, group_name);
45 if (params != NULL)
46 AssociateVariationParams(trial_name, group_name, *params);
47 base::FieldTrialList::FindFullName(trial_name);
50 // Creates a study with the given |study_name| and |consistency|.
51 Study CreateStudy(const std::string& study_name,
52 Study_Consistency consistency) {
53 Study study;
54 study.set_name(study_name);
55 study.set_consistency(consistency);
56 return study;
59 // Adds an experiment to |study| with the specified |experiment_name| and
60 // |probability| values and sets it as the study's default experiment.
61 Study_Experiment* AddExperiment(const std::string& experiment_name,
62 int probability,
63 Study* study) {
64 Study_Experiment* experiment = study->add_experiment();
65 experiment->set_name(experiment_name);
66 experiment->set_probability_weight(probability);
67 study->set_default_experiment_name(experiment_name);
68 return experiment;
71 // Add an experiment param with |param_name| and |param_value| to |experiment|.
72 Study_Experiment_Param* AddExperimentParam(const std::string& param_name,
73 const std::string& param_value,
74 Study_Experiment* experiment) {
75 Study_Experiment_Param* param = experiment->add_param();
76 param->set_name(param_name);
77 param->set_value(param_value);
78 return param;
81 } // namespace
83 class VariationsSeedSimulatorTest : public ::testing::Test {
84 public:
85 VariationsSeedSimulatorTest() : field_trial_list_(NULL) {
88 ~VariationsSeedSimulatorTest() override {
89 // Ensure that the maps are cleared between tests, since they are stored as
90 // process singletons.
91 testing::ClearAllVariationIDs();
92 testing::ClearAllVariationParams();
95 // Uses a VariationsSeedSimulator to simulate the differences between
96 // |studies| and the current field trial state.
97 VariationsSeedSimulator::Result SimulateDifferences(
98 const std::vector<ProcessedStudy>& studies) {
99 TestEntropyProvider provider(0.5);
100 VariationsSeedSimulator seed_simulator(provider);
101 return seed_simulator.ComputeDifferences(studies);
104 // Simulates the differences between |study| and the current field trial
105 // state, returning a string like "1 2 3", where 1 is the number of regular
106 // group changes, 2 is the number of "kill best effort" group changes and 3
107 // is the number of "kill critical" group changes.
108 std::string SimulateStudyDifferences(const Study* study) {
109 std::vector<ProcessedStudy> studies;
110 if (!ProcessedStudy::ValidateAndAppendStudy(study, false, &studies))
111 return "invalid study";
112 return ConvertSimulationResultToString(SimulateDifferences(studies));
115 // Simulates the differences between expired |study| and the current field
116 // trial state, returning a string like "1 2 3", where 1 is the number of
117 // regular group changes, 2 is the number of "kill best effort" group changes
118 // and 3 is the number of "kill critical" group changes.
119 std::string SimulateStudyDifferencesExpired(const Study* study) {
120 std::vector<ProcessedStudy> studies;
121 if (!ProcessedStudy::ValidateAndAppendStudy(study, true, &studies))
122 return "invalid study";
123 if (!studies[0].is_expired())
124 return "not expired";
125 return ConvertSimulationResultToString(SimulateDifferences(studies));
128 // Formats |result| as a string with format "1 2 3", where 1 is the number of
129 // regular group changes, 2 is the number of "kill best effort" group changes
130 // and 3 is the number of "kill critical" group changes.
131 std::string ConvertSimulationResultToString(
132 const VariationsSeedSimulator::Result& result) {
133 return base::StringPrintf("%d %d %d",
134 result.normal_group_change_count,
135 result.kill_best_effort_group_change_count,
136 result.kill_critical_group_change_count);
139 private:
140 base::FieldTrialList field_trial_list_;
142 DISALLOW_COPY_AND_ASSIGN(VariationsSeedSimulatorTest);
145 TEST_F(VariationsSeedSimulatorTest, PermanentNoChanges) {
146 CreateTrial("A", "B", NULL);
148 std::vector<ProcessedStudy> processed_studies;
149 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
150 Study_Experiment* experiment = AddExperiment("B", 100, &study);
152 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
154 experiment->set_type(Study_Experiment_Type_NORMAL);
155 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
156 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
157 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
158 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
159 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
160 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
161 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
164 TEST_F(VariationsSeedSimulatorTest, PermanentGroupChange) {
165 CreateTrial("A", "B", NULL);
167 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
168 Study_Experiment* experiment = AddExperiment("C", 100, &study);
170 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
172 // Changing "C" group type should not affect the type of change. (Since the
173 // type is evaluated for the "old" group.)
174 experiment->set_type(Study_Experiment_Type_NORMAL);
175 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
176 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
177 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
178 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
179 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
180 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
181 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
184 TEST_F(VariationsSeedSimulatorTest, PermanentExpired) {
185 CreateTrial("A", "B", NULL);
187 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
188 Study_Experiment* experiment = AddExperiment("B", 1, &study);
189 AddExperiment("C", 0, &study);
191 // There should be a difference because the study is expired, which should
192 // result in the default group "C" being chosen.
193 EXPECT_EQ("1 0 0", SimulateStudyDifferencesExpired(&study));
195 experiment->set_type(Study_Experiment_Type_NORMAL);
196 EXPECT_EQ("1 0 0", SimulateStudyDifferencesExpired(&study));
197 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
198 EXPECT_EQ("0 0 0", SimulateStudyDifferencesExpired(&study));
199 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
200 EXPECT_EQ("0 1 0", SimulateStudyDifferencesExpired(&study));
201 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
202 EXPECT_EQ("0 0 1", SimulateStudyDifferencesExpired(&study));
205 TEST_F(VariationsSeedSimulatorTest, SessionRandomized) {
206 CreateTrial("A", "B", NULL);
208 Study study = CreateStudy("A", Study_Consistency_SESSION);
209 Study_Experiment* experiment = AddExperiment("B", 1, &study);
210 AddExperiment("C", 1, &study);
211 AddExperiment("D", 1, &study);
213 // There should be no differences, since a session randomized study can result
214 // in any of the groups being chosen on startup.
215 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
217 experiment->set_type(Study_Experiment_Type_NORMAL);
218 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
219 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
220 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
221 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
222 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
223 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
224 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
227 TEST_F(VariationsSeedSimulatorTest, SessionRandomizedGroupRemoved) {
228 CreateTrial("A", "B", NULL);
230 Study study = CreateStudy("A", Study_Consistency_SESSION);
231 AddExperiment("C", 1, &study);
232 AddExperiment("D", 1, &study);
234 // There should be a difference since there is no group "B" in the new config.
235 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
238 TEST_F(VariationsSeedSimulatorTest, SessionRandomizedGroupProbabilityZero) {
239 CreateTrial("A", "B", NULL);
241 Study study = CreateStudy("A", Study_Consistency_SESSION);
242 Study_Experiment* experiment = AddExperiment("B", 0, &study);
243 AddExperiment("C", 1, &study);
244 AddExperiment("D", 1, &study);
246 // There should be a difference since group "B" has probability 0.
247 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
249 experiment->set_type(Study_Experiment_Type_NORMAL);
250 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
251 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
252 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
253 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
254 EXPECT_EQ("0 1 0", SimulateStudyDifferences(&study));
255 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
256 EXPECT_EQ("0 0 1", SimulateStudyDifferences(&study));
259 TEST_F(VariationsSeedSimulatorTest, SessionRandomizedExpired) {
260 CreateTrial("A", "B", NULL);
262 Study study = CreateStudy("A", Study_Consistency_SESSION);
263 Study_Experiment* experiment = AddExperiment("B", 1, &study);
264 AddExperiment("C", 1, &study);
265 AddExperiment("D", 1, &study);
267 // There should be a difference because the study is expired, which should
268 // result in the default group "D" being chosen.
269 EXPECT_EQ("1 0 0", SimulateStudyDifferencesExpired(&study));
271 experiment->set_type(Study_Experiment_Type_NORMAL);
272 EXPECT_EQ("1 0 0", SimulateStudyDifferencesExpired(&study));
273 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
274 EXPECT_EQ("0 0 0", SimulateStudyDifferencesExpired(&study));
275 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
276 EXPECT_EQ("0 1 0", SimulateStudyDifferencesExpired(&study));
277 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
278 EXPECT_EQ("0 0 1", SimulateStudyDifferencesExpired(&study));
281 TEST_F(VariationsSeedSimulatorTest, ParamsUnchanged) {
282 std::map<std::string, std::string> params;
283 params["p1"] = "x";
284 params["p2"] = "y";
285 params["p3"] = "z";
286 CreateTrial("A", "B", &params);
288 std::vector<ProcessedStudy> processed_studies;
289 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
290 Study_Experiment* experiment = AddExperiment("B", 100, &study);
291 AddExperimentParam("p2", "y", experiment);
292 AddExperimentParam("p1", "x", experiment);
293 AddExperimentParam("p3", "z", experiment);
295 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
297 experiment->set_type(Study_Experiment_Type_NORMAL);
298 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
299 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
300 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
301 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
302 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
303 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
304 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
307 TEST_F(VariationsSeedSimulatorTest, ParamsChanged) {
308 std::map<std::string, std::string> params;
309 params["p1"] = "x";
310 params["p2"] = "y";
311 params["p3"] = "z";
312 CreateTrial("A", "B", &params);
314 std::vector<ProcessedStudy> processed_studies;
315 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
316 Study_Experiment* experiment = AddExperiment("B", 100, &study);
317 AddExperimentParam("p2", "test", experiment);
318 AddExperimentParam("p1", "x", experiment);
319 AddExperimentParam("p3", "z", experiment);
321 // The param lists differ.
322 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
324 experiment->set_type(Study_Experiment_Type_NORMAL);
325 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
326 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
327 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
328 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
329 EXPECT_EQ("0 1 0", SimulateStudyDifferences(&study));
330 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
331 EXPECT_EQ("0 0 1", SimulateStudyDifferences(&study));
334 TEST_F(VariationsSeedSimulatorTest, ParamsRemoved) {
335 std::map<std::string, std::string> params;
336 params["p1"] = "x";
337 params["p2"] = "y";
338 params["p3"] = "z";
339 CreateTrial("A", "B", &params);
341 std::vector<ProcessedStudy> processed_studies;
342 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
343 Study_Experiment* experiment = AddExperiment("B", 100, &study);
345 // The current group has params, but the new config doesn't have any.
346 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
348 experiment->set_type(Study_Experiment_Type_NORMAL);
349 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
350 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
351 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
352 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
353 EXPECT_EQ("0 1 0", SimulateStudyDifferences(&study));
354 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
355 EXPECT_EQ("0 0 1", SimulateStudyDifferences(&study));
358 TEST_F(VariationsSeedSimulatorTest, ParamsAdded) {
359 CreateTrial("A", "B", NULL);
361 std::vector<ProcessedStudy> processed_studies;
362 Study study = CreateStudy("A", Study_Consistency_PERMANENT);
363 Study_Experiment* experiment = AddExperiment("B", 100, &study);
364 AddExperimentParam("p2", "y", experiment);
365 AddExperimentParam("p1", "x", experiment);
366 AddExperimentParam("p3", "z", experiment);
368 // The current group has no params, but the config has added some.
369 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
371 experiment->set_type(Study_Experiment_Type_NORMAL);
372 EXPECT_EQ("1 0 0", SimulateStudyDifferences(&study));
373 experiment->set_type(Study_Experiment_Type_IGNORE_CHANGE);
374 EXPECT_EQ("0 0 0", SimulateStudyDifferences(&study));
375 experiment->set_type(Study_Experiment_Type_KILL_BEST_EFFORT);
376 EXPECT_EQ("0 1 0", SimulateStudyDifferences(&study));
377 experiment->set_type(Study_Experiment_Type_KILL_CRITICAL);
378 EXPECT_EQ("0 0 1", SimulateStudyDifferences(&study));
381 } // namespace variations