xref: /aosp_15_r20/external/libchrome/base/metrics/field_trial_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/metrics/field_trial.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include "base/base_switches.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/build_time.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/feature_list.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/message_loop/message_loop.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/metrics/field_trial_param_associator.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/rand_util.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
21*635a8641SAndroid Build Coastguard Worker #include "base/test/mock_entropy_provider.h"
22*635a8641SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
23*635a8641SAndroid Build Coastguard Worker #include "base/test/test_shared_memory_util.h"
24*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
25*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker namespace base {
28*635a8641SAndroid Build Coastguard Worker 
29*635a8641SAndroid Build Coastguard Worker namespace {
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker // Default group name used by several tests.
32*635a8641SAndroid Build Coastguard Worker const char kDefaultGroupName[] = "DefaultGroup";
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker // Call FieldTrialList::FactoryGetFieldTrial() with a future expiry date.
CreateFieldTrial(const std::string & trial_name,int total_probability,const std::string & default_group_name,int * default_group_number)35*635a8641SAndroid Build Coastguard Worker scoped_refptr<FieldTrial> CreateFieldTrial(
36*635a8641SAndroid Build Coastguard Worker     const std::string& trial_name,
37*635a8641SAndroid Build Coastguard Worker     int total_probability,
38*635a8641SAndroid Build Coastguard Worker     const std::string& default_group_name,
39*635a8641SAndroid Build Coastguard Worker     int* default_group_number) {
40*635a8641SAndroid Build Coastguard Worker   return FieldTrialList::FactoryGetFieldTrial(
41*635a8641SAndroid Build Coastguard Worker       trial_name, total_probability, default_group_name,
42*635a8641SAndroid Build Coastguard Worker       FieldTrialList::kNoExpirationYear, 1, 1, FieldTrial::SESSION_RANDOMIZED,
43*635a8641SAndroid Build Coastguard Worker       default_group_number);
44*635a8641SAndroid Build Coastguard Worker }
45*635a8641SAndroid Build Coastguard Worker 
OneYearBeforeBuildTime()46*635a8641SAndroid Build Coastguard Worker int OneYearBeforeBuildTime() {
47*635a8641SAndroid Build Coastguard Worker   Time one_year_before_build_time = GetBuildTime() - TimeDelta::FromDays(365);
48*635a8641SAndroid Build Coastguard Worker   Time::Exploded exploded;
49*635a8641SAndroid Build Coastguard Worker   one_year_before_build_time.LocalExplode(&exploded);
50*635a8641SAndroid Build Coastguard Worker   return exploded.year;
51*635a8641SAndroid Build Coastguard Worker }
52*635a8641SAndroid Build Coastguard Worker 
53*635a8641SAndroid Build Coastguard Worker // FieldTrialList::Observer implementation for testing.
54*635a8641SAndroid Build Coastguard Worker class TestFieldTrialObserver : public FieldTrialList::Observer {
55*635a8641SAndroid Build Coastguard Worker  public:
56*635a8641SAndroid Build Coastguard Worker   enum Type {
57*635a8641SAndroid Build Coastguard Worker     ASYNCHRONOUS,
58*635a8641SAndroid Build Coastguard Worker     SYNCHRONOUS,
59*635a8641SAndroid Build Coastguard Worker   };
60*635a8641SAndroid Build Coastguard Worker 
TestFieldTrialObserver(Type type)61*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver(Type type) : type_(type) {
62*635a8641SAndroid Build Coastguard Worker     if (type == SYNCHRONOUS)
63*635a8641SAndroid Build Coastguard Worker       FieldTrialList::SetSynchronousObserver(this);
64*635a8641SAndroid Build Coastguard Worker     else
65*635a8641SAndroid Build Coastguard Worker       FieldTrialList::AddObserver(this);
66*635a8641SAndroid Build Coastguard Worker   }
67*635a8641SAndroid Build Coastguard Worker 
~TestFieldTrialObserver()68*635a8641SAndroid Build Coastguard Worker   ~TestFieldTrialObserver() override {
69*635a8641SAndroid Build Coastguard Worker     if (type_ == SYNCHRONOUS)
70*635a8641SAndroid Build Coastguard Worker       FieldTrialList::RemoveSynchronousObserver(this);
71*635a8641SAndroid Build Coastguard Worker     else
72*635a8641SAndroid Build Coastguard Worker       FieldTrialList::RemoveObserver(this);
73*635a8641SAndroid Build Coastguard Worker   }
74*635a8641SAndroid Build Coastguard Worker 
OnFieldTrialGroupFinalized(const std::string & trial,const std::string & group)75*635a8641SAndroid Build Coastguard Worker   void OnFieldTrialGroupFinalized(const std::string& trial,
76*635a8641SAndroid Build Coastguard Worker                                   const std::string& group) override {
77*635a8641SAndroid Build Coastguard Worker     trial_name_ = trial;
78*635a8641SAndroid Build Coastguard Worker     group_name_ = group;
79*635a8641SAndroid Build Coastguard Worker   }
80*635a8641SAndroid Build Coastguard Worker 
trial_name() const81*635a8641SAndroid Build Coastguard Worker   const std::string& trial_name() const { return trial_name_; }
group_name() const82*635a8641SAndroid Build Coastguard Worker   const std::string& group_name() const { return group_name_; }
83*635a8641SAndroid Build Coastguard Worker 
84*635a8641SAndroid Build Coastguard Worker  private:
85*635a8641SAndroid Build Coastguard Worker   const Type type_;
86*635a8641SAndroid Build Coastguard Worker   std::string trial_name_;
87*635a8641SAndroid Build Coastguard Worker   std::string group_name_;
88*635a8641SAndroid Build Coastguard Worker 
89*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(TestFieldTrialObserver);
90*635a8641SAndroid Build Coastguard Worker };
91*635a8641SAndroid Build Coastguard Worker 
MockEscapeQueryParamValue(const std::string & input)92*635a8641SAndroid Build Coastguard Worker std::string MockEscapeQueryParamValue(const std::string& input) {
93*635a8641SAndroid Build Coastguard Worker   return input;
94*635a8641SAndroid Build Coastguard Worker }
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker }  // namespace
97*635a8641SAndroid Build Coastguard Worker 
98*635a8641SAndroid Build Coastguard Worker class FieldTrialTest : public ::testing::Test {
99*635a8641SAndroid Build Coastguard Worker  public:
FieldTrialTest()100*635a8641SAndroid Build Coastguard Worker   FieldTrialTest() : trial_list_(nullptr) {}
101*635a8641SAndroid Build Coastguard Worker 
102*635a8641SAndroid Build Coastguard Worker  private:
103*635a8641SAndroid Build Coastguard Worker   MessageLoop message_loop_;
104*635a8641SAndroid Build Coastguard Worker   FieldTrialList trial_list_;
105*635a8641SAndroid Build Coastguard Worker 
106*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(FieldTrialTest);
107*635a8641SAndroid Build Coastguard Worker };
108*635a8641SAndroid Build Coastguard Worker 
109*635a8641SAndroid Build Coastguard Worker // Test registration, and also check that destructors are called for trials.
TEST_F(FieldTrialTest,Registration)110*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Registration) {
111*635a8641SAndroid Build Coastguard Worker   const char name1[] = "name 1 test";
112*635a8641SAndroid Build Coastguard Worker   const char name2[] = "name 2 test";
113*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name1));
114*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name2));
115*635a8641SAndroid Build Coastguard Worker 
116*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial1 =
117*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(name1, 10, "default name 1 test", nullptr);
118*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
119*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(name1, trial1->trial_name());
120*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("", trial1->group_name_internal());
121*635a8641SAndroid Build Coastguard Worker 
122*635a8641SAndroid Build Coastguard Worker   trial1->AppendGroup(std::string(), 7);
123*635a8641SAndroid Build Coastguard Worker 
124*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
125*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name2));
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
128*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(name2, 10, "default name 2 test", nullptr);
129*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
130*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(name2, trial2->trial_name());
131*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("", trial2->group_name_internal());
132*635a8641SAndroid Build Coastguard Worker 
133*635a8641SAndroid Build Coastguard Worker   trial2->AppendGroup("a first group", 7);
134*635a8641SAndroid Build Coastguard Worker 
135*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
136*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial2.get(), FieldTrialList::Find(name2));
137*635a8641SAndroid Build Coastguard Worker   // Note: FieldTrialList should delete the objects at shutdown.
138*635a8641SAndroid Build Coastguard Worker }
139*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,AbsoluteProbabilities)140*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, AbsoluteProbabilities) {
141*635a8641SAndroid Build Coastguard Worker   char always_true[] = " always true";
142*635a8641SAndroid Build Coastguard Worker   char default_always_true[] = " default always true";
143*635a8641SAndroid Build Coastguard Worker   char always_false[] = " always false";
144*635a8641SAndroid Build Coastguard Worker   char default_always_false[] = " default always false";
145*635a8641SAndroid Build Coastguard Worker   for (int i = 1; i < 250; ++i) {
146*635a8641SAndroid Build Coastguard Worker     // Try lots of names, by changing the first character of the name.
147*635a8641SAndroid Build Coastguard Worker     char c = static_cast<char>(i);
148*635a8641SAndroid Build Coastguard Worker     always_true[0] = c;
149*635a8641SAndroid Build Coastguard Worker     default_always_true[0] = c;
150*635a8641SAndroid Build Coastguard Worker     always_false[0] = c;
151*635a8641SAndroid Build Coastguard Worker     default_always_false[0] = c;
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial_true =
154*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial(always_true, 10, default_always_true, nullptr);
155*635a8641SAndroid Build Coastguard Worker     const std::string winner = "TheWinner";
156*635a8641SAndroid Build Coastguard Worker     int winner_group = trial_true->AppendGroup(winner, 10);
157*635a8641SAndroid Build Coastguard Worker 
158*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(winner_group, trial_true->group());
159*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(winner, trial_true->group_name());
160*635a8641SAndroid Build Coastguard Worker 
161*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial_false =
162*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial(always_false, 10, default_always_false, nullptr);
163*635a8641SAndroid Build Coastguard Worker     int loser_group = trial_false->AppendGroup("ALoser", 0);
164*635a8641SAndroid Build Coastguard Worker 
165*635a8641SAndroid Build Coastguard Worker     EXPECT_NE(loser_group, trial_false->group());
166*635a8641SAndroid Build Coastguard Worker   }
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,RemainingProbability)169*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, RemainingProbability) {
170*635a8641SAndroid Build Coastguard Worker   // First create a test that hasn't had a winner yet.
171*635a8641SAndroid Build Coastguard Worker   const std::string winner = "Winner";
172*635a8641SAndroid Build Coastguard Worker   const std::string loser = "Loser";
173*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial;
174*635a8641SAndroid Build Coastguard Worker   int counter = 0;
175*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
176*635a8641SAndroid Build Coastguard Worker   do {
177*635a8641SAndroid Build Coastguard Worker     std::string name = StringPrintf("trial%d", ++counter);
178*635a8641SAndroid Build Coastguard Worker     trial = CreateFieldTrial(name, 10, winner, &default_group_number);
179*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup(loser, 5);  // 50% chance of not being chosen.
180*635a8641SAndroid Build Coastguard Worker     // If a group is not assigned, group_ will be kNotFinalized.
181*635a8641SAndroid Build Coastguard Worker   } while (trial->group_ != FieldTrial::kNotFinalized);
182*635a8641SAndroid Build Coastguard Worker 
183*635a8641SAndroid Build Coastguard Worker   // And that 'default' group (winner) should always win.
184*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group_number, trial->group());
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker   // And that winner should ALWAYS win.
187*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(winner, trial->group_name());
188*635a8641SAndroid Build Coastguard Worker }
189*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,FiftyFiftyProbability)190*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, FiftyFiftyProbability) {
191*635a8641SAndroid Build Coastguard Worker   // Check that even with small divisors, we have the proper probabilities, and
192*635a8641SAndroid Build Coastguard Worker   // all outcomes are possible.  Since this is a 50-50 test, it should get both
193*635a8641SAndroid Build Coastguard Worker   // outcomes in a few tries, but we'll try no more than 100 times (and be flaky
194*635a8641SAndroid Build Coastguard Worker   // with probability around 1 in 2^99).
195*635a8641SAndroid Build Coastguard Worker   bool first_winner = false;
196*635a8641SAndroid Build Coastguard Worker   bool second_winner = false;
197*635a8641SAndroid Build Coastguard Worker   int counter = 0;
198*635a8641SAndroid Build Coastguard Worker   do {
199*635a8641SAndroid Build Coastguard Worker     std::string name = StringPrintf("FiftyFifty%d", ++counter);
200*635a8641SAndroid Build Coastguard Worker     std::string default_group_name =
201*635a8641SAndroid Build Coastguard Worker         StringPrintf("Default FiftyFifty%d", ++counter);
202*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial =
203*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial(name, 2, default_group_name, nullptr);
204*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup("first", 1);  // 50% chance of being chosen.
205*635a8641SAndroid Build Coastguard Worker     // If group_ is kNotFinalized, then a group assignement hasn't been done.
206*635a8641SAndroid Build Coastguard Worker     if (trial->group_ != FieldTrial::kNotFinalized) {
207*635a8641SAndroid Build Coastguard Worker       first_winner = true;
208*635a8641SAndroid Build Coastguard Worker       continue;
209*635a8641SAndroid Build Coastguard Worker     }
210*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup("second", 1);  // Always chosen at this point.
211*635a8641SAndroid Build Coastguard Worker     EXPECT_NE(FieldTrial::kNotFinalized, trial->group());
212*635a8641SAndroid Build Coastguard Worker     second_winner = true;
213*635a8641SAndroid Build Coastguard Worker   } while ((!second_winner || !first_winner) && counter < 100);
214*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(second_winner);
215*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(first_winner);
216*635a8641SAndroid Build Coastguard Worker }
217*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,MiddleProbabilities)218*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, MiddleProbabilities) {
219*635a8641SAndroid Build Coastguard Worker   char name[] = " same name";
220*635a8641SAndroid Build Coastguard Worker   char default_group_name[] = " default same name";
221*635a8641SAndroid Build Coastguard Worker   bool false_event_seen = false;
222*635a8641SAndroid Build Coastguard Worker   bool true_event_seen = false;
223*635a8641SAndroid Build Coastguard Worker   for (int i = 1; i < 250; ++i) {
224*635a8641SAndroid Build Coastguard Worker     char c = static_cast<char>(i);
225*635a8641SAndroid Build Coastguard Worker     name[0] = c;
226*635a8641SAndroid Build Coastguard Worker     default_group_name[0] = c;
227*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial =
228*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial(name, 10, default_group_name, nullptr);
229*635a8641SAndroid Build Coastguard Worker     int might_win = trial->AppendGroup("MightWin", 5);
230*635a8641SAndroid Build Coastguard Worker 
231*635a8641SAndroid Build Coastguard Worker     if (trial->group() == might_win) {
232*635a8641SAndroid Build Coastguard Worker       true_event_seen = true;
233*635a8641SAndroid Build Coastguard Worker     } else {
234*635a8641SAndroid Build Coastguard Worker       false_event_seen = true;
235*635a8641SAndroid Build Coastguard Worker     }
236*635a8641SAndroid Build Coastguard Worker     if (false_event_seen && true_event_seen)
237*635a8641SAndroid Build Coastguard Worker       return;  // Successful test!!!
238*635a8641SAndroid Build Coastguard Worker   }
239*635a8641SAndroid Build Coastguard Worker   // Very surprising to get here. Probability should be around 1 in 2 ** 250.
240*635a8641SAndroid Build Coastguard Worker   // One of the following will fail.
241*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(false_event_seen);
242*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(true_event_seen);
243*635a8641SAndroid Build Coastguard Worker }
244*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,OneWinner)245*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, OneWinner) {
246*635a8641SAndroid Build Coastguard Worker   char name[] = "Some name";
247*635a8641SAndroid Build Coastguard Worker   char default_group_name[] = "Default some name";
248*635a8641SAndroid Build Coastguard Worker   int group_count(10);
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
251*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
252*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(name, group_count, default_group_name, nullptr);
253*635a8641SAndroid Build Coastguard Worker   int winner_index(-2);
254*635a8641SAndroid Build Coastguard Worker   std::string winner_name;
255*635a8641SAndroid Build Coastguard Worker 
256*635a8641SAndroid Build Coastguard Worker   for (int i = 1; i <= group_count; ++i) {
257*635a8641SAndroid Build Coastguard Worker     int might_win = trial->AppendGroup(std::string(), 1);
258*635a8641SAndroid Build Coastguard Worker 
259*635a8641SAndroid Build Coastguard Worker     // Because we keep appending groups, we want to see if the last group that
260*635a8641SAndroid Build Coastguard Worker     // was added has been assigned or not.
261*635a8641SAndroid Build Coastguard Worker     if (trial->group_ == might_win) {
262*635a8641SAndroid Build Coastguard Worker       EXPECT_EQ(-2, winner_index);
263*635a8641SAndroid Build Coastguard Worker       winner_index = might_win;
264*635a8641SAndroid Build Coastguard Worker       StringAppendF(&winner_name, "%d", might_win);
265*635a8641SAndroid Build Coastguard Worker       EXPECT_EQ(winner_name, trial->group_name());
266*635a8641SAndroid Build Coastguard Worker     }
267*635a8641SAndroid Build Coastguard Worker   }
268*635a8641SAndroid Build Coastguard Worker   EXPECT_GE(winner_index, 0);
269*635a8641SAndroid Build Coastguard Worker   // Since all groups cover the total probability, we should not have
270*635a8641SAndroid Build Coastguard Worker   // chosen the default group.
271*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(trial->group(), default_group_number);
272*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group(), winner_index);
273*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), winner_name);
274*635a8641SAndroid Build Coastguard Worker }
275*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DisableProbability)276*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DisableProbability) {
277*635a8641SAndroid Build Coastguard Worker   const std::string default_group_name = "Default group";
278*635a8641SAndroid Build Coastguard Worker   const std::string loser = "Loser";
279*635a8641SAndroid Build Coastguard Worker   const std::string name = "Trial";
280*635a8641SAndroid Build Coastguard Worker 
281*635a8641SAndroid Build Coastguard Worker   // Create a field trail that has expired.
282*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
283*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
284*635a8641SAndroid Build Coastguard Worker       name, 1000000000, default_group_name, OneYearBeforeBuildTime(), 1, 1,
285*635a8641SAndroid Build Coastguard Worker       FieldTrial::SESSION_RANDOMIZED,
286*635a8641SAndroid Build Coastguard Worker       &default_group_number);
287*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup(loser, 999999999);  // 99.9999999% chance of being chosen.
288*635a8641SAndroid Build Coastguard Worker 
289*635a8641SAndroid Build Coastguard Worker   // Because trial has expired, we should always be in the default group.
290*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group_number, trial->group());
291*635a8641SAndroid Build Coastguard Worker 
292*635a8641SAndroid Build Coastguard Worker   // And that default_group_name should ALWAYS win.
293*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group_name, trial->group_name());
294*635a8641SAndroid Build Coastguard Worker }
295*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ActiveGroups)296*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ActiveGroups) {
297*635a8641SAndroid Build Coastguard Worker   std::string no_group("No Group");
298*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
299*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(no_group, 10, "Default", nullptr);
300*635a8641SAndroid Build Coastguard Worker 
301*635a8641SAndroid Build Coastguard Worker   // There is no winner yet, so no NameGroupId should be returned.
302*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroup active_group;
303*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
304*635a8641SAndroid Build Coastguard Worker 
305*635a8641SAndroid Build Coastguard Worker   // Create a single winning group.
306*635a8641SAndroid Build Coastguard Worker   std::string one_winner("One Winner");
307*635a8641SAndroid Build Coastguard Worker   trial = CreateFieldTrial(one_winner, 10, "Default", nullptr);
308*635a8641SAndroid Build Coastguard Worker   std::string winner("Winner");
309*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup(winner, 10);
310*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
311*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
312*635a8641SAndroid Build Coastguard Worker   trial->group();
313*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(trial->GetActiveGroup(&active_group));
314*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(one_winner, active_group.trial_name);
315*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(winner, active_group.group_name);
316*635a8641SAndroid Build Coastguard Worker 
317*635a8641SAndroid Build Coastguard Worker   std::string multi_group("MultiGroup");
318*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> multi_group_trial =
319*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(multi_group, 9, "Default", nullptr);
320*635a8641SAndroid Build Coastguard Worker 
321*635a8641SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("Me", 3);
322*635a8641SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("You", 3);
323*635a8641SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("Them", 3);
324*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(multi_group_trial->GetActiveGroup(&active_group));
325*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
326*635a8641SAndroid Build Coastguard Worker   multi_group_trial->group();
327*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(multi_group_trial->GetActiveGroup(&active_group));
328*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(multi_group, active_group.trial_name);
329*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(multi_group_trial->group_name(), active_group.group_name);
330*635a8641SAndroid Build Coastguard Worker 
331*635a8641SAndroid Build Coastguard Worker   // Now check if the list is built properly...
332*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
333*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
334*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(2U, active_groups.size());
335*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < active_groups.size(); ++i) {
336*635a8641SAndroid Build Coastguard Worker     // Order is not guaranteed, so check all values.
337*635a8641SAndroid Build Coastguard Worker     EXPECT_NE(no_group, active_groups[i].trial_name);
338*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(one_winner != active_groups[i].trial_name ||
339*635a8641SAndroid Build Coastguard Worker                 winner == active_groups[i].group_name);
340*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(multi_group != active_groups[i].trial_name ||
341*635a8641SAndroid Build Coastguard Worker                 multi_group_trial->group_name() == active_groups[i].group_name);
342*635a8641SAndroid Build Coastguard Worker   }
343*635a8641SAndroid Build Coastguard Worker }
344*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,GetActiveFieldTrialGroupsFromString)345*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, GetActiveFieldTrialGroupsFromString) {
346*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
347*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroupsFromString("*A/X/B/Y/*C/Z",
348*635a8641SAndroid Build Coastguard Worker                                                       &active_groups);
349*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
350*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("A", active_groups[0].trial_name);
351*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("X", active_groups[0].group_name);
352*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("C", active_groups[1].trial_name);
353*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Z", active_groups[1].group_name);
354*635a8641SAndroid Build Coastguard Worker }
355*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ActiveGroupsNotFinalized)356*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ActiveGroupsNotFinalized) {
357*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TestTrial";
358*635a8641SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
359*635a8641SAndroid Build Coastguard Worker 
360*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
361*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
362*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
363*635a8641SAndroid Build Coastguard Worker   const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
364*635a8641SAndroid Build Coastguard Worker 
365*635a8641SAndroid Build Coastguard Worker   // Before |group()| is called, |GetActiveGroup()| should return false.
366*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroup active_group;
367*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
368*635a8641SAndroid Build Coastguard Worker 
369*635a8641SAndroid Build Coastguard Worker   // |GetActiveFieldTrialGroups()| should also not include the trial.
370*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
371*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
372*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
373*635a8641SAndroid Build Coastguard Worker 
374*635a8641SAndroid Build Coastguard Worker   // After |group()| has been called, both APIs should succeed.
375*635a8641SAndroid Build Coastguard Worker   const int chosen_group = trial->group();
376*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
377*635a8641SAndroid Build Coastguard Worker 
378*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(trial->GetActiveGroup(&active_group));
379*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, active_group.trial_name);
380*635a8641SAndroid Build Coastguard Worker   if (chosen_group == default_group)
381*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kDefaultGroupName, active_group.group_name);
382*635a8641SAndroid Build Coastguard Worker   else
383*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kSecondaryGroupName, active_group.group_name);
384*635a8641SAndroid Build Coastguard Worker 
385*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
386*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(1U, active_groups.size());
387*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, active_groups[0].trial_name);
388*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(active_group.group_name, active_groups[0].group_name);
389*635a8641SAndroid Build Coastguard Worker }
390*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,GetGroupNameWithoutActivation)391*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, GetGroupNameWithoutActivation) {
392*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TestTrial";
393*635a8641SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
394*635a8641SAndroid Build Coastguard Worker 
395*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
396*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
397*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
398*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup(kSecondaryGroupName, 50);
399*635a8641SAndroid Build Coastguard Worker 
400*635a8641SAndroid Build Coastguard Worker   // The trial should start inactive.
401*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
402*635a8641SAndroid Build Coastguard Worker 
403*635a8641SAndroid Build Coastguard Worker   // Calling |GetGroupNameWithoutActivation()| should not activate the trial.
404*635a8641SAndroid Build Coastguard Worker   std::string group_name = trial->GetGroupNameWithoutActivation();
405*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(group_name.empty());
406*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
407*635a8641SAndroid Build Coastguard Worker 
408*635a8641SAndroid Build Coastguard Worker   // Calling |group_name()| should activate it and return the same group name.
409*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(group_name, trial->group_name());
410*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
411*635a8641SAndroid Build Coastguard Worker }
412*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,Save)413*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Save) {
414*635a8641SAndroid Build Coastguard Worker   std::string save_string;
415*635a8641SAndroid Build Coastguard Worker 
416*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
417*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Some name", 10, "Default some name", nullptr);
418*635a8641SAndroid Build Coastguard Worker   // There is no winner yet, so no textual group name is associated with trial.
419*635a8641SAndroid Build Coastguard Worker   // In this case, the trial should not be included.
420*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("", trial->group_name_internal());
421*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&save_string);
422*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("", save_string);
423*635a8641SAndroid Build Coastguard Worker   save_string.clear();
424*635a8641SAndroid Build Coastguard Worker 
425*635a8641SAndroid Build Coastguard Worker   // Create a winning group.
426*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
427*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
428*635a8641SAndroid Build Coastguard Worker   trial->group();
429*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&save_string);
430*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Winner/", save_string);
431*635a8641SAndroid Build Coastguard Worker   save_string.clear();
432*635a8641SAndroid Build Coastguard Worker 
433*635a8641SAndroid Build Coastguard Worker   // Create a second trial and winning group.
434*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
435*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("xxx", 10, "Default xxx", nullptr);
436*635a8641SAndroid Build Coastguard Worker   trial2->AppendGroup("yyyy", 10);
437*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
438*635a8641SAndroid Build Coastguard Worker   trial2->group();
439*635a8641SAndroid Build Coastguard Worker 
440*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&save_string);
441*635a8641SAndroid Build Coastguard Worker   // We assume names are alphabetized... though this is not critical.
442*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Winner/xxx/yyyy/", save_string);
443*635a8641SAndroid Build Coastguard Worker   save_string.clear();
444*635a8641SAndroid Build Coastguard Worker 
445*635a8641SAndroid Build Coastguard Worker   // Create a third trial with only the default group.
446*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial3 =
447*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("zzz", 10, "default", nullptr);
448*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
449*635a8641SAndroid Build Coastguard Worker   trial3->group();
450*635a8641SAndroid Build Coastguard Worker 
451*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&save_string);
452*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Winner/xxx/yyyy/zzz/default/", save_string);
453*635a8641SAndroid Build Coastguard Worker }
454*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SaveAll)455*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SaveAll) {
456*635a8641SAndroid Build Coastguard Worker   std::string save_string;
457*635a8641SAndroid Build Coastguard Worker 
458*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
459*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Some name", 10, "Default some name", nullptr);
460*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("", trial->group_name_internal());
461*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, false);
462*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/", save_string);
463*635a8641SAndroid Build Coastguard Worker   // Getting all states should have finalized the trial.
464*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Default some name", trial->group_name_internal());
465*635a8641SAndroid Build Coastguard Worker   save_string.clear();
466*635a8641SAndroid Build Coastguard Worker 
467*635a8641SAndroid Build Coastguard Worker   // Create a winning group.
468*635a8641SAndroid Build Coastguard Worker   trial = CreateFieldTrial("trial2", 10, "Default some name", nullptr);
469*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
470*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
471*635a8641SAndroid Build Coastguard Worker   trial->group();
472*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, false);
473*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/", save_string);
474*635a8641SAndroid Build Coastguard Worker   save_string.clear();
475*635a8641SAndroid Build Coastguard Worker 
476*635a8641SAndroid Build Coastguard Worker   // Create a second trial and winning group.
477*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
478*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("xxx", 10, "Default xxx", nullptr);
479*635a8641SAndroid Build Coastguard Worker   trial2->AppendGroup("yyyy", 10);
480*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
481*635a8641SAndroid Build Coastguard Worker   trial2->group();
482*635a8641SAndroid Build Coastguard Worker 
483*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, false);
484*635a8641SAndroid Build Coastguard Worker   // We assume names are alphabetized... though this is not critical.
485*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/",
486*635a8641SAndroid Build Coastguard Worker             save_string);
487*635a8641SAndroid Build Coastguard Worker   save_string.clear();
488*635a8641SAndroid Build Coastguard Worker 
489*635a8641SAndroid Build Coastguard Worker   // Create a third trial with only the default group.
490*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial3 =
491*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("zzz", 10, "default", nullptr);
492*635a8641SAndroid Build Coastguard Worker 
493*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, false);
494*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default/",
495*635a8641SAndroid Build Coastguard Worker             save_string);
496*635a8641SAndroid Build Coastguard Worker 
497*635a8641SAndroid Build Coastguard Worker   // Create expired study.
498*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
499*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> expired_trial =
500*635a8641SAndroid Build Coastguard Worker       FieldTrialList::FactoryGetFieldTrial(
501*635a8641SAndroid Build Coastguard Worker           "Expired trial name", 1000000000, "Default group",
502*635a8641SAndroid Build Coastguard Worker           OneYearBeforeBuildTime(), 1, 1, FieldTrial::SESSION_RANDOMIZED,
503*635a8641SAndroid Build Coastguard Worker           &default_group_number);
504*635a8641SAndroid Build Coastguard Worker   expired_trial->AppendGroup("Expired trial group name", 999999999);
505*635a8641SAndroid Build Coastguard Worker 
506*635a8641SAndroid Build Coastguard Worker   save_string.clear();
507*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, false);
508*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default/",
509*635a8641SAndroid Build Coastguard Worker             save_string);
510*635a8641SAndroid Build Coastguard Worker   save_string.clear();
511*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string, true);
512*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(
513*635a8641SAndroid Build Coastguard Worker       "Expired trial name/Default group/"
514*635a8641SAndroid Build Coastguard Worker       "Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default/",
515*635a8641SAndroid Build Coastguard Worker       save_string);
516*635a8641SAndroid Build Coastguard Worker }
517*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,Restore)518*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Restore) {
519*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
520*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("xxx"));
521*635a8641SAndroid Build Coastguard Worker 
522*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromString("Some_name/Winner/xxx/yyyy/",
523*635a8641SAndroid Build Coastguard Worker                                          std::set<std::string>());
524*635a8641SAndroid Build Coastguard Worker 
525*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("Some_name");
526*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
527*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Winner", trial->group_name());
528*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some_name", trial->trial_name());
529*635a8641SAndroid Build Coastguard Worker 
530*635a8641SAndroid Build Coastguard Worker   trial = FieldTrialList::Find("xxx");
531*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
532*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("yyyy", trial->group_name());
533*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("xxx", trial->trial_name());
534*635a8641SAndroid Build Coastguard Worker }
535*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,RestoreNotEndingWithSlash)536*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, RestoreNotEndingWithSlash) {
537*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::CreateTrialsFromString("tname/gname",
538*635a8641SAndroid Build Coastguard Worker                                                      std::set<std::string>()));
539*635a8641SAndroid Build Coastguard Worker 
540*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("tname");
541*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
542*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("gname", trial->group_name());
543*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("tname", trial->trial_name());
544*635a8641SAndroid Build Coastguard Worker }
545*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,BogusRestore)546*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, BogusRestore) {
547*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingSlash",
548*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
549*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingGroupName/",
550*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
551*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("noname, only group/",
552*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
553*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("/emptyname",
554*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
555*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("*/emptyname",
556*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
557*635a8641SAndroid Build Coastguard Worker }
558*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DuplicateRestore)559*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DuplicateRestore) {
560*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
561*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Some name", 10, "Default", nullptr);
562*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
563*635a8641SAndroid Build Coastguard Worker   // Finalize the group selection by accessing the selected group.
564*635a8641SAndroid Build Coastguard Worker   trial->group();
565*635a8641SAndroid Build Coastguard Worker   std::string save_string;
566*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&save_string);
567*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Winner/", save_string);
568*635a8641SAndroid Build Coastguard Worker 
569*635a8641SAndroid Build Coastguard Worker   // It is OK if we redundantly specify a winner.
570*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(save_string,
571*635a8641SAndroid Build Coastguard Worker                                                      std::set<std::string>()));
572*635a8641SAndroid Build Coastguard Worker 
573*635a8641SAndroid Build Coastguard Worker   // But it is an error to try to change to a different winner.
574*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("Some name/Loser/",
575*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
576*635a8641SAndroid Build Coastguard Worker }
577*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActive)578*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringNotActive) {
579*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
580*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
581*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/Xyz/zyx/",
582*635a8641SAndroid Build Coastguard Worker                                                      std::set<std::string>()));
583*635a8641SAndroid Build Coastguard Worker 
584*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
585*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
586*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(active_groups.empty());
587*635a8641SAndroid Build Coastguard Worker 
588*635a8641SAndroid Build Coastguard Worker   // Check that the values still get returned and querying them activates them.
589*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
590*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", FieldTrialList::FindFullName("Xyz"));
591*635a8641SAndroid Build Coastguard Worker 
592*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
593*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
594*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
595*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("def", active_groups[0].group_name);
596*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
597*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
598*635a8641SAndroid Build Coastguard Worker }
599*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringForceActivation)600*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringForceActivation) {
601*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
602*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("def"));
603*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
604*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
605*635a8641SAndroid Build Coastguard Worker       "*Abc/cba/def/fed/*Xyz/zyx/", std::set<std::string>()));
606*635a8641SAndroid Build Coastguard Worker 
607*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
608*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
609*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
610*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
611*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("cba", active_groups[0].group_name);
612*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
613*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
614*635a8641SAndroid Build Coastguard Worker }
615*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActiveObserver)616*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringNotActiveObserver) {
617*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
618*635a8641SAndroid Build Coastguard Worker 
619*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
620*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/",
621*635a8641SAndroid Build Coastguard Worker                                                      std::set<std::string>()));
622*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
623*635a8641SAndroid Build Coastguard Worker   // Observer shouldn't be notified.
624*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
625*635a8641SAndroid Build Coastguard Worker 
626*635a8641SAndroid Build Coastguard Worker   // Check that the values still get returned and querying them activates them.
627*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
628*635a8641SAndroid Build Coastguard Worker 
629*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
630*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", observer.trial_name());
631*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("def", observer.group_name());
632*635a8641SAndroid Build Coastguard Worker }
633*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringWithIgnoredFieldTrials)634*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringWithIgnoredFieldTrials) {
635*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
636*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Foo"));
637*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
638*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Bar"));
639*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
640*635a8641SAndroid Build Coastguard Worker 
641*635a8641SAndroid Build Coastguard Worker   std::set<std::string> ignored_trial_names;
642*635a8641SAndroid Build Coastguard Worker   ignored_trial_names.insert("Unaccepted1");
643*635a8641SAndroid Build Coastguard Worker   ignored_trial_names.insert("Unaccepted2");
644*635a8641SAndroid Build Coastguard Worker   ignored_trial_names.insert("Unaccepted3");
645*635a8641SAndroid Build Coastguard Worker 
646*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromString(
647*635a8641SAndroid Build Coastguard Worker       "Unaccepted1/Unaccepted1_name/"
648*635a8641SAndroid Build Coastguard Worker       "Foo/Foo_name/"
649*635a8641SAndroid Build Coastguard Worker       "Unaccepted2/Unaccepted2_name/"
650*635a8641SAndroid Build Coastguard Worker       "Bar/Bar_name/"
651*635a8641SAndroid Build Coastguard Worker       "Unaccepted3/Unaccepted3_name/",
652*635a8641SAndroid Build Coastguard Worker       ignored_trial_names);
653*635a8641SAndroid Build Coastguard Worker 
654*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
655*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::TrialExists("Foo"));
656*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
657*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::TrialExists("Bar"));
658*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
659*635a8641SAndroid Build Coastguard Worker 
660*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
661*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
662*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
663*635a8641SAndroid Build Coastguard Worker 
664*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("Foo");
665*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
666*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Foo", trial->trial_name());
667*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Foo_name", trial->group_name());
668*635a8641SAndroid Build Coastguard Worker 
669*635a8641SAndroid Build Coastguard Worker   trial = FieldTrialList::Find("Bar");
670*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
671*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Bar", trial->trial_name());
672*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Bar_name", trial->group_name());
673*635a8641SAndroid Build Coastguard Worker }
674*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateFieldTrial)675*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateFieldTrial) {
676*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
677*635a8641SAndroid Build Coastguard Worker 
678*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Some_name", "Winner");
679*635a8641SAndroid Build Coastguard Worker 
680*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("Some_name");
681*635a8641SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
682*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Winner", trial->group_name());
683*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Some_name", trial->trial_name());
684*635a8641SAndroid Build Coastguard Worker }
685*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateFieldTrialIsNotActive)686*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateFieldTrialIsNotActive) {
687*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "CreateFieldTrialIsActiveTrial";
688*635a8641SAndroid Build Coastguard Worker   const char kWinnerGroup[] = "Winner";
689*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
690*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(kTrialName, kWinnerGroup);
691*635a8641SAndroid Build Coastguard Worker 
692*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
693*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
694*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
695*635a8641SAndroid Build Coastguard Worker }
696*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DuplicateFieldTrial)697*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DuplicateFieldTrial) {
698*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
699*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Some_name", 10, "Default", nullptr);
700*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
701*635a8641SAndroid Build Coastguard Worker 
702*635a8641SAndroid Build Coastguard Worker   // It is OK if we redundantly specify a winner.
703*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("Some_name", "Winner");
704*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(trial1 != nullptr);
705*635a8641SAndroid Build Coastguard Worker 
706*635a8641SAndroid Build Coastguard Worker   // But it is an error to try to change to a different winner.
707*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("Some_name", "Loser");
708*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(trial2 == nullptr);
709*635a8641SAndroid Build Coastguard Worker }
710*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DisableImmediately)711*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DisableImmediately) {
712*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
713*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
714*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("trial", 100, "default", &default_group_number);
715*635a8641SAndroid Build Coastguard Worker   trial->Disable();
716*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ("default", trial->group_name());
717*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(default_group_number, trial->group());
718*635a8641SAndroid Build Coastguard Worker }
719*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DisableAfterInitialization)720*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DisableAfterInitialization) {
721*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
722*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("trial", 100, "default", nullptr);
723*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("non_default", 100);
724*635a8641SAndroid Build Coastguard Worker   trial->Disable();
725*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ("default", trial->group_name());
726*635a8641SAndroid Build Coastguard Worker }
727*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ForcedFieldTrials)728*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ForcedFieldTrials) {
729*635a8641SAndroid Build Coastguard Worker   // Validate we keep the forced choice.
730*635a8641SAndroid Build Coastguard Worker   FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Use the",
731*635a8641SAndroid Build Coastguard Worker                                                               "Force");
732*635a8641SAndroid Build Coastguard Worker   EXPECT_STREQ("Force", forced_trial->group_name().c_str());
733*635a8641SAndroid Build Coastguard Worker 
734*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
735*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> factory_trial =
736*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1000, "default", &default_group_number);
737*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(factory_trial.get(), forced_trial);
738*635a8641SAndroid Build Coastguard Worker 
739*635a8641SAndroid Build Coastguard Worker   int chosen_group = factory_trial->AppendGroup("Force", 100);
740*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(chosen_group, factory_trial->group());
741*635a8641SAndroid Build Coastguard Worker   int not_chosen_group = factory_trial->AppendGroup("Dark Side", 100);
742*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(chosen_group, not_chosen_group);
743*635a8641SAndroid Build Coastguard Worker 
744*635a8641SAndroid Build Coastguard Worker   // Since we didn't force the default group, we should not be returned the
745*635a8641SAndroid Build Coastguard Worker   // chosen group as the default group.
746*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group_number, chosen_group);
747*635a8641SAndroid Build Coastguard Worker   int new_group = factory_trial->AppendGroup("Duck Tape", 800);
748*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(chosen_group, new_group);
749*635a8641SAndroid Build Coastguard Worker   // The new group should not be the default group either.
750*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group_number, new_group);
751*635a8641SAndroid Build Coastguard Worker }
752*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ForcedFieldTrialsDefaultGroup)753*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ForcedFieldTrialsDefaultGroup) {
754*635a8641SAndroid Build Coastguard Worker   // Forcing the default should use the proper group ID.
755*635a8641SAndroid Build Coastguard Worker   FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Trial Name",
756*635a8641SAndroid Build Coastguard Worker                                                               "Default");
757*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
758*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> factory_trial =
759*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Trial Name", 1000, "Default", &default_group_number);
760*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_trial, factory_trial.get());
761*635a8641SAndroid Build Coastguard Worker 
762*635a8641SAndroid Build Coastguard Worker   int other_group = factory_trial->AppendGroup("Not Default", 100);
763*635a8641SAndroid Build Coastguard Worker   EXPECT_STREQ("Default", factory_trial->group_name().c_str());
764*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group_number, factory_trial->group());
765*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(other_group, factory_trial->group());
766*635a8641SAndroid Build Coastguard Worker 
767*635a8641SAndroid Build Coastguard Worker   int new_other_group = factory_trial->AppendGroup("Not Default Either", 800);
768*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(new_other_group, factory_trial->group());
769*635a8641SAndroid Build Coastguard Worker }
770*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForced)771*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForced) {
772*635a8641SAndroid Build Coastguard Worker   // Start by setting a trial for which we ensure a winner...
773*635a8641SAndroid Build Coastguard Worker   int default_group_number = -1;
774*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
775*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default", &default_group_number);
776*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_trial, forced_trial);
777*635a8641SAndroid Build Coastguard Worker 
778*635a8641SAndroid Build Coastguard Worker   int forced_group = forced_trial->AppendGroup("Force", 1);
779*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_group, forced_trial->group());
780*635a8641SAndroid Build Coastguard Worker 
781*635a8641SAndroid Build Coastguard Worker   // Now force it.
782*635a8641SAndroid Build Coastguard Worker   forced_trial->SetForced();
783*635a8641SAndroid Build Coastguard Worker 
784*635a8641SAndroid Build Coastguard Worker   // Now try to set it up differently as a hard coded registration would.
785*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> hard_coded_trial =
786*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default", &default_group_number);
787*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(hard_coded_trial, forced_trial);
788*635a8641SAndroid Build Coastguard Worker 
789*635a8641SAndroid Build Coastguard Worker   int would_lose_group = hard_coded_trial->AppendGroup("Force", 0);
790*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_group, hard_coded_trial->group());
791*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_group, would_lose_group);
792*635a8641SAndroid Build Coastguard Worker 
793*635a8641SAndroid Build Coastguard Worker   // Same thing if we would have done it to win again.
794*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> other_hard_coded_trial =
795*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default", &default_group_number);
796*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(other_hard_coded_trial, forced_trial);
797*635a8641SAndroid Build Coastguard Worker 
798*635a8641SAndroid Build Coastguard Worker   int would_win_group = other_hard_coded_trial->AppendGroup("Force", 1);
799*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_group, other_hard_coded_trial->group());
800*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(forced_group, would_win_group);
801*635a8641SAndroid Build Coastguard Worker }
802*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedDefaultOnly)803*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedDefaultOnly) {
804*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultOnly";
805*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
806*635a8641SAndroid Build Coastguard Worker 
807*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
808*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
809*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
810*635a8641SAndroid Build Coastguard Worker   trial->SetForced();
811*635a8641SAndroid Build Coastguard Worker 
812*635a8641SAndroid Build Coastguard Worker   trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
813*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, trial->group());
814*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, trial->group_name());
815*635a8641SAndroid Build Coastguard Worker }
816*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedDefaultWithExtraGroup)817*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedDefaultWithExtraGroup) {
818*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultWithExtraGroup";
819*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
820*635a8641SAndroid Build Coastguard Worker 
821*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
822*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
823*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
824*635a8641SAndroid Build Coastguard Worker   trial->SetForced();
825*635a8641SAndroid Build Coastguard Worker 
826*635a8641SAndroid Build Coastguard Worker   trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
827*635a8641SAndroid Build Coastguard Worker   const int extra_group = trial->AppendGroup("Extra", 100);
828*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, trial->group());
829*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(extra_group, trial->group());
830*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, trial->group_name());
831*635a8641SAndroid Build Coastguard Worker }
832*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedTurnFeatureOn)833*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedTurnFeatureOn) {
834*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedTurnFeatureOn";
835*635a8641SAndroid Build Coastguard Worker   const char kExtraGroupName[] = "Extra";
836*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
837*635a8641SAndroid Build Coastguard Worker 
838*635a8641SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that turns the feature on when the
839*635a8641SAndroid Build Coastguard Worker   // original hard-coded config had it disabled.
840*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
841*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
842*635a8641SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kExtraGroupName, 100);
843*635a8641SAndroid Build Coastguard Worker   forced_trial->SetForced();
844*635a8641SAndroid Build Coastguard Worker 
845*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
846*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
847*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
848*635a8641SAndroid Build Coastguard Worker   const int extra_group = client_trial->AppendGroup(kExtraGroupName, 0);
849*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group, extra_group);
850*635a8641SAndroid Build Coastguard Worker 
851*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
852*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(extra_group, client_trial->group());
853*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
854*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kExtraGroupName, client_trial->group_name());
855*635a8641SAndroid Build Coastguard Worker }
856*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedTurnFeatureOff)857*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedTurnFeatureOff) {
858*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedTurnFeatureOff";
859*635a8641SAndroid Build Coastguard Worker   const char kExtraGroupName[] = "Extra";
860*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
861*635a8641SAndroid Build Coastguard Worker 
862*635a8641SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that turns the feature off when the
863*635a8641SAndroid Build Coastguard Worker   // original hard-coded config had it enabled.
864*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
865*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
866*635a8641SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kExtraGroupName, 0);
867*635a8641SAndroid Build Coastguard Worker   forced_trial->SetForced();
868*635a8641SAndroid Build Coastguard Worker 
869*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
870*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
871*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
872*635a8641SAndroid Build Coastguard Worker   const int extra_group = client_trial->AppendGroup(kExtraGroupName, 100);
873*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group, extra_group);
874*635a8641SAndroid Build Coastguard Worker 
875*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
876*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, client_trial->group());
877*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
878*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, client_trial->group_name());
879*635a8641SAndroid Build Coastguard Worker }
880*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedChangeDefault_Default)881*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedChangeDefault_Default) {
882*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultGroupChange";
883*635a8641SAndroid Build Coastguard Worker   const char kGroupAName[] = "A";
884*635a8641SAndroid Build Coastguard Worker   const char kGroupBName[] = "B";
885*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
886*635a8641SAndroid Build Coastguard Worker 
887*635a8641SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that switches which group is default
888*635a8641SAndroid Build Coastguard Worker   // and ensures that the non-forced code receives the correct group numbers.
889*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
890*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupAName, nullptr);
891*635a8641SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kGroupBName, 100);
892*635a8641SAndroid Build Coastguard Worker   forced_trial->SetForced();
893*635a8641SAndroid Build Coastguard Worker 
894*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
895*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
896*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
897*635a8641SAndroid Build Coastguard Worker   const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
898*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group, extra_group);
899*635a8641SAndroid Build Coastguard Worker 
900*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
901*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, client_trial->group());
902*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
903*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupBName, client_trial->group_name());
904*635a8641SAndroid Build Coastguard Worker }
905*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedChangeDefault_NonDefault)906*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedChangeDefault_NonDefault) {
907*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultGroupChange";
908*635a8641SAndroid Build Coastguard Worker   const char kGroupAName[] = "A";
909*635a8641SAndroid Build Coastguard Worker   const char kGroupBName[] = "B";
910*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
911*635a8641SAndroid Build Coastguard Worker 
912*635a8641SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that switches which group is default
913*635a8641SAndroid Build Coastguard Worker   // and ensures that the non-forced code receives the correct group numbers.
914*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
915*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupAName, nullptr);
916*635a8641SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kGroupBName, 0);
917*635a8641SAndroid Build Coastguard Worker   forced_trial->SetForced();
918*635a8641SAndroid Build Coastguard Worker 
919*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
920*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
921*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
922*635a8641SAndroid Build Coastguard Worker   const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
923*635a8641SAndroid Build Coastguard Worker   EXPECT_NE(default_group, extra_group);
924*635a8641SAndroid Build Coastguard Worker 
925*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
926*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(extra_group, client_trial->group());
927*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
928*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupAName, client_trial->group_name());
929*635a8641SAndroid Build Coastguard Worker }
930*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,Observe)931*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Observe) {
932*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve1";
933*635a8641SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
934*635a8641SAndroid Build Coastguard Worker 
935*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
936*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
937*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
938*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
939*635a8641SAndroid Build Coastguard Worker   const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
940*635a8641SAndroid Build Coastguard Worker   const int chosen_group = trial->group();
941*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
942*635a8641SAndroid Build Coastguard Worker 
943*635a8641SAndroid Build Coastguard Worker   // Observers are called asynchronously.
944*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
945*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.group_name().empty());
946*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
947*635a8641SAndroid Build Coastguard Worker 
948*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, observer.trial_name());
949*635a8641SAndroid Build Coastguard Worker   if (chosen_group == default_group)
950*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kDefaultGroupName, observer.group_name());
951*635a8641SAndroid Build Coastguard Worker   else
952*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kSecondaryGroupName, observer.group_name());
953*635a8641SAndroid Build Coastguard Worker }
954*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SynchronousObserver)955*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SynchronousObserver) {
956*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve1";
957*635a8641SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
958*635a8641SAndroid Build Coastguard Worker 
959*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver observer(TestFieldTrialObserver::SYNCHRONOUS);
960*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
961*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
962*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
963*635a8641SAndroid Build Coastguard Worker   const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
964*635a8641SAndroid Build Coastguard Worker   const int chosen_group = trial->group();
965*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
966*635a8641SAndroid Build Coastguard Worker 
967*635a8641SAndroid Build Coastguard Worker   // The observer should be notified synchronously by the group() call.
968*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, observer.trial_name());
969*635a8641SAndroid Build Coastguard Worker   if (chosen_group == default_group)
970*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kDefaultGroupName, observer.group_name());
971*635a8641SAndroid Build Coastguard Worker   else
972*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(kSecondaryGroupName, observer.group_name());
973*635a8641SAndroid Build Coastguard Worker }
974*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ObserveDisabled)975*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ObserveDisabled) {
976*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve2";
977*635a8641SAndroid Build Coastguard Worker 
978*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
979*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
980*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
981*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
982*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("A", 25);
983*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("B", 25);
984*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("C", 25);
985*635a8641SAndroid Build Coastguard Worker   trial->Disable();
986*635a8641SAndroid Build Coastguard Worker 
987*635a8641SAndroid Build Coastguard Worker   // Observer shouldn't be notified of a disabled trial.
988*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
989*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
990*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.group_name().empty());
991*635a8641SAndroid Build Coastguard Worker 
992*635a8641SAndroid Build Coastguard Worker   // Observer shouldn't be notified even after a |group()| call.
993*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, trial->group());
994*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
995*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
996*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.group_name().empty());
997*635a8641SAndroid Build Coastguard Worker }
998*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ObserveForcedDisabled)999*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ObserveForcedDisabled) {
1000*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve3";
1001*635a8641SAndroid Build Coastguard Worker 
1002*635a8641SAndroid Build Coastguard Worker   TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
1003*635a8641SAndroid Build Coastguard Worker   int default_group = -1;
1004*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
1005*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
1006*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("A", 25);
1007*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("B", 25);
1008*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("C", 25);
1009*635a8641SAndroid Build Coastguard Worker   trial->SetForced();
1010*635a8641SAndroid Build Coastguard Worker   trial->Disable();
1011*635a8641SAndroid Build Coastguard Worker 
1012*635a8641SAndroid Build Coastguard Worker   // Observer shouldn't be notified of a disabled trial, even when forced.
1013*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
1014*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
1015*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.group_name().empty());
1016*635a8641SAndroid Build Coastguard Worker 
1017*635a8641SAndroid Build Coastguard Worker   // Observer shouldn't be notified even after a |group()| call.
1018*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(default_group, trial->group());
1019*635a8641SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
1020*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
1021*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.group_name().empty());
1022*635a8641SAndroid Build Coastguard Worker }
1023*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DisabledTrialNotActive)1024*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DisabledTrialNotActive) {
1025*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "DisabledTrial";
1026*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1027*635a8641SAndroid Build Coastguard Worker 
1028*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
1029*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
1030*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("X", 50);
1031*635a8641SAndroid Build Coastguard Worker   trial->Disable();
1032*635a8641SAndroid Build Coastguard Worker 
1033*635a8641SAndroid Build Coastguard Worker   // Ensure the trial is not listed as active.
1034*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
1035*635a8641SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
1036*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
1037*635a8641SAndroid Build Coastguard Worker 
1038*635a8641SAndroid Build Coastguard Worker   // Ensure the trial is not listed in the |StatesToString()| result.
1039*635a8641SAndroid Build Coastguard Worker   std::string states;
1040*635a8641SAndroid Build Coastguard Worker   FieldTrialList::StatesToString(&states);
1041*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(states.empty());
1042*635a8641SAndroid Build Coastguard Worker }
1043*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ExpirationYearNotExpired)1044*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ExpirationYearNotExpired) {
1045*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "NotExpired";
1046*635a8641SAndroid Build Coastguard Worker   const char kGroupName[] = "Group2";
1047*635a8641SAndroid Build Coastguard Worker   const int kProbability = 100;
1048*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1049*635a8641SAndroid Build Coastguard Worker 
1050*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
1051*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, kProbability, kDefaultGroupName, nullptr);
1052*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup(kGroupName, kProbability);
1053*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupName, trial->group_name());
1054*635a8641SAndroid Build Coastguard Worker }
1055*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,FloatBoundariesGiveEqualGroupSizes)1056*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes) {
1057*635a8641SAndroid Build Coastguard Worker   const int kBucketCount = 100;
1058*635a8641SAndroid Build Coastguard Worker 
1059*635a8641SAndroid Build Coastguard Worker   // Try each boundary value |i / 100.0| as the entropy value.
1060*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < kBucketCount; ++i) {
1061*635a8641SAndroid Build Coastguard Worker     const double entropy = i / static_cast<double>(kBucketCount);
1062*635a8641SAndroid Build Coastguard Worker 
1063*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial(
1064*635a8641SAndroid Build Coastguard Worker         new FieldTrial("test", kBucketCount, "default", entropy));
1065*635a8641SAndroid Build Coastguard Worker     for (int j = 0; j < kBucketCount; ++j)
1066*635a8641SAndroid Build Coastguard Worker       trial->AppendGroup(IntToString(j), 1);
1067*635a8641SAndroid Build Coastguard Worker 
1068*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(IntToString(i), trial->group_name());
1069*635a8641SAndroid Build Coastguard Worker   }
1070*635a8641SAndroid Build Coastguard Worker }
1071*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DoesNotSurpassTotalProbability)1072*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DoesNotSurpassTotalProbability) {
1073*635a8641SAndroid Build Coastguard Worker   const double kEntropyValue = 1.0 - 1e-9;
1074*635a8641SAndroid Build Coastguard Worker   ASSERT_LT(kEntropyValue, 1.0);
1075*635a8641SAndroid Build Coastguard Worker 
1076*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial(
1077*635a8641SAndroid Build Coastguard Worker       new FieldTrial("test", 2, "default", kEntropyValue));
1078*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("1", 1);
1079*635a8641SAndroid Build Coastguard Worker   trial->AppendGroup("2", 1);
1080*635a8641SAndroid Build Coastguard Worker 
1081*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("2", trial->group_name());
1082*635a8641SAndroid Build Coastguard Worker }
1083*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateSimulatedFieldTrial)1084*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateSimulatedFieldTrial) {
1085*635a8641SAndroid Build Coastguard Worker   const char kTrialName[] = "CreateSimulatedFieldTrial";
1086*635a8641SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1087*635a8641SAndroid Build Coastguard Worker 
1088*635a8641SAndroid Build Coastguard Worker   // Different cases to test, e.g. default vs. non default group being chosen.
1089*635a8641SAndroid Build Coastguard Worker   struct {
1090*635a8641SAndroid Build Coastguard Worker     double entropy_value;
1091*635a8641SAndroid Build Coastguard Worker     const char* expected_group;
1092*635a8641SAndroid Build Coastguard Worker   } test_cases[] = {
1093*635a8641SAndroid Build Coastguard Worker     { 0.4, "A" },
1094*635a8641SAndroid Build Coastguard Worker     { 0.85, "B" },
1095*635a8641SAndroid Build Coastguard Worker     { 0.95, kDefaultGroupName },
1096*635a8641SAndroid Build Coastguard Worker   };
1097*635a8641SAndroid Build Coastguard Worker 
1098*635a8641SAndroid Build Coastguard Worker   for (size_t i = 0; i < arraysize(test_cases); ++i) {
1099*635a8641SAndroid Build Coastguard Worker     TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
1100*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial(
1101*635a8641SAndroid Build Coastguard Worker        FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, kDefaultGroupName,
1102*635a8641SAndroid Build Coastguard Worker                                              test_cases[i].entropy_value));
1103*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup("A", 80);
1104*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup("B", 10);
1105*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(test_cases[i].expected_group, trial->group_name());
1106*635a8641SAndroid Build Coastguard Worker 
1107*635a8641SAndroid Build Coastguard Worker     // Field trial shouldn't have been registered with the list.
1108*635a8641SAndroid Build Coastguard Worker     EXPECT_FALSE(FieldTrialList::TrialExists(kTrialName));
1109*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0u, FieldTrialList::GetFieldTrialCount());
1110*635a8641SAndroid Build Coastguard Worker 
1111*635a8641SAndroid Build Coastguard Worker     // Observer shouldn't have been notified.
1112*635a8641SAndroid Build Coastguard Worker     RunLoop().RunUntilIdle();
1113*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(observer.trial_name().empty());
1114*635a8641SAndroid Build Coastguard Worker 
1115*635a8641SAndroid Build Coastguard Worker     // The trial shouldn't be in the active set of trials.
1116*635a8641SAndroid Build Coastguard Worker     FieldTrial::ActiveGroups active_groups;
1117*635a8641SAndroid Build Coastguard Worker     FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
1118*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(active_groups.empty());
1119*635a8641SAndroid Build Coastguard Worker 
1120*635a8641SAndroid Build Coastguard Worker     // The trial shouldn't be listed in the |StatesToString()| result.
1121*635a8641SAndroid Build Coastguard Worker     std::string states;
1122*635a8641SAndroid Build Coastguard Worker     FieldTrialList::StatesToString(&states);
1123*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(states.empty());
1124*635a8641SAndroid Build Coastguard Worker   }
1125*635a8641SAndroid Build Coastguard Worker }
1126*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialTestWithoutList,StatesStringFormat)1127*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialTestWithoutList, StatesStringFormat) {
1128*635a8641SAndroid Build Coastguard Worker   std::string save_string;
1129*635a8641SAndroid Build Coastguard Worker 
1130*635a8641SAndroid Build Coastguard Worker   // Scoping the first FieldTrialList, as we need another one to test the
1131*635a8641SAndroid Build Coastguard Worker   // importing function.
1132*635a8641SAndroid Build Coastguard Worker   {
1133*635a8641SAndroid Build Coastguard Worker     FieldTrialList field_trial_list(nullptr);
1134*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial =
1135*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial("Abc", 10, "Default some name", nullptr);
1136*635a8641SAndroid Build Coastguard Worker     trial->AppendGroup("cba", 10);
1137*635a8641SAndroid Build Coastguard Worker     trial->group();
1138*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial2 =
1139*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial("Xyz", 10, "Default xxx", nullptr);
1140*635a8641SAndroid Build Coastguard Worker     trial2->AppendGroup("zyx", 10);
1141*635a8641SAndroid Build Coastguard Worker     trial2->group();
1142*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial3 =
1143*635a8641SAndroid Build Coastguard Worker         CreateFieldTrial("zzz", 10, "default", nullptr);
1144*635a8641SAndroid Build Coastguard Worker 
1145*635a8641SAndroid Build Coastguard Worker     FieldTrialList::AllStatesToString(&save_string, false);
1146*635a8641SAndroid Build Coastguard Worker   }
1147*635a8641SAndroid Build Coastguard Worker 
1148*635a8641SAndroid Build Coastguard Worker   // Starting with a new blank FieldTrialList.
1149*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(nullptr);
1150*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(field_trial_list.CreateTrialsFromString(save_string,
1151*635a8641SAndroid Build Coastguard Worker                                                       std::set<std::string>()));
1152*635a8641SAndroid Build Coastguard Worker 
1153*635a8641SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
1154*635a8641SAndroid Build Coastguard Worker   field_trial_list.GetActiveFieldTrialGroups(&active_groups);
1155*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
1156*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
1157*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("cba", active_groups[0].group_name);
1158*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
1159*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
1160*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(field_trial_list.TrialExists("zzz"));
1161*635a8641SAndroid Build Coastguard Worker }
1162*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialDeathTest,OneTimeRandomizedTrialWithoutFieldTrialList)1163*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialDeathTest, OneTimeRandomizedTrialWithoutFieldTrialList) {
1164*635a8641SAndroid Build Coastguard Worker   // Trying to instantiate a one-time randomized field trial before the
1165*635a8641SAndroid Build Coastguard Worker   // FieldTrialList is created should crash.
1166*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH_IF_SUPPORTED(
1167*635a8641SAndroid Build Coastguard Worker       FieldTrialList::FactoryGetFieldTrial(
1168*635a8641SAndroid Build Coastguard Worker           "OneTimeRandomizedTrialWithoutFieldTrialList", 100, kDefaultGroupName,
1169*635a8641SAndroid Build Coastguard Worker           FieldTrialList::kNoExpirationYear, 1, 1,
1170*635a8641SAndroid Build Coastguard Worker           FieldTrial::ONE_TIME_RANDOMIZED, nullptr),
1171*635a8641SAndroid Build Coastguard Worker       "");
1172*635a8641SAndroid Build Coastguard Worker }
1173*635a8641SAndroid Build Coastguard Worker 
1174*635a8641SAndroid Build Coastguard Worker #if defined(OS_FUCHSIA)
1175*635a8641SAndroid Build Coastguard Worker // TODO(crbug.com/752368): This is flaky on Fuchsia.
1176*635a8641SAndroid Build Coastguard Worker #define MAYBE_TestCopyFieldTrialStateToFlags \
1177*635a8641SAndroid Build Coastguard Worker   DISABLED_TestCopyFieldTrialStateToFlags
1178*635a8641SAndroid Build Coastguard Worker #else
1179*635a8641SAndroid Build Coastguard Worker #define MAYBE_TestCopyFieldTrialStateToFlags TestCopyFieldTrialStateToFlags
1180*635a8641SAndroid Build Coastguard Worker #endif
TEST(FieldTrialListTest,MAYBE_TestCopyFieldTrialStateToFlags)1181*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, MAYBE_TestCopyFieldTrialStateToFlags) {
1182*635a8641SAndroid Build Coastguard Worker   constexpr char kFieldTrialHandleSwitch[] = "test-field-trial-handle";
1183*635a8641SAndroid Build Coastguard Worker   constexpr char kEnableFeaturesSwitch[] = "test-enable-features";
1184*635a8641SAndroid Build Coastguard Worker   constexpr char kDisableFeaturesSwitch[] = "test-disable-features";
1185*635a8641SAndroid Build Coastguard Worker 
1186*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(std::make_unique<MockEntropyProvider>());
1187*635a8641SAndroid Build Coastguard Worker 
1188*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<FeatureList> feature_list(new FeatureList);
1189*635a8641SAndroid Build Coastguard Worker   feature_list->InitializeFromCommandLine("A,B", "C");
1190*635a8641SAndroid Build Coastguard Worker 
1191*635a8641SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1192*635a8641SAndroid Build Coastguard Worker   feature_list->RegisterFieldTrialOverride(
1193*635a8641SAndroid Build Coastguard Worker       "MyFeature", FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
1194*635a8641SAndroid Build Coastguard Worker 
1195*635a8641SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1196*635a8641SAndroid Build Coastguard Worker   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
1197*635a8641SAndroid Build Coastguard Worker 
1198*635a8641SAndroid Build Coastguard Worker   FilePath test_file_path = FilePath(FILE_PATH_LITERAL("Program"));
1199*635a8641SAndroid Build Coastguard Worker   CommandLine command_line = CommandLine(test_file_path);
1200*635a8641SAndroid Build Coastguard Worker 
1201*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CopyFieldTrialStateToFlags(
1202*635a8641SAndroid Build Coastguard Worker       kFieldTrialHandleSwitch, kEnableFeaturesSwitch, kDisableFeaturesSwitch,
1203*635a8641SAndroid Build Coastguard Worker       &command_line);
1204*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(command_line.HasSwitch(kFieldTrialHandleSwitch));
1205*635a8641SAndroid Build Coastguard Worker 
1206*635a8641SAndroid Build Coastguard Worker   // Explictly specified enabled/disabled features should be specified.
1207*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("A,B", command_line.GetSwitchValueASCII(kEnableFeaturesSwitch));
1208*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("C", command_line.GetSwitchValueASCII(kDisableFeaturesSwitch));
1209*635a8641SAndroid Build Coastguard Worker }
1210*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialListTest,InstantiateAllocator)1211*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, InstantiateAllocator) {
1212*635a8641SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1213*635a8641SAndroid Build Coastguard Worker   scoped_feature_list.Init();
1214*635a8641SAndroid Build Coastguard Worker 
1215*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(nullptr);
1216*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1217*635a8641SAndroid Build Coastguard Worker 
1218*635a8641SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1219*635a8641SAndroid Build Coastguard Worker   void* memory = field_trial_list.field_trial_allocator_->shared_memory();
1220*635a8641SAndroid Build Coastguard Worker   size_t used = field_trial_list.field_trial_allocator_->used();
1221*635a8641SAndroid Build Coastguard Worker 
1222*635a8641SAndroid Build Coastguard Worker   // Ensure that the function is idempotent.
1223*635a8641SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1224*635a8641SAndroid Build Coastguard Worker   void* new_memory = field_trial_list.field_trial_allocator_->shared_memory();
1225*635a8641SAndroid Build Coastguard Worker   size_t new_used = field_trial_list.field_trial_allocator_->used();
1226*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(memory, new_memory);
1227*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(used, new_used);
1228*635a8641SAndroid Build Coastguard Worker }
1229*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialListTest,AddTrialsToAllocator)1230*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, AddTrialsToAllocator) {
1231*635a8641SAndroid Build Coastguard Worker   std::string save_string;
1232*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle handle;
1233*635a8641SAndroid Build Coastguard Worker 
1234*635a8641SAndroid Build Coastguard Worker   // Scoping the first FieldTrialList, as we need another one to test that it
1235*635a8641SAndroid Build Coastguard Worker   // matches.
1236*635a8641SAndroid Build Coastguard Worker   {
1237*635a8641SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list;
1238*635a8641SAndroid Build Coastguard Worker     scoped_feature_list.Init();
1239*635a8641SAndroid Build Coastguard Worker 
1240*635a8641SAndroid Build Coastguard Worker     FieldTrialList field_trial_list(nullptr);
1241*635a8641SAndroid Build Coastguard Worker     FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1242*635a8641SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1243*635a8641SAndroid Build Coastguard Worker     FieldTrialList::AllStatesToString(&save_string, false);
1244*635a8641SAndroid Build Coastguard Worker     handle = SharedMemory::DuplicateHandle(
1245*635a8641SAndroid Build Coastguard Worker         field_trial_list.field_trial_allocator_->shared_memory()->handle());
1246*635a8641SAndroid Build Coastguard Worker   }
1247*635a8641SAndroid Build Coastguard Worker 
1248*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list2(nullptr);
1249*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
1250*635a8641SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1251*635a8641SAndroid Build Coastguard Worker   shm.get()->Map(4 << 10);
1252*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
1253*635a8641SAndroid Build Coastguard Worker   std::string check_string;
1254*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string, false);
1255*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(save_string, check_string);
1256*635a8641SAndroid Build Coastguard Worker }
1257*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialListTest,DoNotAddSimulatedFieldTrialsToAllocator)1258*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, DoNotAddSimulatedFieldTrialsToAllocator) {
1259*635a8641SAndroid Build Coastguard Worker   constexpr char kTrialName[] = "trial";
1260*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle handle;
1261*635a8641SAndroid Build Coastguard Worker   {
1262*635a8641SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list;
1263*635a8641SAndroid Build Coastguard Worker     scoped_feature_list.Init();
1264*635a8641SAndroid Build Coastguard Worker 
1265*635a8641SAndroid Build Coastguard Worker     // Create a simulated trial and a real trial and call group() on them, which
1266*635a8641SAndroid Build Coastguard Worker     // should only add the real trial to the field trial allocator.
1267*635a8641SAndroid Build Coastguard Worker     FieldTrialList field_trial_list(nullptr);
1268*635a8641SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1269*635a8641SAndroid Build Coastguard Worker 
1270*635a8641SAndroid Build Coastguard Worker     // This shouldn't add to the allocator.
1271*635a8641SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> simulated_trial =
1272*635a8641SAndroid Build Coastguard Worker         FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, "Simulated",
1273*635a8641SAndroid Build Coastguard Worker                                               0.95);
1274*635a8641SAndroid Build Coastguard Worker     simulated_trial->group();
1275*635a8641SAndroid Build Coastguard Worker 
1276*635a8641SAndroid Build Coastguard Worker     // This should add to the allocator.
1277*635a8641SAndroid Build Coastguard Worker     FieldTrial* real_trial =
1278*635a8641SAndroid Build Coastguard Worker         FieldTrialList::CreateFieldTrial(kTrialName, "Real");
1279*635a8641SAndroid Build Coastguard Worker     real_trial->group();
1280*635a8641SAndroid Build Coastguard Worker 
1281*635a8641SAndroid Build Coastguard Worker     handle = SharedMemory::DuplicateHandle(
1282*635a8641SAndroid Build Coastguard Worker         field_trial_list.field_trial_allocator_->shared_memory()->handle());
1283*635a8641SAndroid Build Coastguard Worker   }
1284*635a8641SAndroid Build Coastguard Worker 
1285*635a8641SAndroid Build Coastguard Worker   // Check that there's only one entry in the allocator.
1286*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list2(nullptr);
1287*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
1288*635a8641SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1289*635a8641SAndroid Build Coastguard Worker   shm.get()->Map(4 << 10);
1290*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
1291*635a8641SAndroid Build Coastguard Worker   std::string check_string;
1292*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string, false);
1293*635a8641SAndroid Build Coastguard Worker   ASSERT_EQ(check_string.find("Simulated"), std::string::npos);
1294*635a8641SAndroid Build Coastguard Worker }
1295*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialListTest,AssociateFieldTrialParams)1296*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, AssociateFieldTrialParams) {
1297*635a8641SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1298*635a8641SAndroid Build Coastguard Worker   scoped_feature_list.Init();
1299*635a8641SAndroid Build Coastguard Worker 
1300*635a8641SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1301*635a8641SAndroid Build Coastguard Worker   std::string group_name("Group1");
1302*635a8641SAndroid Build Coastguard Worker 
1303*635a8641SAndroid Build Coastguard Worker   // Create a field trial with some params.
1304*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(nullptr);
1305*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(trial_name, group_name);
1306*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1307*635a8641SAndroid Build Coastguard Worker   params["key1"] = "value1";
1308*635a8641SAndroid Build Coastguard Worker   params["key2"] = "value2";
1309*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1310*635a8641SAndroid Build Coastguard Worker       trial_name, group_name, params);
1311*635a8641SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1312*635a8641SAndroid Build Coastguard Worker 
1313*635a8641SAndroid Build Coastguard Worker   // Clear all cached params from the associator.
1314*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->ClearAllCachedParamsForTesting();
1315*635a8641SAndroid Build Coastguard Worker   // Check that the params have been cleared from the cache.
1316*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> cached_params;
1317*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->GetFieldTrialParamsWithoutFallback(
1318*635a8641SAndroid Build Coastguard Worker       trial_name, group_name, &cached_params);
1319*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(0U, cached_params.size());
1320*635a8641SAndroid Build Coastguard Worker 
1321*635a8641SAndroid Build Coastguard Worker   // Check that we fetch the param from shared memory properly.
1322*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> new_params;
1323*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams(trial_name,
1324*635a8641SAndroid Build Coastguard Worker                                                                 &new_params);
1325*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("value1", new_params["key1"]);
1326*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("value2", new_params["key2"]);
1327*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(2U, new_params.size());
1328*635a8641SAndroid Build Coastguard Worker }
1329*635a8641SAndroid Build Coastguard Worker 
1330*635a8641SAndroid Build Coastguard Worker #if defined(OS_FUCHSIA)
1331*635a8641SAndroid Build Coastguard Worker // TODO(crbug.com/752368): This is flaky on Fuchsia.
1332*635a8641SAndroid Build Coastguard Worker #define MAYBE_ClearParamsFromSharedMemory DISABLED_ClearParamsFromSharedMemory
1333*635a8641SAndroid Build Coastguard Worker #else
1334*635a8641SAndroid Build Coastguard Worker #define MAYBE_ClearParamsFromSharedMemory ClearParamsFromSharedMemory
1335*635a8641SAndroid Build Coastguard Worker #endif
TEST(FieldTrialListTest,MAYBE_ClearParamsFromSharedMemory)1336*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, MAYBE_ClearParamsFromSharedMemory) {
1337*635a8641SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1338*635a8641SAndroid Build Coastguard Worker   std::string group_name("Group1");
1339*635a8641SAndroid Build Coastguard Worker 
1340*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle handle;
1341*635a8641SAndroid Build Coastguard Worker   {
1342*635a8641SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list;
1343*635a8641SAndroid Build Coastguard Worker     scoped_feature_list.Init();
1344*635a8641SAndroid Build Coastguard Worker 
1345*635a8641SAndroid Build Coastguard Worker     // Create a field trial with some params.
1346*635a8641SAndroid Build Coastguard Worker     FieldTrialList field_trial_list(nullptr);
1347*635a8641SAndroid Build Coastguard Worker     FieldTrial* trial =
1348*635a8641SAndroid Build Coastguard Worker         FieldTrialList::CreateFieldTrial(trial_name, group_name);
1349*635a8641SAndroid Build Coastguard Worker     std::map<std::string, std::string> params;
1350*635a8641SAndroid Build Coastguard Worker     params["key1"] = "value1";
1351*635a8641SAndroid Build Coastguard Worker     params["key2"] = "value2";
1352*635a8641SAndroid Build Coastguard Worker     FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1353*635a8641SAndroid Build Coastguard Worker         trial_name, group_name, params);
1354*635a8641SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1355*635a8641SAndroid Build Coastguard Worker 
1356*635a8641SAndroid Build Coastguard Worker     // Clear all params from the associator AND shared memory. The allocated
1357*635a8641SAndroid Build Coastguard Worker     // segments should be different.
1358*635a8641SAndroid Build Coastguard Worker     FieldTrial::FieldTrialRef old_ref = trial->ref_;
1359*635a8641SAndroid Build Coastguard Worker     FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
1360*635a8641SAndroid Build Coastguard Worker     FieldTrial::FieldTrialRef new_ref = trial->ref_;
1361*635a8641SAndroid Build Coastguard Worker     EXPECT_NE(old_ref, new_ref);
1362*635a8641SAndroid Build Coastguard Worker 
1363*635a8641SAndroid Build Coastguard Worker     // Check that there are no params associated with the field trial anymore.
1364*635a8641SAndroid Build Coastguard Worker     std::map<std::string, std::string> new_params;
1365*635a8641SAndroid Build Coastguard Worker     FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams(trial_name,
1366*635a8641SAndroid Build Coastguard Worker                                                                   &new_params);
1367*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0U, new_params.size());
1368*635a8641SAndroid Build Coastguard Worker 
1369*635a8641SAndroid Build Coastguard Worker     // Now duplicate the handle so we can easily check that the trial is still
1370*635a8641SAndroid Build Coastguard Worker     // in shared memory via AllStatesToString.
1371*635a8641SAndroid Build Coastguard Worker     handle = SharedMemory::DuplicateHandle(
1372*635a8641SAndroid Build Coastguard Worker         field_trial_list.field_trial_allocator_->shared_memory()->handle());
1373*635a8641SAndroid Build Coastguard Worker   }
1374*635a8641SAndroid Build Coastguard Worker 
1375*635a8641SAndroid Build Coastguard Worker   // Check that we have the trial.
1376*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list2(nullptr);
1377*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
1378*635a8641SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1379*635a8641SAndroid Build Coastguard Worker   shm.get()->Map(4 << 10);
1380*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
1381*635a8641SAndroid Build Coastguard Worker   std::string check_string;
1382*635a8641SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string, false);
1383*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("*Trial1/Group1/", check_string);
1384*635a8641SAndroid Build Coastguard Worker }
1385*635a8641SAndroid Build Coastguard Worker 
TEST(FieldTrialListTest,DumpAndFetchFromSharedMemory)1386*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, DumpAndFetchFromSharedMemory) {
1387*635a8641SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1388*635a8641SAndroid Build Coastguard Worker   std::string group_name("Group1");
1389*635a8641SAndroid Build Coastguard Worker 
1390*635a8641SAndroid Build Coastguard Worker   // Create a field trial with some params.
1391*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(nullptr);
1392*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(trial_name, group_name);
1393*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1394*635a8641SAndroid Build Coastguard Worker   params["key1"] = "value1";
1395*635a8641SAndroid Build Coastguard Worker   params["key2"] = "value2";
1396*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1397*635a8641SAndroid Build Coastguard Worker       trial_name, group_name, params);
1398*635a8641SAndroid Build Coastguard Worker 
1399*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(new SharedMemory());
1400*635a8641SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1401*635a8641SAndroid Build Coastguard Worker   shm.get()->CreateAndMapAnonymous(4 << 10);
1402*635a8641SAndroid Build Coastguard Worker   // We _could_ use PersistentMemoryAllocator, this just has less params.
1403*635a8641SAndroid Build Coastguard Worker   SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
1404*635a8641SAndroid Build Coastguard Worker 
1405*635a8641SAndroid Build Coastguard Worker   // Dump and subsequently retrieve the field trial to |allocator|.
1406*635a8641SAndroid Build Coastguard Worker   FieldTrialList::DumpAllFieldTrialsToPersistentAllocator(&allocator);
1407*635a8641SAndroid Build Coastguard Worker   std::vector<const FieldTrial::FieldTrialEntry*> entries =
1408*635a8641SAndroid Build Coastguard Worker       FieldTrialList::GetAllFieldTrialsFromPersistentAllocator(allocator);
1409*635a8641SAndroid Build Coastguard Worker 
1410*635a8641SAndroid Build Coastguard Worker   // Check that we have the entry we put in.
1411*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(1u, entries.size());
1412*635a8641SAndroid Build Coastguard Worker   const FieldTrial::FieldTrialEntry* entry = entries[0];
1413*635a8641SAndroid Build Coastguard Worker 
1414*635a8641SAndroid Build Coastguard Worker   // Check that the trial and group names match.
1415*635a8641SAndroid Build Coastguard Worker   StringPiece shm_trial_name;
1416*635a8641SAndroid Build Coastguard Worker   StringPiece shm_group_name;
1417*635a8641SAndroid Build Coastguard Worker   entry->GetTrialAndGroupName(&shm_trial_name, &shm_group_name);
1418*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(trial_name, shm_trial_name);
1419*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(group_name, shm_group_name);
1420*635a8641SAndroid Build Coastguard Worker 
1421*635a8641SAndroid Build Coastguard Worker   // Check that the params match.
1422*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> shm_params;
1423*635a8641SAndroid Build Coastguard Worker   entry->GetParams(&shm_params);
1424*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(2u, shm_params.size());
1425*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("value1", shm_params["key1"]);
1426*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ("value2", shm_params["key2"]);
1427*635a8641SAndroid Build Coastguard Worker }
1428*635a8641SAndroid Build Coastguard Worker 
1429*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL)
TEST(FieldTrialListTest,SerializeSharedMemoryHandleMetadata)1430*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, SerializeSharedMemoryHandleMetadata) {
1431*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<SharedMemory> shm(new SharedMemory());
1432*635a8641SAndroid Build Coastguard Worker   shm->CreateAndMapAnonymous(4 << 10);
1433*635a8641SAndroid Build Coastguard Worker 
1434*635a8641SAndroid Build Coastguard Worker   std::string serialized =
1435*635a8641SAndroid Build Coastguard Worker       FieldTrialList::SerializeSharedMemoryHandleMetadata(shm->handle());
1436*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) || defined(OS_FUCHSIA)
1437*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle deserialized =
1438*635a8641SAndroid Build Coastguard Worker       FieldTrialList::DeserializeSharedMemoryHandleMetadata(serialized);
1439*635a8641SAndroid Build Coastguard Worker #else
1440*635a8641SAndroid Build Coastguard Worker   // Use a valid-looking arbitrary number for the file descriptor. It's not
1441*635a8641SAndroid Build Coastguard Worker   // being used in this unittest, but needs to pass sanity checks in the
1442*635a8641SAndroid Build Coastguard Worker   // handle's constructor.
1443*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle deserialized =
1444*635a8641SAndroid Build Coastguard Worker       FieldTrialList::DeserializeSharedMemoryHandleMetadata(42, serialized);
1445*635a8641SAndroid Build Coastguard Worker #endif
1446*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(deserialized.GetGUID(), shm->handle().GetGUID());
1447*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(deserialized.GetGUID().is_empty());
1448*635a8641SAndroid Build Coastguard Worker }
1449*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL)
1450*635a8641SAndroid Build Coastguard Worker 
1451*635a8641SAndroid Build Coastguard Worker // Verify that the field trial shared memory handle is really read-only, and
1452*635a8641SAndroid Build Coastguard Worker // does not allow writable mappings. Test disabled on NaCl, Windows and Fuchsia
1453*635a8641SAndroid Build Coastguard Worker // which don't support/implement GetFieldTrialHandle(). For Fuchsia, see
1454*635a8641SAndroid Build Coastguard Worker // crbug.com/752368
1455*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
TEST(FieldTrialListTest,CheckReadOnlySharedMemoryHandle)1456*635a8641SAndroid Build Coastguard Worker TEST(FieldTrialListTest, CheckReadOnlySharedMemoryHandle) {
1457*635a8641SAndroid Build Coastguard Worker   FieldTrialList field_trial_list(nullptr);
1458*635a8641SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1459*635a8641SAndroid Build Coastguard Worker 
1460*635a8641SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1461*635a8641SAndroid Build Coastguard Worker   scoped_feature_list.Init();
1462*635a8641SAndroid Build Coastguard Worker 
1463*635a8641SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1464*635a8641SAndroid Build Coastguard Worker 
1465*635a8641SAndroid Build Coastguard Worker   SharedMemoryHandle handle = FieldTrialList::GetFieldTrialHandle();
1466*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(handle.IsValid());
1467*635a8641SAndroid Build Coastguard Worker 
1468*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(CheckReadOnlySharedMemoryHandleForTesting(handle));
1469*635a8641SAndroid Build Coastguard Worker }
1470*635a8641SAndroid Build Coastguard Worker #endif  // !OS_NACL && !OS_WIN && !OS_FUCHSIA
1471*635a8641SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,TestAllParamsToString)1472*635a8641SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, TestAllParamsToString) {
1473*635a8641SAndroid Build Coastguard Worker   std::string exptected_output = "t1.g1:p1/v1/p2/v2";
1474*635a8641SAndroid Build Coastguard Worker 
1475*635a8641SAndroid Build Coastguard Worker   // Create study with one group and two params.
1476*635a8641SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1477*635a8641SAndroid Build Coastguard Worker   params["p1"] = "v1";
1478*635a8641SAndroid Build Coastguard Worker   params["p2"] = "v2";
1479*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1480*635a8641SAndroid Build Coastguard Worker       "t1", "g1", params);
1481*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(
1482*635a8641SAndroid Build Coastguard Worker       "", FieldTrialList::AllParamsToString(false, &MockEscapeQueryParamValue));
1483*635a8641SAndroid Build Coastguard Worker 
1484*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial1 =
1485*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("t1", 100, "Default", nullptr);
1486*635a8641SAndroid Build Coastguard Worker   trial1->AppendGroup("g1", 100);
1487*635a8641SAndroid Build Coastguard Worker   trial1->group();
1488*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(exptected_output, FieldTrialList::AllParamsToString(
1489*635a8641SAndroid Build Coastguard Worker                                   false, &MockEscapeQueryParamValue));
1490*635a8641SAndroid Build Coastguard Worker 
1491*635a8641SAndroid Build Coastguard Worker   // Create study with two groups and params that don't belog to the assigned
1492*635a8641SAndroid Build Coastguard Worker   // group. This should be in the output.
1493*635a8641SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1494*635a8641SAndroid Build Coastguard Worker       "t2", "g2", params);
1495*635a8641SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
1496*635a8641SAndroid Build Coastguard Worker       CreateFieldTrial("t2", 100, "Default", nullptr);
1497*635a8641SAndroid Build Coastguard Worker   trial2->AppendGroup("g1", 100);
1498*635a8641SAndroid Build Coastguard Worker   trial2->AppendGroup("g2", 0);
1499*635a8641SAndroid Build Coastguard Worker   trial2->group();
1500*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(exptected_output, FieldTrialList::AllParamsToString(
1501*635a8641SAndroid Build Coastguard Worker                                   false, &MockEscapeQueryParamValue));
1502*635a8641SAndroid Build Coastguard Worker }
1503*635a8641SAndroid Build Coastguard Worker 
1504*635a8641SAndroid Build Coastguard Worker }  // namespace base
1505