xref: /aosp_15_r20/external/cronet/base/metrics/field_trial_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <string_view>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/base_switches.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/build_time.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial_list_including_low_anonymity.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial_param_associator.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/mock_entropy_provider.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/test/multiprocess_test.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/test/test_shared_memory_util.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
30*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
31*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
32*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
33*6777b538SAndroid Build Coastguard Worker #include "testing/multiprocess_func_list.h"
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_BLINK)
36*6777b538SAndroid Build Coastguard Worker #include "base/process/launch.h"
37*6777b538SAndroid Build Coastguard Worker #endif
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX)
40*6777b538SAndroid Build Coastguard Worker #include "base/files/platform_file.h"
41*6777b538SAndroid Build Coastguard Worker #include "base/posix/global_descriptors.h"
42*6777b538SAndroid Build Coastguard Worker #endif
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
45*6777b538SAndroid Build Coastguard Worker #include "base/mac/mach_port_rendezvous.h"
46*6777b538SAndroid Build Coastguard Worker #endif
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker namespace base {
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker namespace {
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker // Default group name used by several tests.
53*6777b538SAndroid Build Coastguard Worker const char kDefaultGroupName[] = "DefaultGroup";
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker // Call FieldTrialList::FactoryGetFieldTrial().
CreateFieldTrial(const std::string & trial_name,int total_probability,const std::string & default_group_name,bool is_low_anonymity=false)56*6777b538SAndroid Build Coastguard Worker scoped_refptr<FieldTrial> CreateFieldTrial(
57*6777b538SAndroid Build Coastguard Worker     const std::string& trial_name,
58*6777b538SAndroid Build Coastguard Worker     int total_probability,
59*6777b538SAndroid Build Coastguard Worker     const std::string& default_group_name,
60*6777b538SAndroid Build Coastguard Worker     bool is_low_anonymity = false) {
61*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.9);
62*6777b538SAndroid Build Coastguard Worker   return FieldTrialList::FactoryGetFieldTrial(
63*6777b538SAndroid Build Coastguard Worker       trial_name, total_probability, default_group_name, entropy_provider, 0,
64*6777b538SAndroid Build Coastguard Worker       is_low_anonymity);
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker // A FieldTrialList::Observer implementation which stores the trial name and
68*6777b538SAndroid Build Coastguard Worker // group name received via OnFieldTrialGroupFinalized() for later inspection.
69*6777b538SAndroid Build Coastguard Worker class TestFieldTrialObserver : public FieldTrialList::Observer {
70*6777b538SAndroid Build Coastguard Worker  public:
TestFieldTrialObserver()71*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver() { FieldTrialList::AddObserver(this); }
72*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver(const TestFieldTrialObserver&) = delete;
73*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver& operator=(const TestFieldTrialObserver&) = delete;
74*6777b538SAndroid Build Coastguard Worker 
~TestFieldTrialObserver()75*6777b538SAndroid Build Coastguard Worker   ~TestFieldTrialObserver() override { FieldTrialList::RemoveObserver(this); }
76*6777b538SAndroid Build Coastguard Worker 
OnFieldTrialGroupFinalized(const FieldTrial & trial,const std::string & group)77*6777b538SAndroid Build Coastguard Worker   void OnFieldTrialGroupFinalized(const FieldTrial& trial,
78*6777b538SAndroid Build Coastguard Worker                                   const std::string& group) override {
79*6777b538SAndroid Build Coastguard Worker     trial_name_ = trial.trial_name();
80*6777b538SAndroid Build Coastguard Worker     group_name_ = group;
81*6777b538SAndroid Build Coastguard Worker   }
82*6777b538SAndroid Build Coastguard Worker 
trial_name() const83*6777b538SAndroid Build Coastguard Worker   const std::string& trial_name() const { return trial_name_; }
group_name() const84*6777b538SAndroid Build Coastguard Worker   const std::string& group_name() const { return group_name_; }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker  private:
87*6777b538SAndroid Build Coastguard Worker   std::string trial_name_;
88*6777b538SAndroid Build Coastguard Worker   std::string group_name_;
89*6777b538SAndroid Build Coastguard Worker };
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker // A FieldTrialList::Observer implementation which accesses the group of a
92*6777b538SAndroid Build Coastguard Worker // FieldTrial from OnFieldTrialGroupFinalized(). Used to test reentrancy.
93*6777b538SAndroid Build Coastguard Worker class FieldTrialObserverAccessingGroup : public FieldTrialList::Observer {
94*6777b538SAndroid Build Coastguard Worker  public:
95*6777b538SAndroid Build Coastguard Worker   // |trial_to_access| is the FieldTrial on which to invoke Activate() when
96*6777b538SAndroid Build Coastguard Worker   // receiving an OnFieldTrialGroupFinalized() notification.
FieldTrialObserverAccessingGroup(scoped_refptr<FieldTrial> trial_to_access)97*6777b538SAndroid Build Coastguard Worker   explicit FieldTrialObserverAccessingGroup(
98*6777b538SAndroid Build Coastguard Worker       scoped_refptr<FieldTrial> trial_to_access)
99*6777b538SAndroid Build Coastguard Worker       : trial_to_access_(trial_to_access) {
100*6777b538SAndroid Build Coastguard Worker     FieldTrialList::AddObserver(this);
101*6777b538SAndroid Build Coastguard Worker   }
102*6777b538SAndroid Build Coastguard Worker   FieldTrialObserverAccessingGroup(const FieldTrialObserverAccessingGroup&) =
103*6777b538SAndroid Build Coastguard Worker       delete;
104*6777b538SAndroid Build Coastguard Worker   FieldTrialObserverAccessingGroup& operator=(
105*6777b538SAndroid Build Coastguard Worker       const FieldTrialObserverAccessingGroup&) = delete;
106*6777b538SAndroid Build Coastguard Worker 
~FieldTrialObserverAccessingGroup()107*6777b538SAndroid Build Coastguard Worker   ~FieldTrialObserverAccessingGroup() override {
108*6777b538SAndroid Build Coastguard Worker     FieldTrialList::RemoveObserver(this);
109*6777b538SAndroid Build Coastguard Worker   }
110*6777b538SAndroid Build Coastguard Worker 
OnFieldTrialGroupFinalized(const base::FieldTrial & trial,const std::string & group)111*6777b538SAndroid Build Coastguard Worker   void OnFieldTrialGroupFinalized(const base::FieldTrial& trial,
112*6777b538SAndroid Build Coastguard Worker                                   const std::string& group) override {
113*6777b538SAndroid Build Coastguard Worker     trial_to_access_->Activate();
114*6777b538SAndroid Build Coastguard Worker   }
115*6777b538SAndroid Build Coastguard Worker 
116*6777b538SAndroid Build Coastguard Worker  private:
117*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial_to_access_;
118*6777b538SAndroid Build Coastguard Worker };
119*6777b538SAndroid Build Coastguard Worker 
MockEscapeQueryParamValue(const std::string & input)120*6777b538SAndroid Build Coastguard Worker std::string MockEscapeQueryParamValue(const std::string& input) {
121*6777b538SAndroid Build Coastguard Worker   return input;
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker }  // namespace
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker // Same as |TestFieldTrialObserver|, but registers for low anonymity field
127*6777b538SAndroid Build Coastguard Worker // trials too.
128*6777b538SAndroid Build Coastguard Worker class TestFieldTrialObserverIncludingLowAnonymity
129*6777b538SAndroid Build Coastguard Worker     : public FieldTrialList::Observer {
130*6777b538SAndroid Build Coastguard Worker  public:
TestFieldTrialObserverIncludingLowAnonymity()131*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserverIncludingLowAnonymity() {
132*6777b538SAndroid Build Coastguard Worker     FieldTrialListIncludingLowAnonymity::AddObserver(this);
133*6777b538SAndroid Build Coastguard Worker   }
134*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserverIncludingLowAnonymity(
135*6777b538SAndroid Build Coastguard Worker       const TestFieldTrialObserverIncludingLowAnonymity&) = delete;
136*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserverIncludingLowAnonymity& operator=(
137*6777b538SAndroid Build Coastguard Worker       const TestFieldTrialObserverIncludingLowAnonymity&) = delete;
138*6777b538SAndroid Build Coastguard Worker 
~TestFieldTrialObserverIncludingLowAnonymity()139*6777b538SAndroid Build Coastguard Worker   ~TestFieldTrialObserverIncludingLowAnonymity() override {
140*6777b538SAndroid Build Coastguard Worker     FieldTrialListIncludingLowAnonymity::RemoveObserver(this);
141*6777b538SAndroid Build Coastguard Worker   }
142*6777b538SAndroid Build Coastguard Worker 
OnFieldTrialGroupFinalized(const base::FieldTrial & trial,const std::string & group)143*6777b538SAndroid Build Coastguard Worker   void OnFieldTrialGroupFinalized(const base::FieldTrial& trial,
144*6777b538SAndroid Build Coastguard Worker                                   const std::string& group) override {
145*6777b538SAndroid Build Coastguard Worker     trial_name_ = trial.trial_name();
146*6777b538SAndroid Build Coastguard Worker     group_name_ = group;
147*6777b538SAndroid Build Coastguard Worker   }
148*6777b538SAndroid Build Coastguard Worker 
trial_name() const149*6777b538SAndroid Build Coastguard Worker   const std::string& trial_name() const { return trial_name_; }
group_name() const150*6777b538SAndroid Build Coastguard Worker   const std::string& group_name() const { return group_name_; }
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker  private:
153*6777b538SAndroid Build Coastguard Worker   std::string trial_name_;
154*6777b538SAndroid Build Coastguard Worker   std::string group_name_;
155*6777b538SAndroid Build Coastguard Worker };
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker class FieldTrialTest : public ::testing::Test {
158*6777b538SAndroid Build Coastguard Worker  public:
FieldTrialTest()159*6777b538SAndroid Build Coastguard Worker   FieldTrialTest() {
160*6777b538SAndroid Build Coastguard Worker     // The test suite instantiates a FieldTrialList but for the purpose of these
161*6777b538SAndroid Build Coastguard Worker     // tests it's cleaner to start from scratch.
162*6777b538SAndroid Build Coastguard Worker     scoped_feature_list_.InitWithEmptyFeatureAndFieldTrialLists();
163*6777b538SAndroid Build Coastguard Worker   }
164*6777b538SAndroid Build Coastguard Worker   FieldTrialTest(const FieldTrialTest&) = delete;
165*6777b538SAndroid Build Coastguard Worker   FieldTrialTest& operator=(const FieldTrialTest&) = delete;
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker  private:
168*6777b538SAndroid Build Coastguard Worker   test::TaskEnvironment task_environment_;
169*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list_;
170*6777b538SAndroid Build Coastguard Worker };
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker MATCHER(CompareActiveGroupToFieldTrial, "") {
173*6777b538SAndroid Build Coastguard Worker   const base::FieldTrial::ActiveGroup& lhs = ::testing::get<0>(arg);
174*6777b538SAndroid Build Coastguard Worker   const base::FieldTrial* rhs = ::testing::get<1>(arg).get();
175*6777b538SAndroid Build Coastguard Worker   return lhs.trial_name == rhs->trial_name() &&
176*6777b538SAndroid Build Coastguard Worker          lhs.group_name == rhs->group_name_internal();
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker // Test registration, and also check that destructors are called for trials.
TEST_F(FieldTrialTest,Registration)180*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Registration) {
181*6777b538SAndroid Build Coastguard Worker   const char name1[] = "name 1 test";
182*6777b538SAndroid Build Coastguard Worker   const char name2[] = "name 2 test";
183*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name1));
184*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name2));
185*6777b538SAndroid Build Coastguard Worker 
186*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial1 =
187*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(name1, 10, "default name 1 test");
188*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
189*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(name1, trial1->trial_name());
190*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", trial1->group_name_internal());
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker   trial1->AppendGroup(std::string(), 7);
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
195*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::Find(name2));
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
198*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(name2, 10, "default name 2 test");
199*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
200*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(name2, trial2->trial_name());
201*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", trial2->group_name_internal());
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   trial2->AppendGroup("a first group", 7);
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
206*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial2.get(), FieldTrialList::Find(name2));
207*6777b538SAndroid Build Coastguard Worker   // Note: FieldTrialList should delete the objects at shutdown.
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,AbsoluteProbabilities)210*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, AbsoluteProbabilities) {
211*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.51);
212*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
213*6777b538SAndroid Build Coastguard Worker       "trial name", 100, "Default", entropy_provider);
214*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("LoserA", 0);
215*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 100);
216*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("LoserB", 0);
217*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), "Winner");
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SmallProbabilities_49)220*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SmallProbabilities_49) {
221*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.49);
222*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
223*6777b538SAndroid Build Coastguard Worker       "trial name", 2, "Default", entropy_provider);
224*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("first", 1);
225*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("second", 1);
226*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), "first");
227*6777b538SAndroid Build Coastguard Worker }
228*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SmallProbabilities_51)229*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SmallProbabilities_51) {
230*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.51);
231*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
232*6777b538SAndroid Build Coastguard Worker       "trial name", 2, "Default", entropy_provider);
233*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("first", 1);
234*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("second", 1);
235*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), "second");
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,MiddleProbabilities_49)238*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, MiddleProbabilities_49) {
239*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.49);
240*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
241*6777b538SAndroid Build Coastguard Worker       "trial name", 10, "Default", entropy_provider);
242*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("NotDefault", 5);
243*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), "NotDefault");
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,MiddleProbabilities_51)246*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, MiddleProbabilities_51) {
247*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.51);
248*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
249*6777b538SAndroid Build Coastguard Worker       "trial name", 10, "Default", entropy_provider);
250*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("NotDefault", 5);
251*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial->group_name(), "Default");
252*6777b538SAndroid Build Coastguard Worker }
253*6777b538SAndroid Build Coastguard Worker 
254*6777b538SAndroid Build Coastguard Worker // AppendGroup after finalization should not change the winner.
TEST_F(FieldTrialTest,OneWinner)255*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, OneWinner) {
256*6777b538SAndroid Build Coastguard Worker   MockEntropyProvider entropy_provider(0.51);
257*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = FieldTrialList::FactoryGetFieldTrial(
258*6777b538SAndroid Build Coastguard Worker       "trial name", 10, "Default", entropy_provider);
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 5; ++i) {
261*6777b538SAndroid Build Coastguard Worker     trial->AppendGroup(StringPrintf("%d", i), 1);
262*6777b538SAndroid Build Coastguard Worker   }
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker   // Entropy 0.51 should assign to the 6th group.
265*6777b538SAndroid Build Coastguard Worker   // It should be declared the winner and stay that way.
266*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 1);
267*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Winner", trial->group_name());
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker   // Note: appending groups after calling group_name() is probably not really
270*6777b538SAndroid Build Coastguard Worker   // valid usage, since it will DCHECK if the default group won.
271*6777b538SAndroid Build Coastguard Worker   for (int i = 7; i < 10; ++i) {
272*6777b538SAndroid Build Coastguard Worker     trial->AppendGroup(StringPrintf("%d", i), 1);
273*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ("Winner", trial->group_name());
274*6777b538SAndroid Build Coastguard Worker   }
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ActiveGroups)277*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ActiveGroups) {
278*6777b538SAndroid Build Coastguard Worker   std::string no_group("No Group");
279*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = CreateFieldTrial(no_group, 10, "Default");
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker   // There is no winner yet, so no NameGroupId should be returned.
282*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroup active_group;
283*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker   // Create a single winning group.
286*6777b538SAndroid Build Coastguard Worker   std::string one_winner("One Winner");
287*6777b538SAndroid Build Coastguard Worker   trial = CreateFieldTrial(one_winner, 10, "Default");
288*6777b538SAndroid Build Coastguard Worker   std::string winner("Winner");
289*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup(winner, 10);
290*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
291*6777b538SAndroid Build Coastguard Worker   trial->Activate();
292*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(trial->GetActiveGroup(&active_group));
293*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(one_winner, active_group.trial_name);
294*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(winner, active_group.group_name);
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   std::string multi_group("MultiGroup");
297*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> multi_group_trial =
298*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(multi_group, 9, "Default");
299*6777b538SAndroid Build Coastguard Worker 
300*6777b538SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("Me", 3);
301*6777b538SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("You", 3);
302*6777b538SAndroid Build Coastguard Worker   multi_group_trial->AppendGroup("Them", 3);
303*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(multi_group_trial->GetActiveGroup(&active_group));
304*6777b538SAndroid Build Coastguard Worker   multi_group_trial->Activate();
305*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(multi_group_trial->GetActiveGroup(&active_group));
306*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(multi_group, active_group.trial_name);
307*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(multi_group_trial->group_name(), active_group.group_name);
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker   // Now check if the list is built properly...
310*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
311*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
312*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2U, active_groups.size());
313*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < active_groups.size(); ++i) {
314*6777b538SAndroid Build Coastguard Worker     // Order is not guaranteed, so check all values.
315*6777b538SAndroid Build Coastguard Worker     EXPECT_NE(no_group, active_groups[i].trial_name);
316*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(one_winner != active_groups[i].trial_name ||
317*6777b538SAndroid Build Coastguard Worker                 winner == active_groups[i].group_name);
318*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(multi_group != active_groups[i].trial_name ||
319*6777b538SAndroid Build Coastguard Worker                 multi_group_trial->group_name() == active_groups[i].group_name);
320*6777b538SAndroid Build Coastguard Worker   }
321*6777b538SAndroid Build Coastguard Worker }
322*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ActiveGroupsNotFinalized)323*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ActiveGroupsNotFinalized) {
324*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "TestTrial";
325*6777b538SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
328*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
329*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup(kSecondaryGroupName, 50);
330*6777b538SAndroid Build Coastguard Worker 
331*6777b538SAndroid Build Coastguard Worker   // Before |Activate()| is called, |GetActiveGroup()| should return false.
332*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroup active_group;
333*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->GetActiveGroup(&active_group));
334*6777b538SAndroid Build Coastguard Worker 
335*6777b538SAndroid Build Coastguard Worker   // |GetActiveFieldTrialGroups()| should also not include the trial.
336*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
337*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
338*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
339*6777b538SAndroid Build Coastguard Worker 
340*6777b538SAndroid Build Coastguard Worker   // After |Activate()| has been called, both APIs should succeed.
341*6777b538SAndroid Build Coastguard Worker   trial->Activate();
342*6777b538SAndroid Build Coastguard Worker 
343*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(trial->GetActiveGroup(&active_group));
344*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, active_group.trial_name);
345*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(kDefaultGroupName == active_group.group_name ||
346*6777b538SAndroid Build Coastguard Worker               kSecondaryGroupName == active_group.group_name);
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
349*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(1U, active_groups.size());
350*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, active_groups[0].trial_name);
351*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(active_group.group_name, active_groups[0].group_name);
352*6777b538SAndroid Build Coastguard Worker }
353*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,GetGroupNameWithoutActivation)354*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, GetGroupNameWithoutActivation) {
355*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "TestTrial";
356*6777b538SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
357*6777b538SAndroid Build Coastguard Worker 
358*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
359*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
360*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup(kSecondaryGroupName, 50);
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker   // The trial should start inactive.
363*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
364*6777b538SAndroid Build Coastguard Worker 
365*6777b538SAndroid Build Coastguard Worker   // Calling |GetGroupNameWithoutActivation()| should not activate the trial.
366*6777b538SAndroid Build Coastguard Worker   std::string group_name = trial->GetGroupNameWithoutActivation();
367*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(group_name.empty());
368*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   // Calling |group_name()| should activate it and return the same group name.
371*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(group_name, trial->group_name());
372*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
373*6777b538SAndroid Build Coastguard Worker }
374*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SaveAll)375*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SaveAll) {
376*6777b538SAndroid Build Coastguard Worker   std::string save_string;
377*6777b538SAndroid Build Coastguard Worker 
378*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
379*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Some name", 10, "Default some name");
380*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", trial->group_name_internal());
381*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
382*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name", save_string);
383*6777b538SAndroid Build Coastguard Worker   // Getting all states should have finalized the trial.
384*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Default some name", trial->group_name_internal());
385*6777b538SAndroid Build Coastguard Worker   save_string.clear();
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker   // Create a winning group.
388*6777b538SAndroid Build Coastguard Worker   trial = CreateFieldTrial("trial2", 10, "Default some name");
389*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
390*6777b538SAndroid Build Coastguard Worker   trial->Activate();
391*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
392*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner", save_string);
393*6777b538SAndroid Build Coastguard Worker   save_string.clear();
394*6777b538SAndroid Build Coastguard Worker 
395*6777b538SAndroid Build Coastguard Worker   // Create a second trial and winning group.
396*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 = CreateFieldTrial("xxx", 10, "Default xxx");
397*6777b538SAndroid Build Coastguard Worker   trial2->AppendGroup("yyyy", 10);
398*6777b538SAndroid Build Coastguard Worker   trial2->Activate();
399*6777b538SAndroid Build Coastguard Worker 
400*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
401*6777b538SAndroid Build Coastguard Worker   // We assume names are alphabetized... though this is not critical.
402*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy",
403*6777b538SAndroid Build Coastguard Worker             save_string);
404*6777b538SAndroid Build Coastguard Worker   save_string.clear();
405*6777b538SAndroid Build Coastguard Worker 
406*6777b538SAndroid Build Coastguard Worker   // Create a third trial with only the default group.
407*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial3 = CreateFieldTrial("zzz", 10, "default");
408*6777b538SAndroid Build Coastguard Worker 
409*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
410*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default",
411*6777b538SAndroid Build Coastguard Worker             save_string);
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker   save_string.clear();
414*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
415*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default",
416*6777b538SAndroid Build Coastguard Worker             save_string);
417*6777b538SAndroid Build Coastguard Worker }
418*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,Restore)419*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Restore) {
420*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
421*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("xxx"));
422*6777b538SAndroid Build Coastguard Worker 
423*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromString("Some_name/Winner/xxx/yyyy/");
424*6777b538SAndroid Build Coastguard Worker 
425*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("Some_name");
426*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
427*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Winner", trial->group_name());
428*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some_name", trial->trial_name());
429*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->IsOverridden());
430*6777b538SAndroid Build Coastguard Worker 
431*6777b538SAndroid Build Coastguard Worker   trial = FieldTrialList::Find("xxx");
432*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
433*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("yyyy", trial->group_name());
434*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("xxx", trial->trial_name());
435*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(trial->IsOverridden());
436*6777b538SAndroid Build Coastguard Worker }
437*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,RestoreNotEndingWithSlash)438*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, RestoreNotEndingWithSlash) {
439*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::CreateTrialsFromString("tname/gname"));
440*6777b538SAndroid Build Coastguard Worker 
441*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("tname");
442*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
443*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("gname", trial->group_name());
444*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("tname", trial->trial_name());
445*6777b538SAndroid Build Coastguard Worker }
446*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,BogusRestore)447*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, BogusRestore) {
448*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingSlash"));
449*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingGroupName/"));
450*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("noname, only group/"));
451*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("/emptyname"));
452*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("*/emptyname"));
453*6777b538SAndroid Build Coastguard Worker }
454*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DuplicateRestore)455*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DuplicateRestore) {
456*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
457*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Some name", 10, "Default");
458*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
459*6777b538SAndroid Build Coastguard Worker   trial->Activate();
460*6777b538SAndroid Build Coastguard Worker   std::string save_string;
461*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&save_string);
462*6777b538SAndroid Build Coastguard Worker   // * prefix since it is activated.
463*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("*Some name/Winner", save_string);
464*6777b538SAndroid Build Coastguard Worker 
465*6777b538SAndroid Build Coastguard Worker   // It is OK if we redundantly specify a winner.
466*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(save_string));
467*6777b538SAndroid Build Coastguard Worker 
468*6777b538SAndroid Build Coastguard Worker   // But it is an error to try to change to a different winner.
469*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("Some name/Loser/"));
470*6777b538SAndroid Build Coastguard Worker }
471*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActive)472*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringNotActive) {
473*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
474*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
475*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/Xyz/zyx/"));
476*6777b538SAndroid Build Coastguard Worker 
477*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
478*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
479*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(active_groups.empty());
480*6777b538SAndroid Build Coastguard Worker 
481*6777b538SAndroid Build Coastguard Worker   // Check that the values still get returned and querying them activates them.
482*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
483*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", FieldTrialList::FindFullName("Xyz"));
484*6777b538SAndroid Build Coastguard Worker 
485*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
486*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
487*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
488*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("def", active_groups[0].group_name);
489*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
490*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
491*6777b538SAndroid Build Coastguard Worker }
492*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringForceActivation)493*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringForceActivation) {
494*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
495*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("def"));
496*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
497*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(
498*6777b538SAndroid Build Coastguard Worker       FieldTrialList::CreateTrialsFromString("*Abc/cba/def/fed/*Xyz/zyx/"));
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
501*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
502*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
503*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
504*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("cba", active_groups[0].group_name);
505*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
506*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
507*6777b538SAndroid Build Coastguard Worker }
508*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActiveObserver)509*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateTrialsFromStringNotActiveObserver) {
510*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
511*6777b538SAndroid Build Coastguard Worker 
512*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver observer;
513*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/"));
514*6777b538SAndroid Build Coastguard Worker   RunLoop().RunUntilIdle();
515*6777b538SAndroid Build Coastguard Worker   // Observer shouldn't be notified.
516*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(observer.trial_name().empty());
517*6777b538SAndroid Build Coastguard Worker 
518*6777b538SAndroid Build Coastguard Worker   // Check that the values still get returned and querying them activates them.
519*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
520*6777b538SAndroid Build Coastguard Worker 
521*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", observer.trial_name());
522*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("def", observer.group_name());
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateFieldTrial)525*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateFieldTrial) {
526*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
527*6777b538SAndroid Build Coastguard Worker 
528*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Some_name", "Winner");
529*6777b538SAndroid Build Coastguard Worker 
530*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::Find("Some_name");
531*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
532*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Winner", trial->group_name());
533*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Some_name", trial->trial_name());
534*6777b538SAndroid Build Coastguard Worker }
535*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateFieldTrialIsNotActive)536*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateFieldTrialIsNotActive) {
537*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "CreateFieldTrialIsActiveTrial";
538*6777b538SAndroid Build Coastguard Worker   const char kWinnerGroup[] = "Winner";
539*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
540*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(kTrialName, kWinnerGroup);
541*6777b538SAndroid Build Coastguard Worker 
542*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
543*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
544*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(active_groups.empty());
545*6777b538SAndroid Build Coastguard Worker }
546*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DuplicateFieldTrial)547*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DuplicateFieldTrial) {
548*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
549*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Some_name", 10, "Default");
550*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Winner", 10);
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker   // It is OK if we redundantly specify a winner.
553*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("Some_name", "Winner");
554*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(trial1 != nullptr);
555*6777b538SAndroid Build Coastguard Worker 
556*6777b538SAndroid Build Coastguard Worker   // But it is an error to try to change to a different winner.
557*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("Some_name", "Loser");
558*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(trial2 == nullptr);
559*6777b538SAndroid Build Coastguard Worker }
560*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ForcedFieldTrials)561*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ForcedFieldTrials) {
562*6777b538SAndroid Build Coastguard Worker   // Validate we keep the forced choice.
563*6777b538SAndroid Build Coastguard Worker   FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Use the",
564*6777b538SAndroid Build Coastguard Worker                                                               "Force");
565*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ("Force", forced_trial->group_name().c_str());
566*6777b538SAndroid Build Coastguard Worker 
567*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> factory_trial =
568*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1000, "default");
569*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(factory_trial.get(), forced_trial);
570*6777b538SAndroid Build Coastguard Worker 
571*6777b538SAndroid Build Coastguard Worker   factory_trial->AppendGroup("Force", 100);
572*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", factory_trial->group_name());
573*6777b538SAndroid Build Coastguard Worker   factory_trial->AppendGroup("Dark Side", 100);
574*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", factory_trial->group_name());
575*6777b538SAndroid Build Coastguard Worker   factory_trial->AppendGroup("Duck Tape", 800);
576*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", factory_trial->group_name());
577*6777b538SAndroid Build Coastguard Worker }
578*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ForcedFieldTrialsDefaultGroup)579*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ForcedFieldTrialsDefaultGroup) {
580*6777b538SAndroid Build Coastguard Worker   // Forcing the default should use the proper group ID.
581*6777b538SAndroid Build Coastguard Worker   FieldTrial* forced_trial =
582*6777b538SAndroid Build Coastguard Worker       FieldTrialList::CreateFieldTrial("Trial Name", "Default");
583*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> factory_trial =
584*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Trial Name", 1000, "Default");
585*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(forced_trial, factory_trial.get());
586*6777b538SAndroid Build Coastguard Worker 
587*6777b538SAndroid Build Coastguard Worker   factory_trial->AppendGroup("Not Default", 100);
588*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ("Default", factory_trial->group_name().c_str());
589*6777b538SAndroid Build Coastguard Worker 
590*6777b538SAndroid Build Coastguard Worker   factory_trial->AppendGroup("Not Default Either", 800);
591*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ("Default", factory_trial->group_name().c_str());
592*6777b538SAndroid Build Coastguard Worker }
593*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForced)594*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForced) {
595*6777b538SAndroid Build Coastguard Worker   // Start by setting a trial for which we ensure a winner...
596*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
597*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default");
598*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(forced_trial, forced_trial);
599*6777b538SAndroid Build Coastguard Worker 
600*6777b538SAndroid Build Coastguard Worker   forced_trial->AppendGroup("Force", 1);
601*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", forced_trial->group_name());
602*6777b538SAndroid Build Coastguard Worker 
603*6777b538SAndroid Build Coastguard Worker   // Now force it.
604*6777b538SAndroid Build Coastguard Worker   forced_trial->SetForced();
605*6777b538SAndroid Build Coastguard Worker 
606*6777b538SAndroid Build Coastguard Worker   // Now try to set it up differently as a hard coded registration would.
607*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> hard_coded_trial =
608*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default");
609*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(hard_coded_trial, forced_trial);
610*6777b538SAndroid Build Coastguard Worker 
611*6777b538SAndroid Build Coastguard Worker   hard_coded_trial->AppendGroup("Force", 0);
612*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", hard_coded_trial->group_name());
613*6777b538SAndroid Build Coastguard Worker 
614*6777b538SAndroid Build Coastguard Worker   // Same thing if we would have done it to win again.
615*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> other_hard_coded_trial =
616*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial("Use the", 1, "default");
617*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(other_hard_coded_trial, forced_trial);
618*6777b538SAndroid Build Coastguard Worker 
619*6777b538SAndroid Build Coastguard Worker   other_hard_coded_trial->AppendGroup("Force", 1);
620*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Force", other_hard_coded_trial->group_name());
621*6777b538SAndroid Build Coastguard Worker }
622*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedDefaultOnly)623*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedDefaultOnly) {
624*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultOnly";
625*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
626*6777b538SAndroid Build Coastguard Worker 
627*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
628*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
629*6777b538SAndroid Build Coastguard Worker   trial->SetForced();
630*6777b538SAndroid Build Coastguard Worker 
631*6777b538SAndroid Build Coastguard Worker   trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
632*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, trial->group_name());
633*6777b538SAndroid Build Coastguard Worker }
634*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedDefaultWithExtraGroup)635*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedDefaultWithExtraGroup) {
636*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultWithExtraGroup";
637*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
638*6777b538SAndroid Build Coastguard Worker 
639*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
640*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
641*6777b538SAndroid Build Coastguard Worker   trial->SetForced();
642*6777b538SAndroid Build Coastguard Worker 
643*6777b538SAndroid Build Coastguard Worker   trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
644*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("Extra", 100);
645*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, trial->group_name());
646*6777b538SAndroid Build Coastguard Worker }
647*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedTurnFeatureOn)648*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedTurnFeatureOn) {
649*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedTurnFeatureOn";
650*6777b538SAndroid Build Coastguard Worker   const char kExtraGroupName[] = "Extra";
651*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
652*6777b538SAndroid Build Coastguard Worker 
653*6777b538SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that turns the feature on when the
654*6777b538SAndroid Build Coastguard Worker   // original hard-coded config had it disabled.
655*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
656*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
657*6777b538SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kExtraGroupName, 100);
658*6777b538SAndroid Build Coastguard Worker   forced_trial->SetForced();
659*6777b538SAndroid Build Coastguard Worker 
660*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
661*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
662*6777b538SAndroid Build Coastguard Worker   client_trial->AppendGroup(kExtraGroupName, 0);
663*6777b538SAndroid Build Coastguard Worker 
664*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
665*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kExtraGroupName, client_trial->group_name());
666*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
667*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kExtraGroupName, client_trial->group_name());
668*6777b538SAndroid Build Coastguard Worker }
669*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedTurnFeatureOff)670*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedTurnFeatureOff) {
671*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedTurnFeatureOff";
672*6777b538SAndroid Build Coastguard Worker   const char kExtraGroupName[] = "Extra";
673*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
674*6777b538SAndroid Build Coastguard Worker 
675*6777b538SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that turns the feature off when the
676*6777b538SAndroid Build Coastguard Worker   // original hard-coded config had it enabled.
677*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
678*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
679*6777b538SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kExtraGroupName, 0);
680*6777b538SAndroid Build Coastguard Worker   forced_trial->SetForced();
681*6777b538SAndroid Build Coastguard Worker 
682*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
683*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
684*6777b538SAndroid Build Coastguard Worker   client_trial->AppendGroup(kExtraGroupName, 100);
685*6777b538SAndroid Build Coastguard Worker 
686*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
687*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, client_trial->group_name());
688*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
689*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, client_trial->group_name());
690*6777b538SAndroid Build Coastguard Worker }
691*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedChangeDefault_Default)692*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedChangeDefault_Default) {
693*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultGroupChange";
694*6777b538SAndroid Build Coastguard Worker   const char kGroupAName[] = "A";
695*6777b538SAndroid Build Coastguard Worker   const char kGroupBName[] = "B";
696*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
697*6777b538SAndroid Build Coastguard Worker 
698*6777b538SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that switches which group is default
699*6777b538SAndroid Build Coastguard Worker   // and ensures that the non-forced code receives the correct group numbers.
700*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
701*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupAName);
702*6777b538SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kGroupBName, 100);
703*6777b538SAndroid Build Coastguard Worker   forced_trial->SetForced();
704*6777b538SAndroid Build Coastguard Worker 
705*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
706*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupBName);
707*6777b538SAndroid Build Coastguard Worker   client_trial->AppendGroup(kGroupAName, 50);
708*6777b538SAndroid Build Coastguard Worker 
709*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
710*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(kGroupAName, client_trial->group_name());
711*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
712*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupBName, client_trial->group_name());
713*6777b538SAndroid Build Coastguard Worker }
714*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,SetForcedChangeDefault_NonDefault)715*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, SetForcedChangeDefault_NonDefault) {
716*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "SetForcedDefaultGroupChange";
717*6777b538SAndroid Build Coastguard Worker   const char kGroupAName[] = "A";
718*6777b538SAndroid Build Coastguard Worker   const char kGroupBName[] = "B";
719*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
720*6777b538SAndroid Build Coastguard Worker 
721*6777b538SAndroid Build Coastguard Worker   // Simulate a server-side (forced) config that switches which group is default
722*6777b538SAndroid Build Coastguard Worker   // and ensures that the non-forced code receives the correct group numbers.
723*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> forced_trial =
724*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupAName);
725*6777b538SAndroid Build Coastguard Worker   forced_trial->AppendGroup(kGroupBName, 0);
726*6777b538SAndroid Build Coastguard Worker   forced_trial->SetForced();
727*6777b538SAndroid Build Coastguard Worker 
728*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> client_trial =
729*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kGroupBName);
730*6777b538SAndroid Build Coastguard Worker   client_trial->AppendGroup(kGroupAName, 50);
731*6777b538SAndroid Build Coastguard Worker 
732*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(client_trial->group_reported_);
733*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupAName, client_trial->group_name());
734*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(client_trial->group_reported_);
735*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupAName, client_trial->group_name());
736*6777b538SAndroid Build Coastguard Worker }
737*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,Observe)738*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, Observe) {
739*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve1";
740*6777b538SAndroid Build Coastguard Worker   const char kSecondaryGroupName[] = "SecondaryGroup";
741*6777b538SAndroid Build Coastguard Worker 
742*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver observer;
743*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
744*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, 100, kDefaultGroupName);
745*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup(kSecondaryGroupName, 50);
746*6777b538SAndroid Build Coastguard Worker   const std::string chosen_group_name = trial->group_name();
747*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(chosen_group_name == kDefaultGroupName ||
748*6777b538SAndroid Build Coastguard Worker               chosen_group_name == kSecondaryGroupName);
749*6777b538SAndroid Build Coastguard Worker 
750*6777b538SAndroid Build Coastguard Worker   // The observer should be notified synchronously by the group_name() call.
751*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, observer.trial_name());
752*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(chosen_group_name, observer.group_name());
753*6777b538SAndroid Build Coastguard Worker }
754*6777b538SAndroid Build Coastguard Worker 
755*6777b538SAndroid Build Coastguard Worker // Verify that no hang occurs when a FieldTrial group is selected from a
756*6777b538SAndroid Build Coastguard Worker // FieldTrialList::Observer::OnFieldTrialGroupFinalized() notification. If the
757*6777b538SAndroid Build Coastguard Worker // FieldTrialList's lock is held when observers are notified, this test will
758*6777b538SAndroid Build Coastguard Worker // hang due to reentrant lock acquisition when selecting the FieldTrial group.
TEST_F(FieldTrialTest,ObserveReentrancy)759*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ObserveReentrancy) {
760*6777b538SAndroid Build Coastguard Worker   const char kTrialName1[] = "TrialToObserve1";
761*6777b538SAndroid Build Coastguard Worker   const char kTrialName2[] = "TrialToObserve2";
762*6777b538SAndroid Build Coastguard Worker 
763*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial_1 =
764*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName1, 100, kDefaultGroupName);
765*6777b538SAndroid Build Coastguard Worker 
766*6777b538SAndroid Build Coastguard Worker   FieldTrialObserverAccessingGroup observer(trial_1);
767*6777b538SAndroid Build Coastguard Worker 
768*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial_2 =
769*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName2, 100, kDefaultGroupName);
770*6777b538SAndroid Build Coastguard Worker 
771*6777b538SAndroid Build Coastguard Worker   // No group should be selected for |trial_1| yet.
772*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial_1->group_);
773*6777b538SAndroid Build Coastguard Worker 
774*6777b538SAndroid Build Coastguard Worker   // Force selection of a group for |trial_2|. This will notify |observer| which
775*6777b538SAndroid Build Coastguard Worker   // will force the selection of a group for |trial_1|. This should not hang.
776*6777b538SAndroid Build Coastguard Worker   trial_2->Activate();
777*6777b538SAndroid Build Coastguard Worker 
778*6777b538SAndroid Build Coastguard Worker   // The above call should have selected a group for |trial_1|.
779*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(FieldTrial::kNotFinalized, trial_1->group_);
780*6777b538SAndroid Build Coastguard Worker }
781*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,NotDisabled)782*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, NotDisabled) {
783*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "NotDisabled";
784*6777b538SAndroid Build Coastguard Worker   const char kGroupName[] = "Group2";
785*6777b538SAndroid Build Coastguard Worker   const int kProbability = 100;
786*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
787*6777b538SAndroid Build Coastguard Worker 
788*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial =
789*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(kTrialName, kProbability, kDefaultGroupName);
790*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup(kGroupName, kProbability);
791*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kGroupName, trial->group_name());
792*6777b538SAndroid Build Coastguard Worker }
793*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,FloatBoundariesGiveEqualGroupSizes)794*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes) {
795*6777b538SAndroid Build Coastguard Worker   const int kBucketCount = 100;
796*6777b538SAndroid Build Coastguard Worker 
797*6777b538SAndroid Build Coastguard Worker   // Try each boundary value |i / 100.0| as the entropy value.
798*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kBucketCount; ++i) {
799*6777b538SAndroid Build Coastguard Worker     const double entropy = i / static_cast<double>(kBucketCount);
800*6777b538SAndroid Build Coastguard Worker 
801*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial(
802*6777b538SAndroid Build Coastguard Worker         new FieldTrial("test", kBucketCount, "default", entropy,
803*6777b538SAndroid Build Coastguard Worker                        /*is_low_anonymity=*/false, /*is_overridden=*/false));
804*6777b538SAndroid Build Coastguard Worker     for (int j = 0; j < kBucketCount; ++j)
805*6777b538SAndroid Build Coastguard Worker       trial->AppendGroup(NumberToString(j), 1);
806*6777b538SAndroid Build Coastguard Worker 
807*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(NumberToString(i), trial->group_name());
808*6777b538SAndroid Build Coastguard Worker   }
809*6777b538SAndroid Build Coastguard Worker }
810*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,DoesNotSurpassTotalProbability)811*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, DoesNotSurpassTotalProbability) {
812*6777b538SAndroid Build Coastguard Worker   const double kEntropyValue = 1.0 - 1e-9;
813*6777b538SAndroid Build Coastguard Worker   ASSERT_LT(kEntropyValue, 1.0);
814*6777b538SAndroid Build Coastguard Worker 
815*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial(
816*6777b538SAndroid Build Coastguard Worker       new FieldTrial("test", 2, "default", kEntropyValue,
817*6777b538SAndroid Build Coastguard Worker                      /*is_low_anonymity=*/false, /*is_overridden=*/false));
818*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("1", 1);
819*6777b538SAndroid Build Coastguard Worker   trial->AppendGroup("2", 1);
820*6777b538SAndroid Build Coastguard Worker 
821*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("2", trial->group_name());
822*6777b538SAndroid Build Coastguard Worker }
823*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,CreateSimulatedFieldTrial)824*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, CreateSimulatedFieldTrial) {
825*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "CreateSimulatedFieldTrial";
826*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
827*6777b538SAndroid Build Coastguard Worker 
828*6777b538SAndroid Build Coastguard Worker   // Different cases to test, e.g. default vs. non default group being chosen.
829*6777b538SAndroid Build Coastguard Worker   struct {
830*6777b538SAndroid Build Coastguard Worker     double entropy_value;
831*6777b538SAndroid Build Coastguard Worker     const char* expected_group;
832*6777b538SAndroid Build Coastguard Worker   } test_cases[] = {
833*6777b538SAndroid Build Coastguard Worker     { 0.4, "A" },
834*6777b538SAndroid Build Coastguard Worker     { 0.85, "B" },
835*6777b538SAndroid Build Coastguard Worker     { 0.95, kDefaultGroupName },
836*6777b538SAndroid Build Coastguard Worker   };
837*6777b538SAndroid Build Coastguard Worker 
838*6777b538SAndroid Build Coastguard Worker   for (auto& test_case : test_cases) {
839*6777b538SAndroid Build Coastguard Worker     TestFieldTrialObserver observer;
840*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial(FieldTrial::CreateSimulatedFieldTrial(
841*6777b538SAndroid Build Coastguard Worker         kTrialName, 100, kDefaultGroupName, test_case.entropy_value));
842*6777b538SAndroid Build Coastguard Worker     trial->AppendGroup("A", 80);
843*6777b538SAndroid Build Coastguard Worker     trial->AppendGroup("B", 10);
844*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.expected_group, trial->group_name());
845*6777b538SAndroid Build Coastguard Worker 
846*6777b538SAndroid Build Coastguard Worker     // Field trial shouldn't have been registered with the list.
847*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(FieldTrialList::TrialExists(kTrialName));
848*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0u, FieldTrialList::GetFieldTrialCount());
849*6777b538SAndroid Build Coastguard Worker 
850*6777b538SAndroid Build Coastguard Worker     // Observer shouldn't have been notified.
851*6777b538SAndroid Build Coastguard Worker     RunLoop().RunUntilIdle();
852*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(observer.trial_name().empty());
853*6777b538SAndroid Build Coastguard Worker 
854*6777b538SAndroid Build Coastguard Worker     // The trial shouldn't be in the active set of trials.
855*6777b538SAndroid Build Coastguard Worker     FieldTrial::ActiveGroups active_groups;
856*6777b538SAndroid Build Coastguard Worker     FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
857*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(active_groups.empty());
858*6777b538SAndroid Build Coastguard Worker 
859*6777b538SAndroid Build Coastguard Worker     // The trial shouldn't be listed in the |AllStatesToString()| result.
860*6777b538SAndroid Build Coastguard Worker     std::string states;
861*6777b538SAndroid Build Coastguard Worker     FieldTrialList::AllStatesToString(&states);
862*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(states.empty());
863*6777b538SAndroid Build Coastguard Worker   }
864*6777b538SAndroid Build Coastguard Worker }
865*6777b538SAndroid Build Coastguard Worker 
TEST(FieldTrialTestWithoutList,StatesStringFormat)866*6777b538SAndroid Build Coastguard Worker TEST(FieldTrialTestWithoutList, StatesStringFormat) {
867*6777b538SAndroid Build Coastguard Worker   std::string save_string;
868*6777b538SAndroid Build Coastguard Worker 
869*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
870*6777b538SAndroid Build Coastguard Worker   // The test suite instantiates a FieldTrialList but for the purpose of these
871*6777b538SAndroid Build Coastguard Worker   // tests it's cleaner to start from scratch.
872*6777b538SAndroid Build Coastguard Worker   scoped_feature_list.InitWithEmptyFeatureAndFieldTrialLists();
873*6777b538SAndroid Build Coastguard Worker 
874*6777b538SAndroid Build Coastguard Worker   // Scoping the first FieldTrialList, as we need another one to test the
875*6777b538SAndroid Build Coastguard Worker   // importing function.
876*6777b538SAndroid Build Coastguard Worker   {
877*6777b538SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list1;
878*6777b538SAndroid Build Coastguard Worker     scoped_feature_list1.InitWithNullFeatureAndFieldTrialLists();
879*6777b538SAndroid Build Coastguard Worker     FieldTrialList field_trial_list;
880*6777b538SAndroid Build Coastguard Worker 
881*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial =
882*6777b538SAndroid Build Coastguard Worker         CreateFieldTrial("Abc", 10, "Default some name");
883*6777b538SAndroid Build Coastguard Worker     trial->AppendGroup("cba", 10);
884*6777b538SAndroid Build Coastguard Worker     trial->Activate();
885*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial2 =
886*6777b538SAndroid Build Coastguard Worker         CreateFieldTrial("Xyz", 10, "Default xxx");
887*6777b538SAndroid Build Coastguard Worker     trial2->AppendGroup("zyx", 10);
888*6777b538SAndroid Build Coastguard Worker     trial2->Activate();
889*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> trial3 = CreateFieldTrial("zzz", 10, "default");
890*6777b538SAndroid Build Coastguard Worker 
891*6777b538SAndroid Build Coastguard Worker     FieldTrialList::AllStatesToString(&save_string);
892*6777b538SAndroid Build Coastguard Worker   }
893*6777b538SAndroid Build Coastguard Worker 
894*6777b538SAndroid Build Coastguard Worker   // Starting with a new blank FieldTrialList.
895*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list2;
896*6777b538SAndroid Build Coastguard Worker   scoped_feature_list2.InitWithNullFeatureAndFieldTrialLists();
897*6777b538SAndroid Build Coastguard Worker   FieldTrialList field_trial_list;
898*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(field_trial_list.CreateTrialsFromString(save_string));
899*6777b538SAndroid Build Coastguard Worker 
900*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
901*6777b538SAndroid Build Coastguard Worker   field_trial_list.GetActiveFieldTrialGroups(&active_groups);
902*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(2U, active_groups.size());
903*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Abc", active_groups[0].trial_name);
904*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("cba", active_groups[0].group_name);
905*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Xyz", active_groups[1].trial_name);
906*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("zyx", active_groups[1].group_name);
907*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(field_trial_list.TrialExists("zzz"));
908*6777b538SAndroid Build Coastguard Worker }
909*6777b538SAndroid Build Coastguard Worker 
910*6777b538SAndroid Build Coastguard Worker class FieldTrialListTest : public ::testing::Test {
911*6777b538SAndroid Build Coastguard Worker  public:
FieldTrialListTest()912*6777b538SAndroid Build Coastguard Worker   FieldTrialListTest() {
913*6777b538SAndroid Build Coastguard Worker     // The test suite instantiates a FieldTrialList but for the purpose of these
914*6777b538SAndroid Build Coastguard Worker     // tests it's cleaner to start from scratch.
915*6777b538SAndroid Build Coastguard Worker     scoped_feature_list_.InitWithEmptyFeatureAndFieldTrialLists();
916*6777b538SAndroid Build Coastguard Worker   }
917*6777b538SAndroid Build Coastguard Worker 
918*6777b538SAndroid Build Coastguard Worker  private:
919*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list_;
920*6777b538SAndroid Build Coastguard Worker };
921*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,InstantiateAllocator)922*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, InstantiateAllocator) {
923*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
924*6777b538SAndroid Build Coastguard Worker   scoped_feature_list.InitWithEmptyFeatureAndFieldTrialLists();
925*6777b538SAndroid Build Coastguard Worker 
926*6777b538SAndroid Build Coastguard Worker   FieldTrialList* field_trial_list = FieldTrialList::GetInstance();
927*6777b538SAndroid Build Coastguard Worker 
928*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Trial1", "Group1");
929*6777b538SAndroid Build Coastguard Worker 
930*6777b538SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
931*6777b538SAndroid Build Coastguard Worker   const void* memory = field_trial_list->field_trial_allocator_->data();
932*6777b538SAndroid Build Coastguard Worker   size_t used = field_trial_list->field_trial_allocator_->used();
933*6777b538SAndroid Build Coastguard Worker 
934*6777b538SAndroid Build Coastguard Worker   // Ensure that the function is idempotent.
935*6777b538SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
936*6777b538SAndroid Build Coastguard Worker   const void* new_memory = field_trial_list->field_trial_allocator_->data();
937*6777b538SAndroid Build Coastguard Worker   size_t new_used = field_trial_list->field_trial_allocator_->used();
938*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(memory, new_memory);
939*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(used, new_used);
940*6777b538SAndroid Build Coastguard Worker }
941*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,AddTrialsToAllocator)942*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, AddTrialsToAllocator) {
943*6777b538SAndroid Build Coastguard Worker   std::string save_string;
944*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryRegion shm_region;
945*6777b538SAndroid Build Coastguard Worker 
946*6777b538SAndroid Build Coastguard Worker   // Scoping the first FieldTrialList, as we need another one to test that it
947*6777b538SAndroid Build Coastguard Worker   // matches.
948*6777b538SAndroid Build Coastguard Worker   {
949*6777b538SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list1;
950*6777b538SAndroid Build Coastguard Worker     scoped_feature_list1.InitWithEmptyFeatureAndFieldTrialLists();
951*6777b538SAndroid Build Coastguard Worker 
952*6777b538SAndroid Build Coastguard Worker     FieldTrialList::CreateFieldTrial("Trial1", "Group1");
953*6777b538SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
954*6777b538SAndroid Build Coastguard Worker     FieldTrialList::AllStatesToString(&save_string);
955*6777b538SAndroid Build Coastguard Worker     shm_region = FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting();
956*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(shm_region.IsValid());
957*6777b538SAndroid Build Coastguard Worker   }
958*6777b538SAndroid Build Coastguard Worker 
959*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list2;
960*6777b538SAndroid Build Coastguard Worker   scoped_feature_list2.InitWithEmptyFeatureAndFieldTrialLists();
961*6777b538SAndroid Build Coastguard Worker 
962*6777b538SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
963*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryMapping shm_mapping = shm_region.MapAt(0, 4 << 10);
964*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(shm_mapping.IsValid());
965*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemoryMapping(std::move(shm_mapping));
966*6777b538SAndroid Build Coastguard Worker   std::string check_string;
967*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string);
968*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(save_string, check_string);
969*6777b538SAndroid Build Coastguard Worker }
970*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,DoNotAddSimulatedFieldTrialsToAllocator)971*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, DoNotAddSimulatedFieldTrialsToAllocator) {
972*6777b538SAndroid Build Coastguard Worker   constexpr char kTrialName[] = "trial";
973*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryRegion shm_region;
974*6777b538SAndroid Build Coastguard Worker   {
975*6777b538SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list1;
976*6777b538SAndroid Build Coastguard Worker     scoped_feature_list1.InitWithEmptyFeatureAndFieldTrialLists();
977*6777b538SAndroid Build Coastguard Worker 
978*6777b538SAndroid Build Coastguard Worker     // Create a simulated trial and a real trial and call Activate() on them,
979*6777b538SAndroid Build Coastguard Worker     // which should only add the real trial to the field trial allocator.
980*6777b538SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
981*6777b538SAndroid Build Coastguard Worker 
982*6777b538SAndroid Build Coastguard Worker     // This shouldn't add to the allocator.
983*6777b538SAndroid Build Coastguard Worker     scoped_refptr<FieldTrial> simulated_trial =
984*6777b538SAndroid Build Coastguard Worker         FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, "Simulated",
985*6777b538SAndroid Build Coastguard Worker                                               0.95);
986*6777b538SAndroid Build Coastguard Worker     simulated_trial->Activate();
987*6777b538SAndroid Build Coastguard Worker 
988*6777b538SAndroid Build Coastguard Worker     // This should add to the allocator.
989*6777b538SAndroid Build Coastguard Worker     FieldTrial* real_trial =
990*6777b538SAndroid Build Coastguard Worker         FieldTrialList::CreateFieldTrial(kTrialName, "Real");
991*6777b538SAndroid Build Coastguard Worker     real_trial->Activate();
992*6777b538SAndroid Build Coastguard Worker 
993*6777b538SAndroid Build Coastguard Worker     shm_region = FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting();
994*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(shm_region.IsValid());
995*6777b538SAndroid Build Coastguard Worker   }
996*6777b538SAndroid Build Coastguard Worker 
997*6777b538SAndroid Build Coastguard Worker   // Check that there's only one entry in the allocator.
998*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list2;
999*6777b538SAndroid Build Coastguard Worker   scoped_feature_list2.InitWithEmptyFeatureAndFieldTrialLists();
1000*6777b538SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1001*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryMapping shm_mapping = shm_region.MapAt(0, 4 << 10);
1002*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(shm_mapping.IsValid());
1003*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemoryMapping(std::move(shm_mapping));
1004*6777b538SAndroid Build Coastguard Worker   std::string check_string;
1005*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string);
1006*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(check_string.find("Simulated"), std::string::npos);
1007*6777b538SAndroid Build Coastguard Worker }
1008*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,AssociateFieldTrialParams)1009*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, AssociateFieldTrialParams) {
1010*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1011*6777b538SAndroid Build Coastguard Worker   scoped_feature_list.InitWithEmptyFeatureAndFieldTrialLists();
1012*6777b538SAndroid Build Coastguard Worker 
1013*6777b538SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1014*6777b538SAndroid Build Coastguard Worker   std::string group_name("Group1");
1015*6777b538SAndroid Build Coastguard Worker 
1016*6777b538SAndroid Build Coastguard Worker   // Create a field trial with some params.
1017*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(trial_name, group_name);
1018*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1019*6777b538SAndroid Build Coastguard Worker   params["key1"] = "value1";
1020*6777b538SAndroid Build Coastguard Worker   params["key2"] = "value2";
1021*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1022*6777b538SAndroid Build Coastguard Worker       trial_name, group_name, params);
1023*6777b538SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1024*6777b538SAndroid Build Coastguard Worker 
1025*6777b538SAndroid Build Coastguard Worker   // Clear all cached params from the associator.
1026*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->ClearAllCachedParamsForTesting();
1027*6777b538SAndroid Build Coastguard Worker   // Check that the params have been cleared from the cache.
1028*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> cached_params;
1029*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->GetFieldTrialParamsWithoutFallback(
1030*6777b538SAndroid Build Coastguard Worker       trial_name, group_name, &cached_params);
1031*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0U, cached_params.size());
1032*6777b538SAndroid Build Coastguard Worker 
1033*6777b538SAndroid Build Coastguard Worker   // Check that we fetch the param from shared memory properly.
1034*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> new_params;
1035*6777b538SAndroid Build Coastguard Worker   GetFieldTrialParams(trial_name, &new_params);
1036*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("value1", new_params["key1"]);
1037*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("value2", new_params["key2"]);
1038*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2U, new_params.size());
1039*6777b538SAndroid Build Coastguard Worker }
1040*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,ClearParamsFromSharedMemory)1041*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, ClearParamsFromSharedMemory) {
1042*6777b538SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1043*6777b538SAndroid Build Coastguard Worker   std::string group_name("Group1");
1044*6777b538SAndroid Build Coastguard Worker 
1045*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryRegion shm_region;
1046*6777b538SAndroid Build Coastguard Worker   {
1047*6777b538SAndroid Build Coastguard Worker     test::ScopedFeatureList scoped_feature_list1;
1048*6777b538SAndroid Build Coastguard Worker     scoped_feature_list1.InitWithEmptyFeatureAndFieldTrialLists();
1049*6777b538SAndroid Build Coastguard Worker 
1050*6777b538SAndroid Build Coastguard Worker     // Create a field trial with some params.
1051*6777b538SAndroid Build Coastguard Worker     FieldTrial* trial =
1052*6777b538SAndroid Build Coastguard Worker         FieldTrialList::CreateFieldTrial(trial_name, group_name);
1053*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> params;
1054*6777b538SAndroid Build Coastguard Worker     params["key1"] = "value1";
1055*6777b538SAndroid Build Coastguard Worker     params["key2"] = "value2";
1056*6777b538SAndroid Build Coastguard Worker     FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1057*6777b538SAndroid Build Coastguard Worker         trial_name, group_name, params);
1058*6777b538SAndroid Build Coastguard Worker     FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1059*6777b538SAndroid Build Coastguard Worker 
1060*6777b538SAndroid Build Coastguard Worker     // Clear all params from the associator AND shared memory. The allocated
1061*6777b538SAndroid Build Coastguard Worker     // segments should be different.
1062*6777b538SAndroid Build Coastguard Worker     FieldTrial::FieldTrialRef old_ref = trial->ref_;
1063*6777b538SAndroid Build Coastguard Worker     FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
1064*6777b538SAndroid Build Coastguard Worker     FieldTrial::FieldTrialRef new_ref = trial->ref_;
1065*6777b538SAndroid Build Coastguard Worker     EXPECT_NE(old_ref, new_ref);
1066*6777b538SAndroid Build Coastguard Worker 
1067*6777b538SAndroid Build Coastguard Worker     // Check that there are no params associated with the field trial anymore.
1068*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> new_params;
1069*6777b538SAndroid Build Coastguard Worker     GetFieldTrialParams(trial_name, &new_params);
1070*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0U, new_params.size());
1071*6777b538SAndroid Build Coastguard Worker 
1072*6777b538SAndroid Build Coastguard Worker     // Now duplicate the handle so we can easily check that the trial is still
1073*6777b538SAndroid Build Coastguard Worker     // in shared memory via AllStatesToString.
1074*6777b538SAndroid Build Coastguard Worker     shm_region = FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting();
1075*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(shm_region.IsValid());
1076*6777b538SAndroid Build Coastguard Worker   }
1077*6777b538SAndroid Build Coastguard Worker 
1078*6777b538SAndroid Build Coastguard Worker   // Check that we have the trial.
1079*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list2;
1080*6777b538SAndroid Build Coastguard Worker   scoped_feature_list2.InitWithEmptyFeatureAndFieldTrialLists();
1081*6777b538SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1082*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryMapping shm_mapping = shm_region.MapAt(0, 4 << 10);
1083*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(shm_mapping.IsValid());
1084*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsFromSharedMemoryMapping(std::move(shm_mapping));
1085*6777b538SAndroid Build Coastguard Worker   std::string check_string;
1086*6777b538SAndroid Build Coastguard Worker   FieldTrialList::AllStatesToString(&check_string);
1087*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("*Trial1/Group1", check_string);
1088*6777b538SAndroid Build Coastguard Worker }
1089*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,DumpAndFetchFromSharedMemory)1090*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, DumpAndFetchFromSharedMemory) {
1091*6777b538SAndroid Build Coastguard Worker   std::string trial_name("Trial1");
1092*6777b538SAndroid Build Coastguard Worker   std::string group_name("Group1");
1093*6777b538SAndroid Build Coastguard Worker 
1094*6777b538SAndroid Build Coastguard Worker   // Create a field trial with some params.
1095*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1096*6777b538SAndroid Build Coastguard Worker   scoped_feature_list.InitWithEmptyFeatureAndFieldTrialLists();
1097*6777b538SAndroid Build Coastguard Worker 
1098*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial(trial_name, group_name);
1099*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Trial2", "Group2", false,
1100*6777b538SAndroid Build Coastguard Worker                                    /*is_overridden=*/true);
1101*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1102*6777b538SAndroid Build Coastguard Worker   params["key1"] = "value1";
1103*6777b538SAndroid Build Coastguard Worker   params["key2"] = "value2";
1104*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1105*6777b538SAndroid Build Coastguard Worker       trial_name, group_name, params);
1106*6777b538SAndroid Build Coastguard Worker 
1107*6777b538SAndroid Build Coastguard Worker   // 4 KiB is enough to hold the trials only created for this test.
1108*6777b538SAndroid Build Coastguard Worker   base::MappedReadOnlyRegion shm =
1109*6777b538SAndroid Build Coastguard Worker       base::ReadOnlySharedMemoryRegion::Create(4 << 10);
1110*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(shm.IsValid());
1111*6777b538SAndroid Build Coastguard Worker   // We _could_ use PersistentMemoryAllocator, this just has less params.
1112*6777b538SAndroid Build Coastguard Worker   WritableSharedPersistentMemoryAllocator allocator(std::move(shm.mapping), 1,
1113*6777b538SAndroid Build Coastguard Worker                                                     "");
1114*6777b538SAndroid Build Coastguard Worker 
1115*6777b538SAndroid Build Coastguard Worker   // Dump and subsequently retrieve the field trial to |allocator|.
1116*6777b538SAndroid Build Coastguard Worker   FieldTrialList::DumpAllFieldTrialsToPersistentAllocator(&allocator);
1117*6777b538SAndroid Build Coastguard Worker   std::vector<const FieldTrial::FieldTrialEntry*> entries =
1118*6777b538SAndroid Build Coastguard Worker       FieldTrialList::GetAllFieldTrialsFromPersistentAllocator(allocator);
1119*6777b538SAndroid Build Coastguard Worker 
1120*6777b538SAndroid Build Coastguard Worker   // Check that we have the entry we put in.
1121*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, entries.size());
1122*6777b538SAndroid Build Coastguard Worker   const FieldTrial::FieldTrialEntry* entry1 = entries[0];
1123*6777b538SAndroid Build Coastguard Worker   const FieldTrial::FieldTrialEntry* entry2 = entries[1];
1124*6777b538SAndroid Build Coastguard Worker 
1125*6777b538SAndroid Build Coastguard Worker   // Check that the trial information matches.
1126*6777b538SAndroid Build Coastguard Worker   std::string_view shm_trial_name;
1127*6777b538SAndroid Build Coastguard Worker   std::string_view shm_group_name;
1128*6777b538SAndroid Build Coastguard Worker   bool overridden;
1129*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(entry1->GetState(shm_trial_name, shm_group_name, overridden));
1130*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(trial_name, shm_trial_name);
1131*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(group_name, shm_group_name);
1132*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(overridden);
1133*6777b538SAndroid Build Coastguard Worker 
1134*6777b538SAndroid Build Coastguard Worker   // Check that the params match.
1135*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> shm_params;
1136*6777b538SAndroid Build Coastguard Worker   entry1->GetParams(&shm_params);
1137*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, shm_params.size());
1138*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("value1", shm_params["key1"]);
1139*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("value2", shm_params["key2"]);
1140*6777b538SAndroid Build Coastguard Worker 
1141*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(entry2->GetState(shm_trial_name, shm_group_name, overridden));
1142*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial2", shm_trial_name);
1143*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Group2", shm_group_name);
1144*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(overridden);
1145*6777b538SAndroid Build Coastguard Worker }
1146*6777b538SAndroid Build Coastguard Worker 
1147*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(USE_BLINK)
1148*6777b538SAndroid Build Coastguard Worker 
1149*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
1150*6777b538SAndroid Build Coastguard Worker constexpr GlobalDescriptors::Key kFDKey = 42;
1151*6777b538SAndroid Build Coastguard Worker #endif
1152*6777b538SAndroid Build Coastguard Worker 
1153*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(kTestFeatureA, "TestFeatureA", base::FEATURE_DISABLED_BY_DEFAULT);
1154*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(kTestFeatureB, "TestFeatureB", base::FEATURE_ENABLED_BY_DEFAULT);
1155*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(kTestFeatureC, "TestFeatureC", base::FEATURE_ENABLED_BY_DEFAULT);
1156*6777b538SAndroid Build Coastguard Worker 
MULTIPROCESS_TEST_MAIN(CreateTrialsInChildProcess)1157*6777b538SAndroid Build Coastguard Worker MULTIPROCESS_TEST_MAIN(CreateTrialsInChildProcess) {
1158*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
1159*6777b538SAndroid Build Coastguard Worker   // Since the fd value will be mapped from the global descriptors singleton,
1160*6777b538SAndroid Build Coastguard Worker   // set it there. We use the same value both for the key and the actual fd for
1161*6777b538SAndroid Build Coastguard Worker   // simplicity.
1162*6777b538SAndroid Build Coastguard Worker   // Note: On Android, the launch service already sets up the mapping.
1163*6777b538SAndroid Build Coastguard Worker   base::GlobalDescriptors::GetInstance()->Set(kFDKey, kFDKey);
1164*6777b538SAndroid Build Coastguard Worker #endif
1165*6777b538SAndroid Build Coastguard Worker 
1166*6777b538SAndroid Build Coastguard Worker   // Create and populate the field trial list singleton.
1167*6777b538SAndroid Build Coastguard Worker   FieldTrialList field_trial_list;
1168*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateTrialsInChildProcess(*CommandLine::ForCurrentProcess());
1169*6777b538SAndroid Build Coastguard Worker 
1170*6777b538SAndroid Build Coastguard Worker   // Create and populate the feature list singleton.
1171*6777b538SAndroid Build Coastguard Worker   auto feature_list = std::make_unique<FeatureList>();
1172*6777b538SAndroid Build Coastguard Worker   base::FieldTrialList::ApplyFeatureOverridesInChildProcess(feature_list.get());
1173*6777b538SAndroid Build Coastguard Worker   FeatureList::SetInstance(std::move(feature_list));
1174*6777b538SAndroid Build Coastguard Worker 
1175*6777b538SAndroid Build Coastguard Worker   // Validate the expected field trial and feaure state
1176*6777b538SAndroid Build Coastguard Worker   CHECK_EQ("Group1", FieldTrialList::FindFullName("Trial1"));
1177*6777b538SAndroid Build Coastguard Worker   CHECK(FeatureList::IsEnabled(kTestFeatureA));
1178*6777b538SAndroid Build Coastguard Worker   CHECK(!FeatureList::IsEnabled(kTestFeatureB));
1179*6777b538SAndroid Build Coastguard Worker   CHECK(!FeatureList::IsEnabled(kTestFeatureC));
1180*6777b538SAndroid Build Coastguard Worker   return 0;
1181*6777b538SAndroid Build Coastguard Worker }
1182*6777b538SAndroid Build Coastguard Worker 
1183*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_IOS)
TEST_F(FieldTrialListTest,PassFieldTrialSharedMemoryOnCommandLine)1184*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, PassFieldTrialSharedMemoryOnCommandLine) {
1185*6777b538SAndroid Build Coastguard Worker   // Setup some field trial state.
1186*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list1;
1187*6777b538SAndroid Build Coastguard Worker   scoped_feature_list1.InitWithEmptyFeatureAndFieldTrialLists();
1188*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<FeatureList> feature_list(new FeatureList);
1189*6777b538SAndroid Build Coastguard Worker   feature_list->InitFromCommandLine(kTestFeatureA.name, kTestFeatureB.name);
1190*6777b538SAndroid Build Coastguard Worker   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1191*6777b538SAndroid Build Coastguard Worker   feature_list->RegisterFieldTrialOverride(
1192*6777b538SAndroid Build Coastguard Worker       kTestFeatureC.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
1193*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list2;
1194*6777b538SAndroid Build Coastguard Worker   scoped_feature_list2.InitWithFeatureList(std::move(feature_list));
1195*6777b538SAndroid Build Coastguard Worker 
1196*6777b538SAndroid Build Coastguard Worker   // Prepare to launch a child process.
1197*6777b538SAndroid Build Coastguard Worker   CommandLine command_line = GetMultiProcessTestChildBaseCommandLine();
1198*6777b538SAndroid Build Coastguard Worker   LaunchOptions launch_options;
1199*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
1200*6777b538SAndroid Build Coastguard Worker   ScopedFD fd_to_share;
1201*6777b538SAndroid Build Coastguard Worker #endif
1202*6777b538SAndroid Build Coastguard Worker   FieldTrialList::PopulateLaunchOptionsWithFieldTrialState(
1203*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
1204*6777b538SAndroid Build Coastguard Worker       kFDKey, fd_to_share,
1205*6777b538SAndroid Build Coastguard Worker #endif
1206*6777b538SAndroid Build Coastguard Worker       &command_line, &launch_options);
1207*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
1208*6777b538SAndroid Build Coastguard Worker   launch_options.fds_to_remap.emplace_back(fd_to_share.get(), kFDKey);
1209*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
1210*6777b538SAndroid Build Coastguard Worker 
1211*6777b538SAndroid Build Coastguard Worker   // The shared memory handle should be specified.
1212*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(command_line.HasSwitch(switches::kFieldTrialHandle));
1213*6777b538SAndroid Build Coastguard Worker 
1214*6777b538SAndroid Build Coastguard Worker   // Explicitly specified enabled/disabled features should be specified.
1215*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTestFeatureA.name,
1216*6777b538SAndroid Build Coastguard Worker             command_line.GetSwitchValueASCII(switches::kEnableFeatures));
1217*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTestFeatureB.name,
1218*6777b538SAndroid Build Coastguard Worker             command_line.GetSwitchValueASCII(switches::kDisableFeatures));
1219*6777b538SAndroid Build Coastguard Worker 
1220*6777b538SAndroid Build Coastguard Worker   // Run the child.
1221*6777b538SAndroid Build Coastguard Worker   Process process = SpawnMultiProcessTestChild("CreateTrialsInChildProcess",
1222*6777b538SAndroid Build Coastguard Worker                                                command_line, launch_options);
1223*6777b538SAndroid Build Coastguard Worker   int exit_code = -1;
1224*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(WaitForMultiprocessTestChildExit(
1225*6777b538SAndroid Build Coastguard Worker       process, TestTimeouts::action_timeout(), &exit_code));
1226*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, exit_code);
1227*6777b538SAndroid Build Coastguard Worker }
1228*6777b538SAndroid Build Coastguard Worker #endif
1229*6777b538SAndroid Build Coastguard Worker 
1230*6777b538SAndroid Build Coastguard Worker // Verify that the field trial shared memory handle is really read-only, and
1231*6777b538SAndroid Build Coastguard Worker // does not allow writable mappings.
TEST_F(FieldTrialListTest,CheckReadOnlySharedMemoryRegion)1232*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, CheckReadOnlySharedMemoryRegion) {
1233*6777b538SAndroid Build Coastguard Worker   test::ScopedFeatureList scoped_feature_list;
1234*6777b538SAndroid Build Coastguard Worker   scoped_feature_list.InitWithEmptyFeatureAndFieldTrialLists();
1235*6777b538SAndroid Build Coastguard Worker 
1236*6777b538SAndroid Build Coastguard Worker   FieldTrialList::CreateFieldTrial("Trial1", "Group1");
1237*6777b538SAndroid Build Coastguard Worker 
1238*6777b538SAndroid Build Coastguard Worker   FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
1239*6777b538SAndroid Build Coastguard Worker 
1240*6777b538SAndroid Build Coastguard Worker   base::ReadOnlySharedMemoryRegion region =
1241*6777b538SAndroid Build Coastguard Worker       FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting();
1242*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(region.IsValid());
1243*6777b538SAndroid Build Coastguard Worker 
1244*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(CheckReadOnlyPlatformSharedMemoryRegionForTesting(
1245*6777b538SAndroid Build Coastguard Worker       base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
1246*6777b538SAndroid Build Coastguard Worker           std::move(region))));
1247*6777b538SAndroid Build Coastguard Worker }
1248*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(USE_BLINK)
1249*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialListTest,TestGetRandomizedFieldTrialCount)1250*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialListTest, TestGetRandomizedFieldTrialCount) {
1251*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, FieldTrialList::GetFieldTrialCount());
1252*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, FieldTrialList::GetRandomizedFieldTrialCount());
1253*6777b538SAndroid Build Coastguard Worker 
1254*6777b538SAndroid Build Coastguard Worker   const char name1[] = "name 1 test";
1255*6777b538SAndroid Build Coastguard Worker   const char name2[] = "name 2 test";
1256*6777b538SAndroid Build Coastguard Worker   const char name3[] = "name 3 test";
1257*6777b538SAndroid Build Coastguard Worker   const char group1[] = "group 1";
1258*6777b538SAndroid Build Coastguard Worker 
1259*6777b538SAndroid Build Coastguard Worker   // Create a field trial with a single group.
1260*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial1 =
1261*6777b538SAndroid Build Coastguard Worker       FieldTrialList::CreateFieldTrial(name1, group1);
1262*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(FieldTrial::kNotFinalized, trial1->group_);
1263*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(group1, trial1->group_name_internal());
1264*6777b538SAndroid Build Coastguard Worker 
1265*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, FieldTrialList::GetFieldTrialCount());
1266*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, FieldTrialList::GetRandomizedFieldTrialCount());
1267*6777b538SAndroid Build Coastguard Worker 
1268*6777b538SAndroid Build Coastguard Worker   // Create a randomized field trial.
1269*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 =
1270*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(name2, 10, "default name 2 test");
1271*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
1272*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(name2, trial2->trial_name());
1273*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", trial2->group_name_internal());
1274*6777b538SAndroid Build Coastguard Worker 
1275*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, FieldTrialList::GetFieldTrialCount());
1276*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, FieldTrialList::GetRandomizedFieldTrialCount());
1277*6777b538SAndroid Build Coastguard Worker 
1278*6777b538SAndroid Build Coastguard Worker   // Append a first group to trial 2. This doesn't affect GetFieldTrialCount()
1279*6777b538SAndroid Build Coastguard Worker   // and GetRandomizedFieldTrialCount().
1280*6777b538SAndroid Build Coastguard Worker   trial2->AppendGroup("a first group", 7);
1281*6777b538SAndroid Build Coastguard Worker 
1282*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, FieldTrialList::GetFieldTrialCount());
1283*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, FieldTrialList::GetRandomizedFieldTrialCount());
1284*6777b538SAndroid Build Coastguard Worker 
1285*6777b538SAndroid Build Coastguard Worker   // Create another randomized field trial.
1286*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial3 =
1287*6777b538SAndroid Build Coastguard Worker       CreateFieldTrial(name3, 10, "default name 3 test");
1288*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(FieldTrial::kNotFinalized, trial3->group_);
1289*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(name3, trial3->trial_name());
1290*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", trial3->group_name_internal());
1291*6777b538SAndroid Build Coastguard Worker 
1292*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3u, FieldTrialList::GetFieldTrialCount());
1293*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, FieldTrialList::GetRandomizedFieldTrialCount());
1294*6777b538SAndroid Build Coastguard Worker 
1295*6777b538SAndroid Build Coastguard Worker   // Note: FieldTrialList should delete the objects at shutdown.
1296*6777b538SAndroid Build Coastguard Worker }
1297*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,TestAllParamsToString)1298*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, TestAllParamsToString) {
1299*6777b538SAndroid Build Coastguard Worker   std::string exptected_output = "t1.g1:p1/v1/p2/v2";
1300*6777b538SAndroid Build Coastguard Worker 
1301*6777b538SAndroid Build Coastguard Worker   // Create study with one group and two params.
1302*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> params;
1303*6777b538SAndroid Build Coastguard Worker   params["p1"] = "v1";
1304*6777b538SAndroid Build Coastguard Worker   params["p2"] = "v2";
1305*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1306*6777b538SAndroid Build Coastguard Worker       "t1", "g1", params);
1307*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", FieldTrialList::AllParamsToString(&MockEscapeQueryParamValue));
1308*6777b538SAndroid Build Coastguard Worker 
1309*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial1 = CreateFieldTrial("t1", 100, "Default");
1310*6777b538SAndroid Build Coastguard Worker   trial1->AppendGroup("g1", 100);
1311*6777b538SAndroid Build Coastguard Worker   trial1->Activate();
1312*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(exptected_output,
1313*6777b538SAndroid Build Coastguard Worker             FieldTrialList::AllParamsToString(&MockEscapeQueryParamValue));
1314*6777b538SAndroid Build Coastguard Worker 
1315*6777b538SAndroid Build Coastguard Worker   // Create study with two groups and params that don't belog to the assigned
1316*6777b538SAndroid Build Coastguard Worker   // group. This should be in the output.
1317*6777b538SAndroid Build Coastguard Worker   FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
1318*6777b538SAndroid Build Coastguard Worker       "t2", "g2", params);
1319*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial2 = CreateFieldTrial("t2", 100, "Default");
1320*6777b538SAndroid Build Coastguard Worker   trial2->AppendGroup("g1", 100);
1321*6777b538SAndroid Build Coastguard Worker   trial2->AppendGroup("g2", 0);
1322*6777b538SAndroid Build Coastguard Worker   trial2->Activate();
1323*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(exptected_output,
1324*6777b538SAndroid Build Coastguard Worker             FieldTrialList::AllParamsToString(&MockEscapeQueryParamValue));
1325*6777b538SAndroid Build Coastguard Worker }
1326*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,GetActiveFieldTrialGroups_LowAnonymity)1327*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, GetActiveFieldTrialGroups_LowAnonymity) {
1328*6777b538SAndroid Build Coastguard Worker   // Create a field trial with a single winning group.
1329*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial_1 = CreateFieldTrial("Normal", 10, "Default");
1330*6777b538SAndroid Build Coastguard Worker   trial_1->AppendGroup("Winner 1", 10);
1331*6777b538SAndroid Build Coastguard Worker   trial_1->Activate();
1332*6777b538SAndroid Build Coastguard Worker 
1333*6777b538SAndroid Build Coastguard Worker   // Create a second field trial with a single winning group, marked as
1334*6777b538SAndroid Build Coastguard Worker   // low-anonymity.
1335*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial_2 = CreateFieldTrial(
1336*6777b538SAndroid Build Coastguard Worker       "Low anonymity", 10, "Default", /*is_low_anonymity=*/true);
1337*6777b538SAndroid Build Coastguard Worker   trial_2->AppendGroup("Winner 2", 10);
1338*6777b538SAndroid Build Coastguard Worker   trial_2->Activate();
1339*6777b538SAndroid Build Coastguard Worker 
1340*6777b538SAndroid Build Coastguard Worker   // Check that |FieldTrialList::GetActiveFieldTrialGroups()| does not include
1341*6777b538SAndroid Build Coastguard Worker   // the low-anonymity trial.
1342*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups_for_metrics;
1343*6777b538SAndroid Build Coastguard Worker   FieldTrialList::GetActiveFieldTrialGroups(&active_groups_for_metrics);
1344*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(
1345*6777b538SAndroid Build Coastguard Worker       active_groups_for_metrics,
1346*6777b538SAndroid Build Coastguard Worker       testing::UnorderedPointwise(CompareActiveGroupToFieldTrial(), {trial_1}));
1347*6777b538SAndroid Build Coastguard Worker 
1348*6777b538SAndroid Build Coastguard Worker   // Check that
1349*6777b538SAndroid Build Coastguard Worker   // |FieldTrialListIncludingLowAnonymity::GetActiveFieldTrialGroups()| includes
1350*6777b538SAndroid Build Coastguard Worker   // both trials.
1351*6777b538SAndroid Build Coastguard Worker   FieldTrial::ActiveGroups active_groups;
1352*6777b538SAndroid Build Coastguard Worker   FieldTrialListIncludingLowAnonymity::GetActiveFieldTrialGroupsForTesting(
1353*6777b538SAndroid Build Coastguard Worker       &active_groups);
1354*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(active_groups,
1355*6777b538SAndroid Build Coastguard Worker               testing::UnorderedPointwise(CompareActiveGroupToFieldTrial(),
1356*6777b538SAndroid Build Coastguard Worker                                           {trial_1, trial_2}));
1357*6777b538SAndroid Build Coastguard Worker }
1358*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ObserveIncludingLowAnonymity)1359*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ObserveIncludingLowAnonymity) {
1360*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserver observer;
1361*6777b538SAndroid Build Coastguard Worker   TestFieldTrialObserverIncludingLowAnonymity low_anonymity_observer;
1362*6777b538SAndroid Build Coastguard Worker 
1363*6777b538SAndroid Build Coastguard Worker   // Create a low-anonymity trial with one active group.
1364*6777b538SAndroid Build Coastguard Worker   const char kTrialName[] = "TrialToObserve1";
1365*6777b538SAndroid Build Coastguard Worker   scoped_refptr<FieldTrial> trial = CreateFieldTrial(
1366*6777b538SAndroid Build Coastguard Worker       kTrialName, 100, kDefaultGroupName, /*is_low_anonymity=*/true);
1367*6777b538SAndroid Build Coastguard Worker   trial->Activate();
1368*6777b538SAndroid Build Coastguard Worker 
1369*6777b538SAndroid Build Coastguard Worker   // Only the low_anonymity_observer should be notified.
1370*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", observer.trial_name());
1371*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", observer.group_name());
1372*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kTrialName, low_anonymity_observer.trial_name());
1373*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(kDefaultGroupName, low_anonymity_observer.group_name());
1374*6777b538SAndroid Build Coastguard Worker }
1375*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ParseFieldTrialsString)1376*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ParseFieldTrialsString) {
1377*6777b538SAndroid Build Coastguard Worker   std::vector<FieldTrial::State> entries;
1378*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrial::ParseFieldTrialsString(
1379*6777b538SAndroid Build Coastguard Worker       "Trial1/Group1", /*override_trials=*/false, entries));
1380*6777b538SAndroid Build Coastguard Worker 
1381*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 1ul);
1382*6777b538SAndroid Build Coastguard Worker   const FieldTrial::State& entry = entries[0];
1383*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial1", entry.trial_name);
1384*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Group1", entry.group_name);
1385*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(false, entry.activated);
1386*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(false, entry.is_overridden);
1387*6777b538SAndroid Build Coastguard Worker }
1388*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ParseFieldTrialsStringTwoStudies)1389*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ParseFieldTrialsStringTwoStudies) {
1390*6777b538SAndroid Build Coastguard Worker   std::vector<FieldTrial::State> entries;
1391*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrial::ParseFieldTrialsString(
1392*6777b538SAndroid Build Coastguard Worker       "Trial1/Group1/*Trial2/Group2/", /*override_trials=*/false, entries));
1393*6777b538SAndroid Build Coastguard Worker 
1394*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2ul);
1395*6777b538SAndroid Build Coastguard Worker   const FieldTrial::State& entry1 = entries[0];
1396*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial1", entry1.trial_name);
1397*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Group1", entry1.group_name);
1398*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(false, entry1.activated);
1399*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(false, entry1.is_overridden);
1400*6777b538SAndroid Build Coastguard Worker 
1401*6777b538SAndroid Build Coastguard Worker   const FieldTrial::State& entry2 = entries[1];
1402*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial2", entry2.trial_name);
1403*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Group2", entry2.group_name);
1404*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(true, entry2.activated);
1405*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(false, entry2.is_overridden);
1406*6777b538SAndroid Build Coastguard Worker }
1407*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ParseFieldTrialsStringEmpty)1408*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ParseFieldTrialsStringEmpty) {
1409*6777b538SAndroid Build Coastguard Worker   std::vector<FieldTrial::State> entries;
1410*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(FieldTrial::ParseFieldTrialsString("", /*override_trials=*/false,
1411*6777b538SAndroid Build Coastguard Worker                                                  entries));
1412*6777b538SAndroid Build Coastguard Worker 
1413*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 0ul);
1414*6777b538SAndroid Build Coastguard Worker }
1415*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,ParseFieldTrialsStringInvalid)1416*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, ParseFieldTrialsStringInvalid) {
1417*6777b538SAndroid Build Coastguard Worker   std::vector<FieldTrial::State> entries;
1418*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrial::ParseFieldTrialsString(
1419*6777b538SAndroid Build Coastguard Worker       "A/", /*override_trials=*/false, entries));
1420*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrial::ParseFieldTrialsString(
1421*6777b538SAndroid Build Coastguard Worker       "/A", /*override_trials=*/false, entries));
1422*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrial::ParseFieldTrialsString(
1423*6777b538SAndroid Build Coastguard Worker       "//", /*override_trials=*/false, entries));
1424*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(FieldTrial::ParseFieldTrialsString(
1425*6777b538SAndroid Build Coastguard Worker       "///", /*override_trials=*/false, entries));
1426*6777b538SAndroid Build Coastguard Worker }
1427*6777b538SAndroid Build Coastguard Worker 
TEST_F(FieldTrialTest,BuildFieldTrialStateString)1428*6777b538SAndroid Build Coastguard Worker TEST_F(FieldTrialTest, BuildFieldTrialStateString) {
1429*6777b538SAndroid Build Coastguard Worker   FieldTrial::State state1;
1430*6777b538SAndroid Build Coastguard Worker   state1.trial_name = "Trial";
1431*6777b538SAndroid Build Coastguard Worker   state1.group_name = "Group";
1432*6777b538SAndroid Build Coastguard Worker   state1.activated = false;
1433*6777b538SAndroid Build Coastguard Worker 
1434*6777b538SAndroid Build Coastguard Worker   FieldTrial::State state2;
1435*6777b538SAndroid Build Coastguard Worker   state2.trial_name = "Foo";
1436*6777b538SAndroid Build Coastguard Worker   state2.group_name = "Bar";
1437*6777b538SAndroid Build Coastguard Worker   state2.activated = true;
1438*6777b538SAndroid Build Coastguard Worker 
1439*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial/Group", FieldTrial::BuildFieldTrialStateString({state1}));
1440*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Trial/Group/*Foo/Bar",
1441*6777b538SAndroid Build Coastguard Worker             FieldTrial::BuildFieldTrialStateString({state1, state2}));
1442*6777b538SAndroid Build Coastguard Worker }
1443*6777b538SAndroid Build Coastguard Worker 
1444*6777b538SAndroid Build Coastguard Worker }  // namespace base
1445