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"
9 #include "components/variations/processed_study.h"
10 #include "components/variations/proto/study.pb.h"
11 #include "components/variations/variations_associated_data.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace chrome_variations
{
18 // An implementation of EntropyProvider that always returns a specific entropy
19 // value, regardless of field trial.
20 class TestEntropyProvider
: public base::FieldTrial::EntropyProvider
{
22 explicit TestEntropyProvider(double entropy_value
)
23 : entropy_value_(entropy_value
) {}
24 virtual ~TestEntropyProvider() {}
26 // base::FieldTrial::EntropyProvider implementation:
27 virtual double GetEntropyForTrial(const std::string
& trial_name
,
28 uint32 randomization_seed
) const OVERRIDE
{
29 return entropy_value_
;
33 const double entropy_value_
;
35 DISALLOW_COPY_AND_ASSIGN(TestEntropyProvider
);
38 // Creates and activates a single-group field trial with name |trial_name| and
39 // group |group_name| and variations |params| (if not NULL).
40 void CreateTrial(const std::string
& trial_name
,
41 const std::string
& group_name
,
42 const std::map
<std::string
, std::string
>* params
) {
43 base::FieldTrialList::CreateFieldTrial(trial_name
, group_name
);
45 AssociateVariationParams(trial_name
, group_name
, *params
);
46 base::FieldTrialList::FindFullName(trial_name
);
49 // Creates a study with the given |study_name| and |consistency|.
50 Study
CreateStudy(const std::string
& study_name
,
51 Study_Consistency consistency
) {
53 study
.set_name(study_name
);
54 study
.set_consistency(consistency
);
58 // Adds an experiment to |study| with the specified |experiment_name| and
59 // |probability| values and sets it as the study's default experiment.
60 Study_Experiment
* AddExperiment(const std::string
& experiment_name
,
63 Study_Experiment
* experiment
= study
->add_experiment();
64 experiment
->set_name(experiment_name
);
65 experiment
->set_probability_weight(probability
);
66 study
->set_default_experiment_name(experiment_name
);
70 // Add an experiment param with |param_name| and |param_value| to |experiment|.
71 Study_Experiment_Param
* AddExperimentParam(const std::string
& param_name
,
72 const std::string
& param_value
,
73 Study_Experiment
* experiment
) {
74 Study_Experiment_Param
* param
= experiment
->add_param();
75 param
->set_name(param_name
);
76 param
->set_value(param_value
);
80 // Uses a VariationsSeedSimulator to simulate the differences between |studies|
81 // and the current field trial state.
82 int SimulateDifferences(const std::vector
<ProcessedStudy
>& studies
) {
83 TestEntropyProvider
provider(0.5);
84 VariationsSeedSimulator
seed_simulator(provider
);
85 return seed_simulator
.ComputeDifferences(studies
);
88 class VariationsSeedSimulatorTest
: public ::testing::Test
{
90 VariationsSeedSimulatorTest() : field_trial_list_(NULL
) {
93 virtual ~VariationsSeedSimulatorTest() {
94 // Ensure that the maps are cleared between tests, since they are stored as
95 // process singletons.
96 testing::ClearAllVariationIDs();
97 testing::ClearAllVariationParams();
101 base::FieldTrialList field_trial_list_
;
103 DISALLOW_COPY_AND_ASSIGN(VariationsSeedSimulatorTest
);
108 TEST_F(VariationsSeedSimulatorTest
, PermanentNoChanges
) {
109 CreateTrial("A", "B", NULL
);
111 std::vector
<ProcessedStudy
> processed_studies
;
112 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
113 AddExperiment("B", 100, &study
);
115 std::vector
<ProcessedStudy
> studies
;
116 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
118 EXPECT_EQ(0, SimulateDifferences(studies
));
121 TEST_F(VariationsSeedSimulatorTest
, PermanentGroupChange
) {
122 CreateTrial("A", "B", NULL
);
124 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
125 AddExperiment("C", 100, &study
);
127 std::vector
<ProcessedStudy
> studies
;
128 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
130 EXPECT_EQ(1, SimulateDifferences(studies
));
133 TEST_F(VariationsSeedSimulatorTest
, PermanentExpired
) {
134 CreateTrial("A", "B", NULL
);
136 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
137 AddExperiment("B", 1, &study
);
138 AddExperiment("C", 0, &study
);
140 std::vector
<ProcessedStudy
> studies
;
141 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, true, &studies
));
142 EXPECT_TRUE(studies
[0].is_expired());
144 // There should be a difference because the study is expired, which should
145 // result in the default group "D" being chosen.
146 EXPECT_EQ(1, SimulateDifferences(studies
));
149 TEST_F(VariationsSeedSimulatorTest
, SessionRandomized
) {
150 CreateTrial("A", "B", NULL
);
152 Study study
= CreateStudy("A", Study_Consistency_SESSION
);
153 AddExperiment("B", 1, &study
);
154 AddExperiment("C", 1, &study
);
155 AddExperiment("D", 1, &study
);
157 std::vector
<ProcessedStudy
> studies
;
158 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
160 // There should be no differences, since a session randomized study can result
161 // in any of the groups being chosen on startup.
162 EXPECT_EQ(0, SimulateDifferences(studies
));
165 TEST_F(VariationsSeedSimulatorTest
, SessionRandomizedGroupRemoved
) {
166 CreateTrial("A", "B", NULL
);
168 Study study
= CreateStudy("A", Study_Consistency_SESSION
);
169 AddExperiment("C", 1, &study
);
170 AddExperiment("D", 1, &study
);
172 std::vector
<ProcessedStudy
> studies
;
173 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
175 // There should be a difference since there is no group "B" in the new config.
176 EXPECT_EQ(1, SimulateDifferences(studies
));
179 TEST_F(VariationsSeedSimulatorTest
, SessionRandomizedGroupProbabilityZero
) {
180 CreateTrial("A", "B", NULL
);
182 Study study
= CreateStudy("A", Study_Consistency_SESSION
);
183 AddExperiment("B", 0, &study
);
184 AddExperiment("C", 1, &study
);
185 AddExperiment("D", 1, &study
);
187 std::vector
<ProcessedStudy
> studies
;
188 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
190 // There should be a difference since there is group "B" has probability 0.
191 EXPECT_EQ(1, SimulateDifferences(studies
));
194 TEST_F(VariationsSeedSimulatorTest
, SessionRandomizedExpired
) {
195 CreateTrial("A", "B", NULL
);
197 Study study
= CreateStudy("A", Study_Consistency_SESSION
);
198 AddExperiment("B", 1, &study
);
199 AddExperiment("C", 1, &study
);
200 AddExperiment("D", 1, &study
);
202 std::vector
<ProcessedStudy
> studies
;
203 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, true, &studies
));
204 EXPECT_TRUE(studies
[0].is_expired());
206 // There should be a difference because the study is expired, which should
207 // result in the default group "D" being chosen.
208 EXPECT_EQ(1, SimulateDifferences(studies
));
211 TEST_F(VariationsSeedSimulatorTest
, ParamsUnchanged
) {
212 std::map
<std::string
, std::string
> params
;
216 CreateTrial("A", "B", ¶ms
);
218 std::vector
<ProcessedStudy
> processed_studies
;
219 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
220 Study_Experiment
* experiment
= AddExperiment("B", 100, &study
);
221 AddExperimentParam("p2", "y", experiment
);
222 AddExperimentParam("p1", "x", experiment
);
223 AddExperimentParam("p3", "z", experiment
);
225 std::vector
<ProcessedStudy
> studies
;
226 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
228 EXPECT_EQ(0, SimulateDifferences(studies
));
231 TEST_F(VariationsSeedSimulatorTest
, ParamsChanged
) {
232 std::map
<std::string
, std::string
> params
;
236 CreateTrial("A", "B", ¶ms
);
238 std::vector
<ProcessedStudy
> processed_studies
;
239 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
240 Study_Experiment
* experiment
= AddExperiment("B", 100, &study
);
241 AddExperimentParam("p2", "test", experiment
);
242 AddExperimentParam("p1", "x", experiment
);
243 AddExperimentParam("p3", "z", experiment
);
245 std::vector
<ProcessedStudy
> studies
;
246 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
248 // The param lists differ.
249 EXPECT_EQ(1, SimulateDifferences(studies
));
252 TEST_F(VariationsSeedSimulatorTest
, ParamsRemoved
) {
253 std::map
<std::string
, std::string
> params
;
257 CreateTrial("A", "B", ¶ms
);
259 std::vector
<ProcessedStudy
> processed_studies
;
260 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
261 AddExperiment("B", 100, &study
);
263 std::vector
<ProcessedStudy
> studies
;
264 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
266 // The current group has params, but the new config doesn't have any.
267 EXPECT_EQ(1, SimulateDifferences(studies
));
270 TEST_F(VariationsSeedSimulatorTest
, ParamsAdded
) {
271 CreateTrial("A", "B", NULL
);
273 std::vector
<ProcessedStudy
> processed_studies
;
274 Study study
= CreateStudy("A", Study_Consistency_PERMANENT
);
275 Study_Experiment
* experiment
= AddExperiment("B", 100, &study
);
276 AddExperimentParam("p2", "y", experiment
);
277 AddExperimentParam("p1", "x", experiment
);
278 AddExperimentParam("p3", "z", experiment
);
280 std::vector
<ProcessedStudy
> studies
;
281 EXPECT_TRUE(ProcessedStudy::ValidateAndAppendStudy(&study
, false, &studies
));
283 // The current group has no params, but the config has added some.
284 EXPECT_EQ(1, SimulateDifferences(studies
));
287 } // namespace chrome_variations