1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Test of FieldTrial class
7 #include "base/field_trial.h"
9 #include "base/string_util.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 class FieldTrialTest
: public testing::Test
{
14 FieldTrialTest() : trial_list_() { }
17 FieldTrialList trial_list_
;
20 // Test registration, and also check that destructors are called for trials
21 // (and that Purify doesn't catch us leaking).
22 TEST_F(FieldTrialTest
, Registration
) {
23 const char* name1
= "name 1 test";
24 const char* name2
= "name 2 test";
25 EXPECT_FALSE(FieldTrialList::Find(name1
));
26 EXPECT_FALSE(FieldTrialList::Find(name2
));
28 FieldTrial
* trial1
= new FieldTrial(name1
, 10);
29 EXPECT_EQ(trial1
->group(), FieldTrial::kNotParticipating
);
30 EXPECT_EQ(trial1
->name(), name1
);
31 EXPECT_EQ(trial1
->group_name(), "");
33 trial1
->AppendGroup("", 7);
35 EXPECT_EQ(trial1
, FieldTrialList::Find(name1
));
36 EXPECT_FALSE(FieldTrialList::Find(name2
));
38 FieldTrial
* trial2
= new FieldTrial(name2
, 10);
39 EXPECT_EQ(trial2
->group(), FieldTrial::kNotParticipating
);
40 EXPECT_EQ(trial2
->name(), name2
);
41 EXPECT_EQ(trial2
->group_name(), "");
43 trial2
->AppendGroup("a first group", 7);
45 EXPECT_EQ(trial1
, FieldTrialList::Find(name1
));
46 EXPECT_EQ(trial2
, FieldTrialList::Find(name2
));
47 // Note: FieldTrialList should delete the objects at shutdown.
50 TEST_F(FieldTrialTest
, AbsoluteProbabilities
) {
51 char always_true
[] = " always true";
52 char always_false
[] = " always false";
53 for (int i
= 1; i
< 250; ++i
) {
54 // Try lots of names, by changing the first character of the name.
58 FieldTrial
* trial_true
= new FieldTrial(always_true
, 10);
59 const std::string winner
= "_TheWinner";
60 int winner_group
= trial_true
->AppendGroup(winner
, 10);
62 EXPECT_EQ(trial_true
->group(), winner_group
);
63 EXPECT_EQ(trial_true
->group_name(), winner
);
65 FieldTrial
* trial_false
= new FieldTrial(always_false
, 10);
66 int loser_group
= trial_false
->AppendGroup("ALoser", 0);
68 EXPECT_NE(trial_false
->group(), loser_group
);
72 TEST_F(FieldTrialTest
, RemainingProbability
) {
73 // First create a test that hasn't had a winner yet.
74 const std::string winner
= "Winner";
75 const std::string loser
= "Loser";
76 scoped_refptr
<FieldTrial
> trial
;
79 std::string name
= StringPrintf("trial%d", ++counter
);
80 trial
= new FieldTrial(name
, 10);
81 trial
->AppendGroup(loser
, 5); // 50% chance of not being chosen.
82 } while (trial
->group() != FieldTrial::kNotParticipating
);
84 // Now add a winner with all remaining probability.
85 trial
->AppendGroup(winner
, FieldTrial::kAllRemainingProbability
);
87 // And that winner should ALWAYS win.
88 EXPECT_EQ(winner
, trial
->group_name());
91 TEST_F(FieldTrialTest
, MiddleProbabilities
) {
92 char name
[] = " same name";
93 bool false_event_seen
= false;
94 bool true_event_seen
= false;
95 for (int i
= 1; i
< 250; ++i
) {
97 FieldTrial
* trial
= new FieldTrial(name
, 10);
98 int might_win
= trial
->AppendGroup("MightWin", 5);
100 if (trial
->group() == might_win
) {
101 true_event_seen
= true;
103 false_event_seen
= true;
105 if (false_event_seen
&& true_event_seen
)
106 return; // Successful test!!!
108 // Very surprising to get here. Probability should be around 1 in 2 ** 250.
109 // One of the following will fail.
110 EXPECT_TRUE(false_event_seen
);
111 EXPECT_TRUE(true_event_seen
);
114 TEST_F(FieldTrialTest
, OneWinner
) {
115 char name
[] = "Some name";
118 FieldTrial
* trial
= new FieldTrial(name
, group_count
);
119 int winner_index(-2);
120 std::string winner_name
;
122 for (int i
= 1; i
<= group_count
; ++i
) {
123 int might_win
= trial
->AppendGroup("", 1);
125 if (trial
->group() == might_win
) {
126 EXPECT_EQ(winner_index
, -2);
127 winner_index
= might_win
;
128 StringAppendF(&winner_name
, "_%d", might_win
);
129 EXPECT_EQ(winner_name
, trial
->group_name());
132 EXPECT_GE(winner_index
, 0);
133 EXPECT_EQ(trial
->group(), winner_index
);
134 EXPECT_EQ(winner_name
, trial
->group_name());
137 TEST_F(FieldTrialTest
, Save
) {
138 std::string save_string
;
140 FieldTrial
* trial
= new FieldTrial("Some name", 10);
141 // There is no winner yet, so no textual group name is associated with trial.
142 EXPECT_EQ(trial
->group_name(), "");
143 FieldTrialList::StatesToString(&save_string
);
144 EXPECT_EQ(save_string
, "");
147 // Create a winning group.
148 trial
->AppendGroup("Winner", 10);
149 FieldTrialList::StatesToString(&save_string
);
150 EXPECT_EQ(save_string
, "Some name/Winner/");
153 // Create a second trial and winning group.
154 FieldTrial
* trial2
= new FieldTrial("xxx", 10);
155 trial2
->AppendGroup("yyyy", 10);
157 FieldTrialList::StatesToString(&save_string
);
158 // We assume names are alphabetized... though this is not critical.
159 EXPECT_EQ(save_string
, "Some name/Winner/xxx/yyyy/");
162 TEST_F(FieldTrialTest
, Restore
) {
163 EXPECT_TRUE(FieldTrialList::Find("Some_name") == NULL
);
164 EXPECT_TRUE(FieldTrialList::Find("xxx") == NULL
);
166 FieldTrialList::StringAugmentsState("Some_name/Winner/xxx/yyyy/");
168 FieldTrial
* trial
= FieldTrialList::Find("Some_name");
169 ASSERT_NE(static_cast<FieldTrial
*>(NULL
), trial
);
170 EXPECT_EQ(trial
->group_name(), "Winner");
171 EXPECT_EQ(trial
->name(), "Some_name");
173 trial
= FieldTrialList::Find("xxx");
174 ASSERT_NE(static_cast<FieldTrial
*>(NULL
), trial
);
175 EXPECT_EQ(trial
->group_name(), "yyyy");
176 EXPECT_EQ(trial
->name(), "xxx");
179 TEST_F(FieldTrialTest
, BogusRestore
) {
180 EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingSlash"));
181 EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingGroupName/"));
182 EXPECT_FALSE(FieldTrialList::StringAugmentsState("MissingFinalSlash/gname"));
183 EXPECT_FALSE(FieldTrialList::StringAugmentsState("/noname, only group/"));
186 TEST_F(FieldTrialTest
, DuplicateRestore
) {
187 FieldTrial
* trial
= new FieldTrial("Some name", 10);
188 trial
->AppendGroup("Winner", 10);
189 std::string save_string
;
190 FieldTrialList::StatesToString(&save_string
);
191 EXPECT_EQ("Some name/Winner/", save_string
);
193 // It is OK if we redundantly specify a winner.
194 EXPECT_TRUE(FieldTrialList::StringAugmentsState(save_string
));
196 // But it is an error to try to change to a different winner.
197 EXPECT_FALSE(FieldTrialList::StringAugmentsState("Some name/Loser/"));