blob: 620c9da5cc07e3c4ba1d2e6c84b69ddda5efb549 [file] [log] [blame]
[email protected]1871a1702013-07-26 09:37:431// Copyright 2013 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
[email protected]50ae9f12013-08-29 18:03:225#include "components/variations/variations_seed_processor.h"
[email protected]1871a1702013-07-26 09:37:436
avi5dd91f82015-12-25 22:30:467#include <stddef.h>
8#include <stdint.h>
dcheng3f767dc32016-04-25 22:54:229
[email protected]e24fff362014-07-22 01:19:0210#include <map>
dcheng3f767dc32016-04-25 22:54:2211#include <memory>
dcheng51ace48a2015-12-26 22:45:1712#include <utility>
[email protected]1871a1702013-07-26 09:37:4313#include <vector>
14
[email protected]e24fff362014-07-22 01:19:0215#include "base/bind.h"
[email protected]1871a1702013-07-26 09:37:4316#include "base/command_line.h"
asvitkine8423d172015-09-28 23:23:4417#include "base/feature_list.h"
18#include "base/format_macros.h"
avi5dd91f82015-12-25 22:30:4619#include "base/macros.h"
robliao79393ffb2016-09-21 18:45:2920#include "base/memory/ptr_util.h"
[email protected]1871a1702013-07-26 09:37:4321#include "base/strings/string_split.h"
asvitkine8423d172015-09-28 23:23:4422#include "base/strings/stringprintf.h"
[email protected]e24fff362014-07-22 01:19:0223#include "base/strings/utf_string_conversions.h"
jwd67c08f752016-05-18 21:04:5924#include "base/test/mock_entropy_provider.h"
asvitkine9499b8d2016-08-09 05:37:0725#include "base/test/scoped_feature_list.h"
isherman52a81bd2017-06-07 23:30:0626#include "components/variations/client_filterable_state.h"
[email protected]d4f84852013-11-08 01:05:3527#include "components/variations/processed_study.h"
asvitkine71411062016-05-17 20:09:4428#include "components/variations/study_filtering.h"
[email protected]50ae9f12013-08-29 18:03:2229#include "components/variations/variations_associated_data.h"
[email protected]1871a1702013-07-26 09:37:4330#include "testing/gtest/include/gtest/gtest.h"
31
[email protected]59b6f672014-07-26 18:35:4732namespace variations {
[email protected]1871a1702013-07-26 09:37:4333
34namespace {
35
36// Converts |time| to Study proto format.
avi5dd91f82015-12-25 22:30:4637int64_t TimeToProtoTime(const base::Time& time) {
[email protected]1871a1702013-07-26 09:37:4338 return (time - base::Time::UnixEpoch()).InSeconds();
39}
40
41// Constants for testing associating command line flags with trial groups.
42const char kFlagStudyName[] = "flag_test_trial";
43const char kFlagGroup1Name[] = "flag_group1";
44const char kFlagGroup2Name[] = "flag_group2";
45const char kNonFlagGroupName[] = "non_flag_group";
jkrcal7ce02462016-07-01 09:57:5346const char kOtherGroupName[] = "other_group";
[email protected]1871a1702013-07-26 09:37:4347const char kForcingFlag1[] = "flag_test1";
48const char kForcingFlag2[] = "flag_test2";
49
[email protected]0aafa3e2013-11-18 09:32:4550const VariationID kExperimentId = 123;
51
[email protected]5bd00ce2013-08-05 23:46:1252// Adds an experiment to |study| with the specified |name| and |probability|.
53Study_Experiment* AddExperiment(const std::string& name, int probability,
54 Study* study) {
55 Study_Experiment* experiment = study->add_experiment();
56 experiment->set_name(name);
57 experiment->set_probability_weight(probability);
58 return experiment;
59}
60
[email protected]1871a1702013-07-26 09:37:4361// Populates |study| with test data used for testing associating command line
62// flags with trials groups. The study will contain three groups, a default
63// group that isn't associated with a flag, and two other groups, both
64// associated with different flags.
65Study CreateStudyWithFlagGroups(int default_group_probability,
66 int flag_group1_probability,
67 int flag_group2_probability) {
68 DCHECK_GE(default_group_probability, 0);
69 DCHECK_GE(flag_group1_probability, 0);
70 DCHECK_GE(flag_group2_probability, 0);
71 Study study;
72 study.set_name(kFlagStudyName);
73 study.set_default_experiment_name(kNonFlagGroupName);
74
[email protected]5bd00ce2013-08-05 23:46:1275 AddExperiment(kNonFlagGroupName, default_group_probability, &study);
76 AddExperiment(kFlagGroup1Name, flag_group1_probability, &study)
77 ->set_forcing_flag(kForcingFlag1);
78 AddExperiment(kFlagGroup2Name, flag_group2_probability, &study)
79 ->set_forcing_flag(kForcingFlag2);
[email protected]1871a1702013-07-26 09:37:4380
81 return study;
82}
83
[email protected]e24fff362014-07-22 01:19:0284class TestOverrideStringCallback {
85 public:
86 typedef std::map<uint32_t, base::string16> OverrideMap;
87
88 TestOverrideStringCallback()
89 : callback_(base::Bind(&TestOverrideStringCallback::Override,
90 base::Unretained(this))) {}
91
92 virtual ~TestOverrideStringCallback() {}
93
94 const VariationsSeedProcessor::UIStringOverrideCallback& callback() const {
95 return callback_;
96 }
97
98 const OverrideMap& overrides() const { return overrides_; }
99
100 private:
101 void Override(uint32_t hash, const base::string16& string) {
102 overrides_[hash] = string;
103 }
104
105 VariationsSeedProcessor::UIStringOverrideCallback callback_;
106 OverrideMap overrides_;
107
108 DISALLOW_COPY_AND_ASSIGN(TestOverrideStringCallback);
109};
110
[email protected]1871a1702013-07-26 09:37:43111} // namespace
112
[email protected]f2fc7cf42013-11-07 21:53:03113class VariationsSeedProcessorTest : public ::testing::Test {
114 public:
115 VariationsSeedProcessorTest() {
116 }
117
dcheng30a1b1542014-10-29 21:27:50118 ~VariationsSeedProcessorTest() override {
[email protected]f2fc7cf42013-11-07 21:53:03119 // Ensure that the maps are cleared between tests, since they are stored as
120 // process singletons.
121 testing::ClearAllVariationIDs();
122 testing::ClearAllVariationParams();
123 }
124
asvitkine71411062016-05-17 20:09:44125 bool CreateTrialFromStudy(const Study& study) {
jwd67c08f752016-05-18 21:04:59126 return CreateTrialFromStudyWithFeatureListAndEntropyOverride(
127 study, nullptr, &feature_list_);
128 }
129
130 bool CreateTrialFromStudyWithEntropyOverride(
131 const Study& study,
132 const base::FieldTrial::EntropyProvider* override_entropy_provider) {
133 return CreateTrialFromStudyWithFeatureListAndEntropyOverride(
134 study, override_entropy_provider, &feature_list_);
asvitkine8423d172015-09-28 23:23:44135 }
136
asvitkine71411062016-05-17 20:09:44137 bool CreateTrialFromStudyWithFeatureList(const Study& study,
asvitkine8423d172015-09-28 23:23:44138 base::FeatureList* feature_list) {
jwd67c08f752016-05-18 21:04:59139 return CreateTrialFromStudyWithFeatureListAndEntropyOverride(study, nullptr,
140 feature_list);
141 }
142
143 bool CreateTrialFromStudyWithFeatureListAndEntropyOverride(
144 const Study& study,
145 const base::FieldTrial::EntropyProvider* override_entropy_provider,
146 base::FeatureList* feature_list) {
[email protected]70fbd0052013-11-20 02:22:06147 ProcessedStudy processed_study;
asvitkine71411062016-05-17 20:09:44148 const bool is_expired = internal::IsStudyExpired(study, base::Time::Now());
149 if (processed_study.Init(&study, is_expired)) {
[email protected]e24fff362014-07-22 01:19:02150 VariationsSeedProcessor().CreateTrialFromStudy(
jwd67c08f752016-05-18 21:04:59151 processed_study, override_callback_.callback(),
152 override_entropy_provider, feature_list);
[email protected]70fbd0052013-11-20 02:22:06153 return true;
154 }
155 return false;
156 }
157
[email protected]e24fff362014-07-22 01:19:02158 protected:
asvitkine8423d172015-09-28 23:23:44159 base::FeatureList feature_list_;
[email protected]e24fff362014-07-22 01:19:02160 TestOverrideStringCallback override_callback_;
161
[email protected]f2fc7cf42013-11-07 21:53:03162 private:
163 DISALLOW_COPY_AND_ASSIGN(VariationsSeedProcessorTest);
164};
165
[email protected]0aafa3e2013-11-18 09:32:45166TEST_F(VariationsSeedProcessorTest, AllowForceGroupAndVariationId) {
avi1772c1a2014-12-22 22:42:33167 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
[email protected]0aafa3e2013-11-18 09:32:45168
asvitkine71411062016-05-17 20:09:44169 base::FieldTrialList field_trial_list(nullptr);
[email protected]0aafa3e2013-11-18 09:32:45170
171 Study study = CreateStudyWithFlagGroups(100, 0, 0);
172 study.mutable_experiment(1)->set_google_web_experiment_id(kExperimentId);
[email protected]0aafa3e2013-11-18 09:32:45173
asvitkine71411062016-05-17 20:09:44174 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]0aafa3e2013-11-18 09:32:45175 EXPECT_EQ(kFlagGroup1Name,
176 base::FieldTrialList::FindFullName(kFlagStudyName));
177
178 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName,
179 kFlagGroup1Name);
180 EXPECT_EQ(kExperimentId, id);
181}
182
[email protected]1871a1702013-07-26 09:37:43183// Test that the group for kForcingFlag1 is forced.
[email protected]f2fc7cf42013-11-07 21:53:03184TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag1) {
avi1772c1a2014-12-22 22:42:33185 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
[email protected]1871a1702013-07-26 09:37:43186
asvitkine71411062016-05-17 20:09:44187 base::FieldTrialList field_trial_list(nullptr);
[email protected]1871a1702013-07-26 09:37:43188
189 Study study = CreateStudyWithFlagGroups(100, 0, 0);
asvitkine71411062016-05-17 20:09:44190 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43191 EXPECT_EQ(kFlagGroup1Name,
192 base::FieldTrialList::FindFullName(kFlagStudyName));
193}
194
195// Test that the group for kForcingFlag2 is forced.
[email protected]f2fc7cf42013-11-07 21:53:03196TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag2) {
avi1772c1a2014-12-22 22:42:33197 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2);
[email protected]1871a1702013-07-26 09:37:43198
asvitkine71411062016-05-17 20:09:44199 base::FieldTrialList field_trial_list(nullptr);
[email protected]1871a1702013-07-26 09:37:43200
201 Study study = CreateStudyWithFlagGroups(100, 0, 0);
asvitkine71411062016-05-17 20:09:44202 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43203 EXPECT_EQ(kFlagGroup2Name,
204 base::FieldTrialList::FindFullName(kFlagStudyName));
205}
206
[email protected]f2fc7cf42013-11-07 21:53:03207TEST_F(VariationsSeedProcessorTest, ForceGroup_ChooseFirstGroupWithFlag) {
[email protected]1871a1702013-07-26 09:37:43208 // Add the flag to the command line arguments so the flag group is forced.
avi1772c1a2014-12-22 22:42:33209 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
210 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2);
[email protected]1871a1702013-07-26 09:37:43211
asvitkine71411062016-05-17 20:09:44212 base::FieldTrialList field_trial_list(nullptr);
[email protected]1871a1702013-07-26 09:37:43213
214 Study study = CreateStudyWithFlagGroups(100, 0, 0);
asvitkine71411062016-05-17 20:09:44215 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43216 EXPECT_EQ(kFlagGroup1Name,
217 base::FieldTrialList::FindFullName(kFlagStudyName));
218}
219
[email protected]f2fc7cf42013-11-07 21:53:03220TEST_F(VariationsSeedProcessorTest, ForceGroup_DontChooseGroupWithFlag) {
asvitkine71411062016-05-17 20:09:44221 base::FieldTrialList field_trial_list(nullptr);
[email protected]1871a1702013-07-26 09:37:43222
223 // The two flag groups are given high probability, which would normally make
224 // them very likely to be chosen. They won't be chosen since flag groups are
225 // never chosen when their flag isn't present.
226 Study study = CreateStudyWithFlagGroups(1, 999, 999);
asvitkine71411062016-05-17 20:09:44227 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43228 EXPECT_EQ(kNonFlagGroupName,
229 base::FieldTrialList::FindFullName(kFlagStudyName));
230}
231
jkrcal7ce02462016-07-01 09:57:53232TEST_F(VariationsSeedProcessorTest, CreateTrialForRegisteredGroup) {
233 base::FieldTrialList field_trial_list(nullptr);
234
235 base::FieldTrialList::CreateFieldTrial(kFlagStudyName, kOtherGroupName);
236
237 // Create an arbitrary study that does not have group named |kOtherGroupName|.
238 Study study = CreateStudyWithFlagGroups(100, 0, 0);
239 // Creating the trial should not crash.
240 EXPECT_TRUE(CreateTrialFromStudy(study));
241 // And the previous group should still be selected.
242 EXPECT_EQ(kOtherGroupName,
243 base::FieldTrialList::FindFullName(kFlagStudyName));
244}
245
[email protected]f2fc7cf42013-11-07 21:53:03246TEST_F(VariationsSeedProcessorTest,
247 NonExpiredStudyPrioritizedOverExpiredStudy) {
[email protected]5bd00ce2013-08-05 23:46:12248 VariationsSeedProcessor seed_processor;
249
250 const std::string kTrialName = "A";
251 const std::string kGroup1Name = "Group1";
252
[email protected]541f66e2013-09-03 15:00:15253 VariationsSeed seed;
[email protected]5bd00ce2013-08-05 23:46:12254 Study* study1 = seed.add_study();
255 study1->set_name(kTrialName);
256 study1->set_default_experiment_name("Default");
257 AddExperiment(kGroup1Name, 100, study1);
258 AddExperiment("Default", 0, study1);
259 Study* study2 = seed.add_study();
260 *study2 = *study1;
261 ASSERT_EQ(seed.study(0).name(), seed.study(1).name());
262
263 const base::Time year_ago =
264 base::Time::Now() - base::TimeDelta::FromDays(365);
265
isherman52a81bd2017-06-07 23:30:06266 ClientFilterableState client_state;
267 client_state.locale = "en-CA";
268 client_state.reference_date = base::Time::Now();
269 client_state.version = base::Version("20.0.0.0");
270 client_state.channel = Study::STABLE;
271 client_state.form_factor = Study::DESKTOP;
272 client_state.platform = Study::PLATFORM_ANDROID;
[email protected]12a9b5552013-08-09 11:05:50273
[email protected]5bd00ce2013-08-05 23:46:12274 // Check that adding [expired, non-expired] activates the non-expired one.
275 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
276 {
asvitkine8423d172015-09-28 23:23:44277 base::FeatureList feature_list;
asvitkine71411062016-05-17 20:09:44278 base::FieldTrialList field_trial_list(nullptr);
[email protected]5bd00ce2013-08-05 23:46:12279 study1->set_expiry_date(TimeToProtoTime(year_ago));
isherman52a81bd2017-06-07 23:30:06280 seed_processor.CreateTrialsFromSeed(seed, client_state,
281 override_callback_.callback(), nullptr,
282 &feature_list);
[email protected]5bd00ce2013-08-05 23:46:12283 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
284 }
285
286 // Check that adding [non-expired, expired] activates the non-expired one.
287 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
288 {
asvitkine8423d172015-09-28 23:23:44289 base::FeatureList feature_list;
asvitkine71411062016-05-17 20:09:44290 base::FieldTrialList field_trial_list(nullptr);
[email protected]5bd00ce2013-08-05 23:46:12291 study1->clear_expiry_date();
292 study2->set_expiry_date(TimeToProtoTime(year_ago));
isherman52a81bd2017-06-07 23:30:06293 seed_processor.CreateTrialsFromSeed(seed, client_state,
294 override_callback_.callback(), nullptr,
295 &feature_list);
[email protected]5bd00ce2013-08-05 23:46:12296 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
297 }
298}
299
[email protected]e24fff362014-07-22 01:19:02300TEST_F(VariationsSeedProcessorTest, OverrideUIStrings) {
asvitkine71411062016-05-17 20:09:44301 base::FieldTrialList field_trial_list(nullptr);
[email protected]e24fff362014-07-22 01:19:02302
303 Study study;
304 study.set_name("Study1");
305 study.set_default_experiment_name("B");
306 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO);
307
308 Study_Experiment* experiment1 = AddExperiment("A", 0, &study);
309 Study_Experiment_OverrideUIString* override =
310 experiment1->add_override_ui_string();
311
312 override->set_name_hash(1234);
313 override->set_value("test");
314
315 Study_Experiment* experiment2 = AddExperiment("B", 1, &study);
316
asvitkine71411062016-05-17 20:09:44317 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]e24fff362014-07-22 01:19:02318
319 const TestOverrideStringCallback::OverrideMap& overrides =
320 override_callback_.overrides();
321
322 EXPECT_TRUE(overrides.empty());
323
324 study.set_name("Study2");
325 experiment1->set_probability_weight(1);
326 experiment2->set_probability_weight(0);
327
asvitkine71411062016-05-17 20:09:44328 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]e24fff362014-07-22 01:19:02329
330 EXPECT_EQ(1u, overrides.size());
331 TestOverrideStringCallback::OverrideMap::const_iterator it =
332 overrides.find(1234);
333 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second);
334}
335
336TEST_F(VariationsSeedProcessorTest, OverrideUIStringsWithForcingFlag) {
337 Study study = CreateStudyWithFlagGroups(100, 0, 0);
338 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag());
339
340 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO);
341 Study_Experiment_OverrideUIString* override =
342 study.mutable_experiment(1)->add_override_ui_string();
343 override->set_name_hash(1234);
344 override->set_value("test");
345
avi1772c1a2014-12-22 22:42:33346 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
asvitkine71411062016-05-17 20:09:44347 base::FieldTrialList field_trial_list(nullptr);
348 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]e24fff362014-07-22 01:19:02349 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name()));
350
351 const TestOverrideStringCallback::OverrideMap& overrides =
352 override_callback_.overrides();
353 EXPECT_EQ(1u, overrides.size());
354 TestOverrideStringCallback::OverrideMap::const_iterator it =
355 overrides.find(1234);
356 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second);
357}
358
[email protected]f2fc7cf42013-11-07 21:53:03359TEST_F(VariationsSeedProcessorTest, ValidateStudy) {
[email protected]1871a1702013-07-26 09:37:43360 Study study;
361 study.set_default_experiment_name("def");
[email protected]5bd00ce2013-08-05 23:46:12362 AddExperiment("abc", 100, &study);
363 Study_Experiment* default_group = AddExperiment("def", 200, &study);
[email protected]1871a1702013-07-26 09:37:43364
[email protected]70fbd0052013-11-20 02:22:06365 ProcessedStudy processed_study;
366 EXPECT_TRUE(processed_study.Init(&study, false));
367 EXPECT_EQ(300, processed_study.total_probability());
asvitkine30ac09132015-02-20 19:50:10368 EXPECT_FALSE(processed_study.all_assignments_to_one_group());
[email protected]1871a1702013-07-26 09:37:43369
370 // Min version checks.
371 study.mutable_filter()->set_min_version("1.2.3.*");
[email protected]70fbd0052013-11-20 02:22:06372 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43373 study.mutable_filter()->set_min_version("1.*.3");
[email protected]70fbd0052013-11-20 02:22:06374 EXPECT_FALSE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43375 study.mutable_filter()->set_min_version("1.2.3");
[email protected]70fbd0052013-11-20 02:22:06376 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43377
378 // Max version checks.
379 study.mutable_filter()->set_max_version("2.3.4.*");
[email protected]70fbd0052013-11-20 02:22:06380 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43381 study.mutable_filter()->set_max_version("*.3");
[email protected]70fbd0052013-11-20 02:22:06382 EXPECT_FALSE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43383 study.mutable_filter()->set_max_version("2.3.4");
[email protected]70fbd0052013-11-20 02:22:06384 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43385
jwd5ff54102017-01-06 18:09:34386 // A blank default study is allowed.
[email protected]1871a1702013-07-26 09:37:43387 study.clear_default_experiment_name();
jwd5ff54102017-01-06 18:09:34388 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43389
390 study.set_default_experiment_name("xyz");
[email protected]70fbd0052013-11-20 02:22:06391 EXPECT_FALSE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43392
393 study.set_default_experiment_name("def");
394 default_group->clear_name();
[email protected]70fbd0052013-11-20 02:22:06395 EXPECT_FALSE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43396
397 default_group->set_name("def");
[email protected]70fbd0052013-11-20 02:22:06398 EXPECT_TRUE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43399 Study_Experiment* repeated_group = study.add_experiment();
400 repeated_group->set_name("abc");
401 repeated_group->set_probability_weight(1);
[email protected]70fbd0052013-11-20 02:22:06402 EXPECT_FALSE(processed_study.Init(&study, false));
[email protected]1871a1702013-07-26 09:37:43403}
404
asvitkine64e9e112016-03-17 17:32:00405TEST_F(VariationsSeedProcessorTest, ValidateStudySingleFeature) {
406 Study study;
407 study.set_default_experiment_name("def");
408 Study_Experiment* exp1 = AddExperiment("exp1", 100, &study);
409 Study_Experiment* exp2 = AddExperiment("exp2", 100, &study);
410 Study_Experiment* exp3 = AddExperiment("exp3", 100, &study);
411 AddExperiment("def", 100, &study);
412
413 ProcessedStudy processed_study;
414 EXPECT_TRUE(processed_study.Init(&study, false));
415 EXPECT_EQ(400, processed_study.total_probability());
416
417 EXPECT_EQ(std::string(), processed_study.single_feature_name());
418
419 const char kFeature1Name[] = "Feature1";
420 const char kFeature2Name[] = "Feature2";
421
422 exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
423 EXPECT_TRUE(processed_study.Init(&study, false));
424 EXPECT_EQ(kFeature1Name, processed_study.single_feature_name());
425
426 exp1->clear_feature_association();
427 exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
428 exp1->mutable_feature_association()->add_enable_feature(kFeature2Name);
429 EXPECT_TRUE(processed_study.Init(&study, false));
430 // Since there's multiple different features, |single_feature_name| should be
431 // unset.
432 EXPECT_EQ(std::string(), processed_study.single_feature_name());
433
434 exp1->clear_feature_association();
435 exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
436 exp2->mutable_feature_association()->add_enable_feature(kFeature1Name);
437 exp3->mutable_feature_association()->add_disable_feature(kFeature1Name);
438 EXPECT_TRUE(processed_study.Init(&study, false));
439 EXPECT_EQ(kFeature1Name, processed_study.single_feature_name());
440
441 // Setting a different feature name on exp2 should cause |single_feature_name|
442 // to be not set.
443 exp2->mutable_feature_association()->set_enable_feature(0, kFeature2Name);
444 EXPECT_TRUE(processed_study.Init(&study, false));
445 EXPECT_EQ(std::string(), processed_study.single_feature_name());
446}
447
asvitkine30ac09132015-02-20 19:50:10448TEST_F(VariationsSeedProcessorTest, ProcessedStudyAllAssignmentsToOneGroup) {
449 Study study;
450 study.set_default_experiment_name("def");
451 AddExperiment("def", 100, &study);
452
453 ProcessedStudy processed_study;
454 EXPECT_TRUE(processed_study.Init(&study, false));
455 EXPECT_TRUE(processed_study.all_assignments_to_one_group());
456
457 AddExperiment("abc", 0, &study);
458 AddExperiment("flag", 0, &study)->set_forcing_flag(kForcingFlag1);
459 EXPECT_TRUE(processed_study.Init(&study, false));
460 EXPECT_TRUE(processed_study.all_assignments_to_one_group());
461
462 AddExperiment("xyz", 1, &study);
463 EXPECT_TRUE(processed_study.Init(&study, false));
464 EXPECT_FALSE(processed_study.all_assignments_to_one_group());
465
466 // Try with default group and first group being at 0.
467 Study study2;
468 study2.set_default_experiment_name("def");
469 AddExperiment("def", 0, &study2);
470 AddExperiment("xyz", 34, &study2);
471 EXPECT_TRUE(processed_study.Init(&study2, false));
472 EXPECT_TRUE(processed_study.all_assignments_to_one_group());
473 AddExperiment("abc", 12, &study2);
474 EXPECT_TRUE(processed_study.Init(&study2, false));
475 EXPECT_FALSE(processed_study.all_assignments_to_one_group());
476}
477
[email protected]f2fc7cf42013-11-07 21:53:03478TEST_F(VariationsSeedProcessorTest, VariationParams) {
asvitkine71411062016-05-17 20:09:44479 base::FieldTrialList field_trial_list(nullptr);
[email protected]1871a1702013-07-26 09:37:43480
481 Study study;
482 study.set_name("Study1");
483 study.set_default_experiment_name("B");
484
[email protected]5bd00ce2013-08-05 23:46:12485 Study_Experiment* experiment1 = AddExperiment("A", 1, &study);
[email protected]1871a1702013-07-26 09:37:43486 Study_Experiment_Param* param = experiment1->add_param();
487 param->set_name("x");
488 param->set_value("y");
489
[email protected]5bd00ce2013-08-05 23:46:12490 Study_Experiment* experiment2 = AddExperiment("B", 0, &study);
[email protected]1871a1702013-07-26 09:37:43491
asvitkine71411062016-05-17 20:09:44492 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43493 EXPECT_EQ("y", GetVariationParamValue("Study1", "x"));
494
495 study.set_name("Study2");
496 experiment1->set_probability_weight(0);
497 experiment2->set_probability_weight(1);
asvitkine71411062016-05-17 20:09:44498 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]1871a1702013-07-26 09:37:43499 EXPECT_EQ(std::string(), GetVariationParamValue("Study2", "x"));
500}
501
[email protected]f2fc7cf42013-11-07 21:53:03502TEST_F(VariationsSeedProcessorTest, VariationParamsWithForcingFlag) {
503 Study study = CreateStudyWithFlagGroups(100, 0, 0);
504 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag());
505 Study_Experiment_Param* param = study.mutable_experiment(1)->add_param();
506 param->set_name("x");
507 param->set_value("y");
508
avi1772c1a2014-12-22 22:42:33509 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
asvitkine71411062016-05-17 20:09:44510 base::FieldTrialList field_trial_list(nullptr);
511 EXPECT_TRUE(CreateTrialFromStudy(study));
[email protected]f2fc7cf42013-11-07 21:53:03512 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name()));
513 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x"));
514}
515
516TEST_F(VariationsSeedProcessorTest, StartsActive) {
asvitkine71411062016-05-17 20:09:44517 base::FieldTrialList field_trial_list(nullptr);
[email protected]f0b95fa2013-10-10 21:35:11518
519 VariationsSeed seed;
520 Study* study1 = seed.add_study();
521 study1->set_name("A");
522 study1->set_default_experiment_name("Default");
523 AddExperiment("AA", 100, study1);
524 AddExperiment("Default", 0, study1);
525
526 Study* study2 = seed.add_study();
527 study2->set_name("B");
528 study2->set_default_experiment_name("Default");
529 AddExperiment("BB", 100, study2);
530 AddExperiment("Default", 0, study2);
531 study2->set_activation_type(Study_ActivationType_ACTIVATION_AUTO);
532
533 Study* study3 = seed.add_study();
534 study3->set_name("C");
535 study3->set_default_experiment_name("Default");
536 AddExperiment("CC", 100, study3);
537 AddExperiment("Default", 0, study3);
538 study3->set_activation_type(Study_ActivationType_ACTIVATION_EXPLICIT);
539
isherman52a81bd2017-06-07 23:30:06540 ClientFilterableState client_state;
541 client_state.locale = "en-CA";
542 client_state.reference_date = base::Time::Now();
543 client_state.version = base::Version("20.0.0.0");
544 client_state.channel = Study::STABLE;
545 client_state.form_factor = Study::DESKTOP;
546 client_state.platform = Study::PLATFORM_ANDROID;
547
[email protected]f0b95fa2013-10-10 21:35:11548 VariationsSeedProcessor seed_processor;
isherman52a81bd2017-06-07 23:30:06549 seed_processor.CreateTrialsFromSeed(seed, client_state,
550 override_callback_.callback(), nullptr,
551 &feature_list_);
[email protected]f0b95fa2013-10-10 21:35:11552
553 // Non-specified and ACTIVATION_EXPLICIT should not start active, but
554 // ACTIVATION_AUTO should.
asvitkine11f882b42015-09-24 16:57:39555 EXPECT_FALSE(base::FieldTrialList::IsTrialActive("A"));
556 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("B"));
557 EXPECT_FALSE(base::FieldTrialList::IsTrialActive("C"));
[email protected]f0b95fa2013-10-10 21:35:11558
559 EXPECT_EQ("AA", base::FieldTrialList::FindFullName("A"));
560 EXPECT_EQ("BB", base::FieldTrialList::FindFullName("B"));
561 EXPECT_EQ("CC", base::FieldTrialList::FindFullName("C"));
562
563 // Now, all studies should be active.
asvitkine11f882b42015-09-24 16:57:39564 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("A"));
565 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("B"));
566 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("C"));
[email protected]f0b95fa2013-10-10 21:35:11567}
568
[email protected]85868c4a2014-02-07 18:23:05569TEST_F(VariationsSeedProcessorTest, StartsActiveWithFlag) {
avi1772c1a2014-12-22 22:42:33570 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
[email protected]85868c4a2014-02-07 18:23:05571
asvitkine71411062016-05-17 20:09:44572 base::FieldTrialList field_trial_list(nullptr);
[email protected]85868c4a2014-02-07 18:23:05573
574 Study study = CreateStudyWithFlagGroups(100, 0, 0);
575 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO);
576
asvitkine71411062016-05-17 20:09:44577 EXPECT_TRUE(CreateTrialFromStudy(study));
asvitkine11f882b42015-09-24 16:57:39578 EXPECT_TRUE(base::FieldTrialList::IsTrialActive(kFlagStudyName));
[email protected]85868c4a2014-02-07 18:23:05579
580 EXPECT_EQ(kFlagGroup1Name,
581 base::FieldTrialList::FindFullName(kFlagStudyName));
582}
583
asvitkine2955e422014-09-03 18:15:40584TEST_F(VariationsSeedProcessorTest, ForcingFlagAlreadyForced) {
585 Study study = CreateStudyWithFlagGroups(100, 0, 0);
586 ASSERT_EQ(kNonFlagGroupName, study.experiment(0).name());
587 Study_Experiment_Param* param = study.mutable_experiment(0)->add_param();
588 param->set_name("x");
589 param->set_value("y");
590 study.mutable_experiment(0)->set_google_web_experiment_id(kExperimentId);
591
asvitkine71411062016-05-17 20:09:44592 base::FieldTrialList field_trial_list(nullptr);
asvitkine2955e422014-09-03 18:15:40593 base::FieldTrialList::CreateFieldTrial(kFlagStudyName, kNonFlagGroupName);
594
avi1772c1a2014-12-22 22:42:33595 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
asvitkine71411062016-05-17 20:09:44596 EXPECT_TRUE(CreateTrialFromStudy(study));
asvitkine2955e422014-09-03 18:15:40597 // The previously forced experiment should still hold.
598 EXPECT_EQ(kNonFlagGroupName,
599 base::FieldTrialList::FindFullName(study.name()));
600
601 // Check that params and experiment ids correspond.
602 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x"));
603 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName,
604 kNonFlagGroupName);
605 EXPECT_EQ(kExperimentId, id);
606}
607
asvitkine8423d172015-09-28 23:23:44608TEST_F(VariationsSeedProcessorTest, FeatureEnabledOrDisableByTrial) {
609 struct base::Feature kFeatureOffByDefault {
610 "kOff", base::FEATURE_DISABLED_BY_DEFAULT
611 };
612 struct base::Feature kFeatureOnByDefault {
613 "kOn", base::FEATURE_ENABLED_BY_DEFAULT
614 };
615 struct base::Feature kUnrelatedFeature {
616 "kUnrelated", base::FEATURE_DISABLED_BY_DEFAULT
617 };
618
619 struct {
620 const char* enable_feature;
621 const char* disable_feature;
622 bool expected_feature_off_state;
623 bool expected_feature_on_state;
624 } test_cases[] = {
625 {nullptr, nullptr, false, true},
626 {kFeatureOnByDefault.name, nullptr, false, true},
627 {kFeatureOffByDefault.name, nullptr, true, true},
628 {nullptr, kFeatureOnByDefault.name, false, false},
629 {nullptr, kFeatureOffByDefault.name, false, true},
630 };
631
632 for (size_t i = 0; i < arraysize(test_cases); i++) {
633 const auto& test_case = test_cases[i];
634 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
635
asvitkine71411062016-05-17 20:09:44636 base::FieldTrialList field_trial_list(nullptr);
dcheng3f767dc32016-04-25 22:54:22637 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
asvitkine8423d172015-09-28 23:23:44638
639 Study study;
640 study.set_name("Study1");
641 study.set_default_experiment_name("B");
642 AddExperiment("B", 0, &study);
643
644 Study_Experiment* experiment = AddExperiment("A", 1, &study);
645 Study_Experiment_FeatureAssociation* association =
646 experiment->mutable_feature_association();
647 if (test_case.enable_feature)
648 association->add_enable_feature(test_case.enable_feature);
649 else if (test_case.disable_feature)
650 association->add_disable_feature(test_case.disable_feature);
651
asvitkine71411062016-05-17 20:09:44652 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
asvitkine9499b8d2016-08-09 05:37:07653 base::test::ScopedFeatureList scoped_feature_list;
654 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
asvitkine8423d172015-09-28 23:23:44655
656 // |kUnrelatedFeature| should not be affected.
657 EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature));
658
659 // Before the associated feature is queried, the trial shouldn't be active.
660 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name()));
661
662 EXPECT_EQ(test_case.expected_feature_off_state,
663 base::FeatureList::IsEnabled(kFeatureOffByDefault));
664 EXPECT_EQ(test_case.expected_feature_on_state,
665 base::FeatureList::IsEnabled(kFeatureOnByDefault));
666
667 // The field trial should get activated if it had a feature association.
668 const bool expected_field_trial_active =
669 test_case.enable_feature || test_case.disable_feature;
670 EXPECT_EQ(expected_field_trial_active,
671 base::FieldTrialList::IsTrialActive(study.name()));
672 }
673}
674
675TEST_F(VariationsSeedProcessorTest, FeatureAssociationAndForcing) {
676 struct base::Feature kFeatureOffByDefault {
677 "kFeatureOffByDefault", base::FEATURE_DISABLED_BY_DEFAULT
678 };
679 struct base::Feature kFeatureOnByDefault {
680 "kFeatureOnByDefault", base::FEATURE_ENABLED_BY_DEFAULT
681 };
682
683 enum OneHundredPercentGroup {
684 DEFAULT_GROUP,
685 ENABLE_GROUP,
686 DISABLE_GROUP,
687 };
688
689 const char kDefaultGroup[] = "Default";
690 const char kEnabledGroup[] = "Enabled";
691 const char kDisabledGroup[] = "Disabled";
692 const char kForcedOnGroup[] = "ForcedOn";
693 const char kForcedOffGroup[] = "ForcedOff";
694
695 struct {
696 const base::Feature& feature;
697 const char* enable_features_command_line;
698 const char* disable_features_command_line;
699 OneHundredPercentGroup one_hundred_percent_group;
700
701 const char* expected_group;
702 bool expected_feature_state;
703 bool expected_trial_activated;
704 } test_cases[] = {
705 // Check what happens without and command-line forcing flags - that the
706 // |one_hundred_percent_group| gets correctly selected and does the right
707 // thing w.r.t. to affecting the feature / activating the trial.
asvitkine64e9e112016-03-17 17:32:00708 {kFeatureOffByDefault, "", "", DEFAULT_GROUP, kDefaultGroup, false, true},
asvitkine8423d172015-09-28 23:23:44709 {kFeatureOffByDefault, "", "", ENABLE_GROUP, kEnabledGroup, true, true},
710 {kFeatureOffByDefault, "", "", DISABLE_GROUP, kDisabledGroup, false,
711 true},
712
713 // Do the same as above, but for kFeatureOnByDefault feature.
asvitkine64e9e112016-03-17 17:32:00714 {kFeatureOnByDefault, "", "", DEFAULT_GROUP, kDefaultGroup, true, true},
asvitkine8423d172015-09-28 23:23:44715 {kFeatureOnByDefault, "", "", ENABLE_GROUP, kEnabledGroup, true, true},
716 {kFeatureOnByDefault, "", "", DISABLE_GROUP, kDisabledGroup, false, true},
717
718 // Test forcing each feature on and off through the command-line and that
719 // the correct associated experiment gets chosen.
720 {kFeatureOffByDefault, kFeatureOffByDefault.name, "", DEFAULT_GROUP,
721 kForcedOnGroup, true, true},
722 {kFeatureOffByDefault, "", kFeatureOffByDefault.name, DEFAULT_GROUP,
723 kForcedOffGroup, false, true},
724 {kFeatureOnByDefault, kFeatureOnByDefault.name, "", DEFAULT_GROUP,
725 kForcedOnGroup, true, true},
726 {kFeatureOnByDefault, "", kFeatureOnByDefault.name, DEFAULT_GROUP,
727 kForcedOffGroup, false, true},
728
729 // Check that even if a feature should be enabled or disabled based on the
730 // the experiment probability weights, the forcing flag association still
731 // takes precedence. This is 4 cases as above, but with different values
732 // for |one_hundred_percent_group|.
733 {kFeatureOffByDefault, kFeatureOffByDefault.name, "", ENABLE_GROUP,
734 kForcedOnGroup, true, true},
735 {kFeatureOffByDefault, "", kFeatureOffByDefault.name, ENABLE_GROUP,
736 kForcedOffGroup, false, true},
737 {kFeatureOnByDefault, kFeatureOnByDefault.name, "", ENABLE_GROUP,
738 kForcedOnGroup, true, true},
739 {kFeatureOnByDefault, "", kFeatureOnByDefault.name, ENABLE_GROUP,
740 kForcedOffGroup, false, true},
741 {kFeatureOffByDefault, kFeatureOffByDefault.name, "", DISABLE_GROUP,
742 kForcedOnGroup, true, true},
743 {kFeatureOffByDefault, "", kFeatureOffByDefault.name, DISABLE_GROUP,
744 kForcedOffGroup, false, true},
745 {kFeatureOnByDefault, kFeatureOnByDefault.name, "", DISABLE_GROUP,
746 kForcedOnGroup, true, true},
747 {kFeatureOnByDefault, "", kFeatureOnByDefault.name, DISABLE_GROUP,
748 kForcedOffGroup, false, true},
749 };
750
751 for (size_t i = 0; i < arraysize(test_cases); i++) {
752 const auto& test_case = test_cases[i];
753 const int group = test_case.one_hundred_percent_group;
754 SCOPED_TRACE(base::StringPrintf(
755 "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name,
756 test_case.enable_features_command_line,
757 test_case.disable_features_command_line, static_cast<int>(group)));
758
asvitkine71411062016-05-17 20:09:44759 base::FieldTrialList field_trial_list(nullptr);
dcheng3f767dc32016-04-25 22:54:22760 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
asvitkine8423d172015-09-28 23:23:44761 feature_list->InitializeFromCommandLine(
762 test_case.enable_features_command_line,
763 test_case.disable_features_command_line);
764
765 Study study;
766 study.set_name("Study1");
asvitkine71411062016-05-17 20:09:44767 study.set_default_experiment_name(kDefaultGroup);
asvitkine8423d172015-09-28 23:23:44768 AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study);
769
770 Study_Experiment* feature_enable =
771 AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study);
772 feature_enable->mutable_feature_association()->add_enable_feature(
773 test_case.feature.name);
774
775 Study_Experiment* feature_disable =
776 AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study);
777 feature_disable->mutable_feature_association()->add_disable_feature(
778 test_case.feature.name);
779
780 AddExperiment(kForcedOnGroup, 0, &study)
781 ->mutable_feature_association()
782 ->set_forcing_feature_on(test_case.feature.name);
783 AddExperiment(kForcedOffGroup, 0, &study)
784 ->mutable_feature_association()
785 ->set_forcing_feature_off(test_case.feature.name);
786
asvitkine71411062016-05-17 20:09:44787 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
asvitkine9499b8d2016-08-09 05:37:07788 base::test::ScopedFeatureList scoped_feature_list;
789 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
asvitkine8423d172015-09-28 23:23:44790
791 // Trial should not be activated initially, but later might get activated
792 // depending on the expected values.
793 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name()));
794 EXPECT_EQ(test_case.expected_feature_state,
795 base::FeatureList::IsEnabled(test_case.feature));
796 EXPECT_EQ(test_case.expected_trial_activated,
797 base::FieldTrialList::IsTrialActive(study.name()));
798 }
799}
800
asvitkine71411062016-05-17 20:09:44801TEST_F(VariationsSeedProcessorTest, FeaturesInExpiredStudies) {
802 struct base::Feature kDisabledFeature {
803 "kDisabledFeature", base::FEATURE_DISABLED_BY_DEFAULT
804 };
805 struct base::Feature kEnabledFeature {
806 "kEnabledFeature", base::FEATURE_ENABLED_BY_DEFAULT
807 };
808 const base::Time now = base::Time::Now();
809 const base::Time year_ago = now - base::TimeDelta::FromDays(365);
810 const base::Time year_later = now + base::TimeDelta::FromDays(365);
811
812 struct {
813 const base::Feature& feature;
814 bool study_force_feature_state;
815 base::Time expiry_date;
816 bool expected_feature_enabled;
817 } test_cases[] = {
818 {kDisabledFeature, true, year_ago, false},
819 {kDisabledFeature, true, year_later, true},
820 {kEnabledFeature, false, year_ago, true},
821 {kEnabledFeature, false, year_later, false},
822 };
823
824 for (size_t i = 0; i < arraysize(test_cases); i++) {
825 const auto& test_case = test_cases[i];
826 SCOPED_TRACE(
827 base::StringPrintf("Test[%" PRIuS "]: %s", i, test_case.feature.name));
828
829 base::FieldTrialList field_trial_list(nullptr);
asvitkine71411062016-05-17 20:09:44830 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
831 feature_list->InitializeFromCommandLine(std::string(), std::string());
832
833 // Expired study with a 100% feature group and a default group that has no
834 // feature association.
835 Study study;
836 study.set_name("Study1");
837 study.set_default_experiment_name("Default");
838
839 study.set_expiry_date(TimeToProtoTime(test_case.expiry_date));
840
841 AddExperiment("Default", 0, &study);
842 Study_Experiment* feature_experiment = AddExperiment("Feature", 1, &study);
843 if (test_case.study_force_feature_state) {
844 feature_experiment->mutable_feature_association()->add_enable_feature(
845 test_case.feature.name);
846 } else {
847 feature_experiment->mutable_feature_association()->add_disable_feature(
848 test_case.feature.name);
849 }
850
851 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
asvitkine9499b8d2016-08-09 05:37:07852 base::test::ScopedFeatureList scoped_feature_list;
853 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
asvitkine71411062016-05-17 20:09:44854
jwd5ff54102017-01-06 18:09:34855 // The feature should not be enabled, because the study is expired.
asvitkine71411062016-05-17 20:09:44856 EXPECT_EQ(test_case.expected_feature_enabled,
857 base::FeatureList::IsEnabled(test_case.feature));
858 }
859}
860
jwd5ff54102017-01-06 18:09:34861TEST_F(VariationsSeedProcessorTest, NoDefaultExperiment) {
862 base::FieldTrialList field_trial_list(nullptr);
863
864 Study study;
865 study.set_name("Study1");
866
867 AddExperiment("A", 1, &study);
868
869 EXPECT_TRUE(CreateTrialFromStudy(study));
870
871 base::FieldTrial* trial = base::FieldTrialList::Find("Study1");
872 trial->Disable();
873
874 EXPECT_EQ(ProcessedStudy::kGenericDefaultExperimentName,
875 base::FieldTrialList::FindFullName("Study1"));
876}
877
asvitkine3cac35f2017-06-03 02:02:27878TEST_F(VariationsSeedProcessorTest, ExistingFieldTrial_ExpiredByConfig) {
879 static struct base::Feature kFeature {
880 "FeatureName", base::FEATURE_ENABLED_BY_DEFAULT
881 };
882 base::FieldTrialList field_trial_list(nullptr);
883
884 // In this case, an existing forced trial exists with a different default
885 // group than the study config, which is expired. This tests that we don't
886 // crash in such a case.
887 auto* trial = base::FieldTrialList::FactoryGetFieldTrial(
888 "Study1", 100, "ExistingDefault", base::FieldTrialList::kNoExpirationYear,
889 1, 1, base::FieldTrial::SESSION_RANDOMIZED, nullptr);
890 trial->AppendGroup("A", 100);
891 trial->SetForced();
892
893 Study study;
894 study.set_name("Study1");
895 const base::Time year_ago =
896 base::Time::Now() - base::TimeDelta::FromDays(365);
897 study.set_expiry_date(TimeToProtoTime(year_ago));
898 auto* exp1 = AddExperiment("A", 1, &study);
899 exp1->mutable_feature_association()->add_enable_feature(kFeature.name);
900 AddExperiment("Default", 1, &study);
901 study.set_default_experiment_name("Default");
902
903 EXPECT_TRUE(CreateTrialFromStudy(study));
904
905 // The expected effect is that processing the server config will expire
906 // the existing trial.
907 EXPECT_EQ("ExistingDefault", trial->group_name());
908}
909
910TEST_F(VariationsSeedProcessorTest, ExpiredStudy_NoDefaultGroup) {
911 static struct base::Feature kFeature {
912 "FeatureName", base::FEATURE_ENABLED_BY_DEFAULT
913 };
914 base::FieldTrialList field_trial_list(nullptr);
915
916 // Although it's not expected for the server to provide a study with an expiry
917 // date set, but not default experiment, this tests that we don't crash if
918 // that happens.
919 Study study;
920 study.set_name("Study1");
921 const base::Time year_ago =
922 base::Time::Now() - base::TimeDelta::FromDays(365);
923 study.set_expiry_date(TimeToProtoTime(year_ago));
924 auto* exp1 = AddExperiment("A", 1, &study);
925 exp1->mutable_feature_association()->add_enable_feature(kFeature.name);
926
927 EXPECT_TRUE(CreateTrialFromStudy(study));
928 EXPECT_EQ("VariationsDefaultExperiment",
929 base::FieldTrialList::FindFullName("Study1"));
930}
931
jwd67c08f752016-05-18 21:04:59932TEST_F(VariationsSeedProcessorTest, LowEntropyStudyTest) {
933 const std::string kTrial1Name = "A";
934 const std::string kTrial2Name = "B";
935 const std::string kGroup1Name = "AA";
936 const std::string kDefaultName = "Default";
937
938 VariationsSeed seed;
939 Study* study1 = seed.add_study();
940 study1->set_name(kTrial1Name);
941 study1->set_consistency(variations::Study_Consistency_PERMANENT);
942 study1->set_default_experiment_name(kDefaultName);
943 AddExperiment(kGroup1Name, 50, study1);
944 AddExperiment(kDefaultName, 50, study1);
945 Study* study2 = seed.add_study();
946 study2->set_name(kTrial2Name);
947 study2->set_consistency(variations::Study_Consistency_PERMANENT);
948 study2->set_default_experiment_name(kDefaultName);
949 AddExperiment(kGroup1Name, 50, study2);
950 AddExperiment(kDefaultName, 50, study2);
951 study2->mutable_experiment(0)->set_google_web_experiment_id(kExperimentId);
952
953 // An entorpy value of 0.1 will cause the AA group to be chosen, since AA is
954 // the only non-default group, and has a probability percent above 0.1.
robliao79393ffb2016-09-21 18:45:29955 base::FieldTrialList field_trial_list(
956 base::MakeUnique<base::MockEntropyProvider>(0.1));
jwd67c08f752016-05-18 21:04:59957
958 // Use a stack instance, since nothing takes ownership of this provider.
959 // This entropy value will cause the default group to be chosen since it's a
960 // 50/50 trial.
961 base::MockEntropyProvider mock_low_entropy_provider(0.9);
962
963 EXPECT_TRUE(CreateTrialFromStudyWithEntropyOverride(
964 *study1, &mock_low_entropy_provider));
965 EXPECT_TRUE(CreateTrialFromStudyWithEntropyOverride(
966 *study2, &mock_low_entropy_provider));
967
968 // Since no experiment in study1 sends experiment IDs, it will use the high
969 // entropy provider, which selects the non-default group.
970 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrial1Name));
971
972 // Since an experiment in study2 has google_web_experiment_id set, it will use
973 // the low entropy provider, which selects the default group.
974 EXPECT_EQ(kDefaultName, base::FieldTrialList::FindFullName(kTrial2Name));
975}
976
[email protected]59b6f672014-07-26 18:35:47977} // namespace variations