1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/metrics/field_trial.h"
6
7 #include <stddef.h>
8
9 #include "base/build_time.h"
10 #include "base/macros.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/rand_util.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 namespace {
21
22 // Default group name used by several tests.
23 const char kDefaultGroupName[] = "DefaultGroup";
24
25 // Call FieldTrialList::FactoryGetFieldTrial() with a future expiry date.
CreateFieldTrial(const std::string & trial_name,int total_probability,const std::string & default_group_name,int * default_group_number)26 scoped_refptr<base::FieldTrial> CreateFieldTrial(
27 const std::string& trial_name,
28 int total_probability,
29 const std::string& default_group_name,
30 int* default_group_number) {
31 return FieldTrialList::FactoryGetFieldTrial(
32 trial_name, total_probability, default_group_name,
33 base::FieldTrialList::kNoExpirationYear, 1, 1,
34 base::FieldTrial::SESSION_RANDOMIZED, default_group_number);
35 }
36
OneYearBeforeBuildTime()37 int OneYearBeforeBuildTime() {
38 Time one_year_before_build_time = GetBuildTime() - TimeDelta::FromDays(365);
39 Time::Exploded exploded;
40 one_year_before_build_time.LocalExplode(&exploded);
41 return exploded.year;
42 }
43
44 // FieldTrialList::Observer implementation for testing.
45 class TestFieldTrialObserver : public FieldTrialList::Observer {
46 public:
TestFieldTrialObserver()47 TestFieldTrialObserver() {
48 FieldTrialList::AddObserver(this);
49 }
50
~TestFieldTrialObserver()51 ~TestFieldTrialObserver() override { FieldTrialList::RemoveObserver(this); }
52
OnFieldTrialGroupFinalized(const std::string & trial,const std::string & group)53 void OnFieldTrialGroupFinalized(const std::string& trial,
54 const std::string& group) override {
55 trial_name_ = trial;
56 group_name_ = group;
57 }
58
trial_name() const59 const std::string& trial_name() const { return trial_name_; }
group_name() const60 const std::string& group_name() const { return group_name_; }
61
62 private:
63 std::string trial_name_;
64 std::string group_name_;
65
66 DISALLOW_COPY_AND_ASSIGN(TestFieldTrialObserver);
67 };
68
69 } // namespace
70
71 class FieldTrialTest : public testing::Test {
72 public:
FieldTrialTest()73 FieldTrialTest() : trial_list_(NULL) {}
74
75 private:
76 MessageLoop message_loop_;
77 FieldTrialList trial_list_;
78
79 DISALLOW_COPY_AND_ASSIGN(FieldTrialTest);
80 };
81
82 // Test registration, and also check that destructors are called for trials
83 // (and that Valgrind doesn't catch us leaking).
TEST_F(FieldTrialTest,Registration)84 TEST_F(FieldTrialTest, Registration) {
85 const char name1[] = "name 1 test";
86 const char name2[] = "name 2 test";
87 EXPECT_FALSE(FieldTrialList::Find(name1));
88 EXPECT_FALSE(FieldTrialList::Find(name2));
89
90 scoped_refptr<FieldTrial> trial1 =
91 CreateFieldTrial(name1, 10, "default name 1 test", NULL);
92 EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
93 EXPECT_EQ(name1, trial1->trial_name());
94 EXPECT_EQ("", trial1->group_name_internal());
95
96 trial1->AppendGroup(std::string(), 7);
97
98 EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
99 EXPECT_FALSE(FieldTrialList::Find(name2));
100
101 scoped_refptr<FieldTrial> trial2 =
102 CreateFieldTrial(name2, 10, "default name 2 test", NULL);
103 EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
104 EXPECT_EQ(name2, trial2->trial_name());
105 EXPECT_EQ("", trial2->group_name_internal());
106
107 trial2->AppendGroup("a first group", 7);
108
109 EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
110 EXPECT_EQ(trial2.get(), FieldTrialList::Find(name2));
111 // Note: FieldTrialList should delete the objects at shutdown.
112 }
113
TEST_F(FieldTrialTest,AbsoluteProbabilities)114 TEST_F(FieldTrialTest, AbsoluteProbabilities) {
115 char always_true[] = " always true";
116 char default_always_true[] = " default always true";
117 char always_false[] = " always false";
118 char default_always_false[] = " default always false";
119 for (int i = 1; i < 250; ++i) {
120 // Try lots of names, by changing the first character of the name.
121 char c = static_cast<char>(i);
122 always_true[0] = c;
123 default_always_true[0] = c;
124 always_false[0] = c;
125 default_always_false[0] = c;
126
127 scoped_refptr<FieldTrial> trial_true =
128 CreateFieldTrial(always_true, 10, default_always_true, NULL);
129 const std::string winner = "TheWinner";
130 int winner_group = trial_true->AppendGroup(winner, 10);
131
132 EXPECT_EQ(winner_group, trial_true->group());
133 EXPECT_EQ(winner, trial_true->group_name());
134
135 scoped_refptr<FieldTrial> trial_false =
136 CreateFieldTrial(always_false, 10, default_always_false, NULL);
137 int loser_group = trial_false->AppendGroup("ALoser", 0);
138
139 EXPECT_NE(loser_group, trial_false->group());
140 }
141 }
142
TEST_F(FieldTrialTest,RemainingProbability)143 TEST_F(FieldTrialTest, RemainingProbability) {
144 // First create a test that hasn't had a winner yet.
145 const std::string winner = "Winner";
146 const std::string loser = "Loser";
147 scoped_refptr<FieldTrial> trial;
148 int counter = 0;
149 int default_group_number = -1;
150 do {
151 std::string name = StringPrintf("trial%d", ++counter);
152 trial = CreateFieldTrial(name, 10, winner, &default_group_number);
153 trial->AppendGroup(loser, 5); // 50% chance of not being chosen.
154 // If a group is not assigned, group_ will be kNotFinalized.
155 } while (trial->group_ != FieldTrial::kNotFinalized);
156
157 // And that 'default' group (winner) should always win.
158 EXPECT_EQ(default_group_number, trial->group());
159
160 // And that winner should ALWAYS win.
161 EXPECT_EQ(winner, trial->group_name());
162 }
163
TEST_F(FieldTrialTest,FiftyFiftyProbability)164 TEST_F(FieldTrialTest, FiftyFiftyProbability) {
165 // Check that even with small divisors, we have the proper probabilities, and
166 // all outcomes are possible. Since this is a 50-50 test, it should get both
167 // outcomes in a few tries, but we'll try no more than 100 times (and be flaky
168 // with probability around 1 in 2^99).
169 bool first_winner = false;
170 bool second_winner = false;
171 int counter = 0;
172 do {
173 std::string name = base::StringPrintf("FiftyFifty%d", ++counter);
174 std::string default_group_name = base::StringPrintf("Default FiftyFifty%d",
175 ++counter);
176 scoped_refptr<FieldTrial> trial =
177 CreateFieldTrial(name, 2, default_group_name, NULL);
178 trial->AppendGroup("first", 1); // 50% chance of being chosen.
179 // If group_ is kNotFinalized, then a group assignement hasn't been done.
180 if (trial->group_ != FieldTrial::kNotFinalized) {
181 first_winner = true;
182 continue;
183 }
184 trial->AppendGroup("second", 1); // Always chosen at this point.
185 EXPECT_NE(FieldTrial::kNotFinalized, trial->group());
186 second_winner = true;
187 } while ((!second_winner || !first_winner) && counter < 100);
188 EXPECT_TRUE(second_winner);
189 EXPECT_TRUE(first_winner);
190 }
191
TEST_F(FieldTrialTest,MiddleProbabilities)192 TEST_F(FieldTrialTest, MiddleProbabilities) {
193 char name[] = " same name";
194 char default_group_name[] = " default same name";
195 bool false_event_seen = false;
196 bool true_event_seen = false;
197 for (int i = 1; i < 250; ++i) {
198 char c = static_cast<char>(i);
199 name[0] = c;
200 default_group_name[0] = c;
201 scoped_refptr<FieldTrial> trial =
202 CreateFieldTrial(name, 10, default_group_name, NULL);
203 int might_win = trial->AppendGroup("MightWin", 5);
204
205 if (trial->group() == might_win) {
206 true_event_seen = true;
207 } else {
208 false_event_seen = true;
209 }
210 if (false_event_seen && true_event_seen)
211 return; // Successful test!!!
212 }
213 // Very surprising to get here. Probability should be around 1 in 2 ** 250.
214 // One of the following will fail.
215 EXPECT_TRUE(false_event_seen);
216 EXPECT_TRUE(true_event_seen);
217 }
218
TEST_F(FieldTrialTest,OneWinner)219 TEST_F(FieldTrialTest, OneWinner) {
220 char name[] = "Some name";
221 char default_group_name[] = "Default some name";
222 int group_count(10);
223
224 int default_group_number = -1;
225 scoped_refptr<FieldTrial> trial =
226 CreateFieldTrial(name, group_count, default_group_name, NULL);
227 int winner_index(-2);
228 std::string winner_name;
229
230 for (int i = 1; i <= group_count; ++i) {
231 int might_win = trial->AppendGroup(std::string(), 1);
232
233 // Because we keep appending groups, we want to see if the last group that
234 // was added has been assigned or not.
235 if (trial->group_ == might_win) {
236 EXPECT_EQ(-2, winner_index);
237 winner_index = might_win;
238 StringAppendF(&winner_name, "%d", might_win);
239 EXPECT_EQ(winner_name, trial->group_name());
240 }
241 }
242 EXPECT_GE(winner_index, 0);
243 // Since all groups cover the total probability, we should not have
244 // chosen the default group.
245 EXPECT_NE(trial->group(), default_group_number);
246 EXPECT_EQ(trial->group(), winner_index);
247 EXPECT_EQ(trial->group_name(), winner_name);
248 }
249
TEST_F(FieldTrialTest,DisableProbability)250 TEST_F(FieldTrialTest, DisableProbability) {
251 const std::string default_group_name = "Default group";
252 const std::string loser = "Loser";
253 const std::string name = "Trial";
254
255 // Create a field trail that has expired.
256 int default_group_number = -1;
257 FieldTrial* trial = FieldTrialList::FactoryGetFieldTrial(
258 name, 1000000000, default_group_name, OneYearBeforeBuildTime(), 1, 1,
259 FieldTrial::SESSION_RANDOMIZED,
260 &default_group_number);
261 trial->AppendGroup(loser, 999999999); // 99.9999999% chance of being chosen.
262
263 // Because trial has expired, we should always be in the default group.
264 EXPECT_EQ(default_group_number, trial->group());
265
266 // And that default_group_name should ALWAYS win.
267 EXPECT_EQ(default_group_name, trial->group_name());
268 }
269
TEST_F(FieldTrialTest,ActiveGroups)270 TEST_F(FieldTrialTest, ActiveGroups) {
271 std::string no_group("No Group");
272 scoped_refptr<FieldTrial> trial =
273 CreateFieldTrial(no_group, 10, "Default", NULL);
274
275 // There is no winner yet, so no NameGroupId should be returned.
276 FieldTrial::ActiveGroup active_group;
277 EXPECT_FALSE(trial->GetActiveGroup(&active_group));
278
279 // Create a single winning group.
280 std::string one_winner("One Winner");
281 trial = CreateFieldTrial(one_winner, 10, "Default", NULL);
282 std::string winner("Winner");
283 trial->AppendGroup(winner, 10);
284 EXPECT_FALSE(trial->GetActiveGroup(&active_group));
285 // Finalize the group selection by accessing the selected group.
286 trial->group();
287 EXPECT_TRUE(trial->GetActiveGroup(&active_group));
288 EXPECT_EQ(one_winner, active_group.trial_name);
289 EXPECT_EQ(winner, active_group.group_name);
290
291 std::string multi_group("MultiGroup");
292 scoped_refptr<FieldTrial> multi_group_trial =
293 CreateFieldTrial(multi_group, 9, "Default", NULL);
294
295 multi_group_trial->AppendGroup("Me", 3);
296 multi_group_trial->AppendGroup("You", 3);
297 multi_group_trial->AppendGroup("Them", 3);
298 EXPECT_FALSE(multi_group_trial->GetActiveGroup(&active_group));
299 // Finalize the group selection by accessing the selected group.
300 multi_group_trial->group();
301 EXPECT_TRUE(multi_group_trial->GetActiveGroup(&active_group));
302 EXPECT_EQ(multi_group, active_group.trial_name);
303 EXPECT_EQ(multi_group_trial->group_name(), active_group.group_name);
304
305 // Now check if the list is built properly...
306 FieldTrial::ActiveGroups active_groups;
307 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
308 EXPECT_EQ(2U, active_groups.size());
309 for (size_t i = 0; i < active_groups.size(); ++i) {
310 // Order is not guaranteed, so check all values.
311 EXPECT_NE(no_group, active_groups[i].trial_name);
312 EXPECT_TRUE(one_winner != active_groups[i].trial_name ||
313 winner == active_groups[i].group_name);
314 EXPECT_TRUE(multi_group != active_groups[i].trial_name ||
315 multi_group_trial->group_name() == active_groups[i].group_name);
316 }
317 }
318
TEST_F(FieldTrialTest,GetActiveFieldTrialGroupsFromString)319 TEST_F(FieldTrialTest, GetActiveFieldTrialGroupsFromString) {
320 FieldTrial::ActiveGroups active_groups;
321 FieldTrialList::GetActiveFieldTrialGroupsFromString("*A/X/B/Y/*C/Z",
322 &active_groups);
323 ASSERT_EQ(2U, active_groups.size());
324 EXPECT_EQ("A", active_groups[0].trial_name);
325 EXPECT_EQ("X", active_groups[0].group_name);
326 EXPECT_EQ("C", active_groups[1].trial_name);
327 EXPECT_EQ("Z", active_groups[1].group_name);
328 }
329
TEST_F(FieldTrialTest,AllGroups)330 TEST_F(FieldTrialTest, AllGroups) {
331 FieldTrial::State field_trial_state;
332 std::string one_winner("One Winner");
333 scoped_refptr<FieldTrial> trial =
334 CreateFieldTrial(one_winner, 10, "Default", NULL);
335 std::string winner("Winner");
336 trial->AppendGroup(winner, 10);
337 EXPECT_TRUE(trial->GetState(&field_trial_state));
338 EXPECT_EQ(one_winner, field_trial_state.trial_name);
339 EXPECT_EQ(winner, field_trial_state.group_name);
340 trial->group();
341 EXPECT_TRUE(trial->GetState(&field_trial_state));
342 EXPECT_EQ(one_winner, field_trial_state.trial_name);
343 EXPECT_EQ(winner, field_trial_state.group_name);
344
345 std::string multi_group("MultiGroup");
346 scoped_refptr<FieldTrial> multi_group_trial =
347 CreateFieldTrial(multi_group, 9, "Default", NULL);
348
349 multi_group_trial->AppendGroup("Me", 3);
350 multi_group_trial->AppendGroup("You", 3);
351 multi_group_trial->AppendGroup("Them", 3);
352 EXPECT_TRUE(multi_group_trial->GetState(&field_trial_state));
353 // Finalize the group selection by accessing the selected group.
354 multi_group_trial->group();
355 EXPECT_TRUE(multi_group_trial->GetState(&field_trial_state));
356 EXPECT_EQ(multi_group, field_trial_state.trial_name);
357 EXPECT_EQ(multi_group_trial->group_name(), field_trial_state.group_name);
358 }
359
TEST_F(FieldTrialTest,ActiveGroupsNotFinalized)360 TEST_F(FieldTrialTest, ActiveGroupsNotFinalized) {
361 const char kTrialName[] = "TestTrial";
362 const char kSecondaryGroupName[] = "SecondaryGroup";
363
364 int default_group = -1;
365 scoped_refptr<FieldTrial> trial =
366 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
367 const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
368
369 // Before |group()| is called, |GetActiveGroup()| should return false.
370 FieldTrial::ActiveGroup active_group;
371 EXPECT_FALSE(trial->GetActiveGroup(&active_group));
372
373 // |GetActiveFieldTrialGroups()| should also not include the trial.
374 FieldTrial::ActiveGroups active_groups;
375 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
376 EXPECT_TRUE(active_groups.empty());
377
378 // After |group()| has been called, both APIs should succeed.
379 const int chosen_group = trial->group();
380 EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
381
382 EXPECT_TRUE(trial->GetActiveGroup(&active_group));
383 EXPECT_EQ(kTrialName, active_group.trial_name);
384 if (chosen_group == default_group)
385 EXPECT_EQ(kDefaultGroupName, active_group.group_name);
386 else
387 EXPECT_EQ(kSecondaryGroupName, active_group.group_name);
388
389 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
390 ASSERT_EQ(1U, active_groups.size());
391 EXPECT_EQ(kTrialName, active_groups[0].trial_name);
392 EXPECT_EQ(active_group.group_name, active_groups[0].group_name);
393 }
394
TEST_F(FieldTrialTest,GetGroupNameWithoutActivation)395 TEST_F(FieldTrialTest, GetGroupNameWithoutActivation) {
396 const char kTrialName[] = "TestTrial";
397 const char kSecondaryGroupName[] = "SecondaryGroup";
398
399 int default_group = -1;
400 scoped_refptr<FieldTrial> trial =
401 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
402 trial->AppendGroup(kSecondaryGroupName, 50);
403
404 // The trial should start inactive.
405 EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
406
407 // Calling |GetGroupNameWithoutActivation()| should not activate the trial.
408 std::string group_name = trial->GetGroupNameWithoutActivation();
409 EXPECT_FALSE(group_name.empty());
410 EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
411
412 // Calling |group_name()| should activate it and return the same group name.
413 EXPECT_EQ(group_name, trial->group_name());
414 EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
415 }
416
TEST_F(FieldTrialTest,Save)417 TEST_F(FieldTrialTest, Save) {
418 std::string save_string;
419
420 scoped_refptr<FieldTrial> trial =
421 CreateFieldTrial("Some name", 10, "Default some name", NULL);
422 // There is no winner yet, so no textual group name is associated with trial.
423 // In this case, the trial should not be included.
424 EXPECT_EQ("", trial->group_name_internal());
425 FieldTrialList::StatesToString(&save_string);
426 EXPECT_EQ("", save_string);
427 save_string.clear();
428
429 // Create a winning group.
430 trial->AppendGroup("Winner", 10);
431 // Finalize the group selection by accessing the selected group.
432 trial->group();
433 FieldTrialList::StatesToString(&save_string);
434 EXPECT_EQ("Some name/Winner/", save_string);
435 save_string.clear();
436
437 // Create a second trial and winning group.
438 scoped_refptr<FieldTrial> trial2 =
439 CreateFieldTrial("xxx", 10, "Default xxx", NULL);
440 trial2->AppendGroup("yyyy", 10);
441 // Finalize the group selection by accessing the selected group.
442 trial2->group();
443
444 FieldTrialList::StatesToString(&save_string);
445 // We assume names are alphabetized... though this is not critical.
446 EXPECT_EQ("Some name/Winner/xxx/yyyy/", save_string);
447 save_string.clear();
448
449 // Create a third trial with only the default group.
450 scoped_refptr<FieldTrial> trial3 =
451 CreateFieldTrial("zzz", 10, "default", NULL);
452 // Finalize the group selection by accessing the selected group.
453 trial3->group();
454
455 FieldTrialList::StatesToString(&save_string);
456 EXPECT_EQ("Some name/Winner/xxx/yyyy/zzz/default/", save_string);
457 }
458
TEST_F(FieldTrialTest,SaveAll)459 TEST_F(FieldTrialTest, SaveAll) {
460 std::string save_string;
461
462 scoped_refptr<FieldTrial> trial =
463 CreateFieldTrial("Some name", 10, "Default some name", nullptr);
464 EXPECT_EQ("", trial->group_name_internal());
465 FieldTrialList::AllStatesToString(&save_string);
466 EXPECT_EQ("Some name/Default some name/", save_string);
467 // Getting all states should have finalized the trial.
468 EXPECT_EQ("Default some name", trial->group_name_internal());
469 save_string.clear();
470
471 // Create a winning group.
472 trial = CreateFieldTrial("trial2", 10, "Default some name", nullptr);
473 trial->AppendGroup("Winner", 10);
474 // Finalize the group selection by accessing the selected group.
475 trial->group();
476 FieldTrialList::AllStatesToString(&save_string);
477 EXPECT_EQ("Some name/Default some name/*trial2/Winner/", save_string);
478 save_string.clear();
479
480 // Create a second trial and winning group.
481 scoped_refptr<FieldTrial> trial2 =
482 CreateFieldTrial("xxx", 10, "Default xxx", nullptr);
483 trial2->AppendGroup("yyyy", 10);
484 // Finalize the group selection by accessing the selected group.
485 trial2->group();
486
487 FieldTrialList::AllStatesToString(&save_string);
488 // We assume names are alphabetized... though this is not critical.
489 EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/",
490 save_string);
491 save_string.clear();
492
493 // Create a third trial with only the default group.
494 scoped_refptr<FieldTrial> trial3 =
495 CreateFieldTrial("zzz", 10, "default", NULL);
496
497 FieldTrialList::AllStatesToString(&save_string);
498 EXPECT_EQ("Some name/Default some name/*trial2/Winner/*xxx/yyyy/zzz/default/",
499 save_string);
500 }
501
TEST_F(FieldTrialTest,Restore)502 TEST_F(FieldTrialTest, Restore) {
503 ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
504 ASSERT_FALSE(FieldTrialList::TrialExists("xxx"));
505
506 FieldTrialList::CreateTrialsFromString("Some_name/Winner/xxx/yyyy/",
507 FieldTrialList::DONT_ACTIVATE_TRIALS,
508 std::set<std::string>());
509
510 FieldTrial* trial = FieldTrialList::Find("Some_name");
511 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
512 EXPECT_EQ("Winner", trial->group_name());
513 EXPECT_EQ("Some_name", trial->trial_name());
514
515 trial = FieldTrialList::Find("xxx");
516 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
517 EXPECT_EQ("yyyy", trial->group_name());
518 EXPECT_EQ("xxx", trial->trial_name());
519 }
520
TEST_F(FieldTrialTest,RestoreNotEndingWithSlash)521 TEST_F(FieldTrialTest, RestoreNotEndingWithSlash) {
522 EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(
523 "tname/gname", FieldTrialList::DONT_ACTIVATE_TRIALS,
524 std::set<std::string>()));
525
526 FieldTrial* trial = FieldTrialList::Find("tname");
527 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
528 EXPECT_EQ("gname", trial->group_name());
529 EXPECT_EQ("tname", trial->trial_name());
530 }
531
TEST_F(FieldTrialTest,BogusRestore)532 TEST_F(FieldTrialTest, BogusRestore) {
533 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
534 "MissingSlash", FieldTrialList::DONT_ACTIVATE_TRIALS,
535 std::set<std::string>()));
536 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
537 "MissingGroupName/", FieldTrialList::DONT_ACTIVATE_TRIALS,
538 std::set<std::string>()));
539 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
540 "noname, only group/", FieldTrialList::DONT_ACTIVATE_TRIALS,
541 std::set<std::string>()));
542 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
543 "/emptyname", FieldTrialList::DONT_ACTIVATE_TRIALS,
544 std::set<std::string>()));
545 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
546 "*/emptyname", FieldTrialList::DONT_ACTIVATE_TRIALS,
547 std::set<std::string>()));
548 }
549
TEST_F(FieldTrialTest,DuplicateRestore)550 TEST_F(FieldTrialTest, DuplicateRestore) {
551 scoped_refptr<FieldTrial> trial =
552 CreateFieldTrial("Some name", 10, "Default", NULL);
553 trial->AppendGroup("Winner", 10);
554 // Finalize the group selection by accessing the selected group.
555 trial->group();
556 std::string save_string;
557 FieldTrialList::StatesToString(&save_string);
558 EXPECT_EQ("Some name/Winner/", save_string);
559
560 // It is OK if we redundantly specify a winner.
561 EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(
562 save_string, FieldTrialList::DONT_ACTIVATE_TRIALS,
563 std::set<std::string>()));
564
565 // But it is an error to try to change to a different winner.
566 EXPECT_FALSE(FieldTrialList::CreateTrialsFromString(
567 "Some name/Loser/", FieldTrialList::DONT_ACTIVATE_TRIALS,
568 std::set<std::string>()));
569 }
570
TEST_F(FieldTrialTest,CreateTrialsFromStringActive)571 TEST_F(FieldTrialTest, CreateTrialsFromStringActive) {
572 ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
573 ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
574 ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
575 "Abc/def/Xyz/zyx/", FieldTrialList::ACTIVATE_TRIALS,
576 std::set<std::string>()));
577
578 FieldTrial::ActiveGroups active_groups;
579 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
580 ASSERT_EQ(2U, active_groups.size());
581 EXPECT_EQ("Abc", active_groups[0].trial_name);
582 EXPECT_EQ("def", active_groups[0].group_name);
583 EXPECT_EQ("Xyz", active_groups[1].trial_name);
584 EXPECT_EQ("zyx", active_groups[1].group_name);
585 }
586
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActive)587 TEST_F(FieldTrialTest, CreateTrialsFromStringNotActive) {
588 ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
589 ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
590 ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
591 "Abc/def/Xyz/zyx/", FieldTrialList::DONT_ACTIVATE_TRIALS,
592 std::set<std::string>()));
593
594 FieldTrial::ActiveGroups active_groups;
595 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
596 ASSERT_TRUE(active_groups.empty());
597
598 // Check that the values still get returned and querying them activates them.
599 EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
600 EXPECT_EQ("zyx", FieldTrialList::FindFullName("Xyz"));
601
602 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
603 ASSERT_EQ(2U, active_groups.size());
604 EXPECT_EQ("Abc", active_groups[0].trial_name);
605 EXPECT_EQ("def", active_groups[0].group_name);
606 EXPECT_EQ("Xyz", active_groups[1].trial_name);
607 EXPECT_EQ("zyx", active_groups[1].group_name);
608 }
609
TEST_F(FieldTrialTest,CreateTrialsFromStringForceActivation)610 TEST_F(FieldTrialTest, CreateTrialsFromStringForceActivation) {
611 ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
612 ASSERT_FALSE(FieldTrialList::TrialExists("def"));
613 ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
614 ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
615 "*Abc/cba/def/fed/*Xyz/zyx/", FieldTrialList::DONT_ACTIVATE_TRIALS,
616 std::set<std::string>()));
617
618 FieldTrial::ActiveGroups active_groups;
619 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
620 ASSERT_EQ(2U, active_groups.size());
621 EXPECT_EQ("Abc", active_groups[0].trial_name);
622 EXPECT_EQ("cba", active_groups[0].group_name);
623 EXPECT_EQ("Xyz", active_groups[1].trial_name);
624 EXPECT_EQ("zyx", active_groups[1].group_name);
625 }
626
TEST_F(FieldTrialTest,CreateTrialsFromStringActiveObserver)627 TEST_F(FieldTrialTest, CreateTrialsFromStringActiveObserver) {
628 ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
629
630 TestFieldTrialObserver observer;
631 ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
632 "Abc/def/", FieldTrialList::ACTIVATE_TRIALS, std::set<std::string>()));
633
634 RunLoop().RunUntilIdle();
635 EXPECT_EQ("Abc", observer.trial_name());
636 EXPECT_EQ("def", observer.group_name());
637 }
638
TEST_F(FieldTrialTest,CreateTrialsFromStringNotActiveObserver)639 TEST_F(FieldTrialTest, CreateTrialsFromStringNotActiveObserver) {
640 ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
641
642 TestFieldTrialObserver observer;
643 ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
644 "Abc/def/", FieldTrialList::DONT_ACTIVATE_TRIALS,
645 std::set<std::string>()));
646 RunLoop().RunUntilIdle();
647 // Observer shouldn't be notified.
648 EXPECT_TRUE(observer.trial_name().empty());
649
650 // Check that the values still get returned and querying them activates them.
651 EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
652
653 RunLoop().RunUntilIdle();
654 EXPECT_EQ("Abc", observer.trial_name());
655 EXPECT_EQ("def", observer.group_name());
656 }
657
TEST_F(FieldTrialTest,CreateTrialsFromStringWithIgnoredFieldTrials)658 TEST_F(FieldTrialTest, CreateTrialsFromStringWithIgnoredFieldTrials) {
659 ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
660 ASSERT_FALSE(FieldTrialList::TrialExists("Foo"));
661 ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
662 ASSERT_FALSE(FieldTrialList::TrialExists("Bar"));
663 ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
664
665 std::set<std::string> ignored_trial_names;
666 ignored_trial_names.insert("Unaccepted1");
667 ignored_trial_names.insert("Unaccepted2");
668 ignored_trial_names.insert("Unaccepted3");
669
670 FieldTrialList::CreateTrialsFromString(
671 "Unaccepted1/Unaccepted1_name/"
672 "Foo/Foo_name/"
673 "Unaccepted2/Unaccepted2_name/"
674 "Bar/Bar_name/"
675 "Unaccepted3/Unaccepted3_name/",
676 FieldTrialList::DONT_ACTIVATE_TRIALS,
677 ignored_trial_names);
678
679 EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
680 EXPECT_TRUE(FieldTrialList::TrialExists("Foo"));
681 EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
682 EXPECT_TRUE(FieldTrialList::TrialExists("Bar"));
683 EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
684
685 FieldTrial::ActiveGroups active_groups;
686 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
687 EXPECT_TRUE(active_groups.empty());
688
689 FieldTrial* trial = FieldTrialList::Find("Foo");
690 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
691 EXPECT_EQ("Foo", trial->trial_name());
692 EXPECT_EQ("Foo_name", trial->group_name());
693
694 trial = FieldTrialList::Find("Bar");
695 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
696 EXPECT_EQ("Bar", trial->trial_name());
697 EXPECT_EQ("Bar_name", trial->group_name());
698 }
699
TEST_F(FieldTrialTest,CreateFieldTrial)700 TEST_F(FieldTrialTest, CreateFieldTrial) {
701 ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
702
703 FieldTrialList::CreateFieldTrial("Some_name", "Winner");
704
705 FieldTrial* trial = FieldTrialList::Find("Some_name");
706 ASSERT_NE(static_cast<FieldTrial*>(NULL), trial);
707 EXPECT_EQ("Winner", trial->group_name());
708 EXPECT_EQ("Some_name", trial->trial_name());
709 }
710
TEST_F(FieldTrialTest,CreateFieldTrialIsNotActive)711 TEST_F(FieldTrialTest, CreateFieldTrialIsNotActive) {
712 const char kTrialName[] = "CreateFieldTrialIsActiveTrial";
713 const char kWinnerGroup[] = "Winner";
714 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
715 FieldTrialList::CreateFieldTrial(kTrialName, kWinnerGroup);
716
717 FieldTrial::ActiveGroups active_groups;
718 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
719 EXPECT_TRUE(active_groups.empty());
720 }
721
TEST_F(FieldTrialTest,DuplicateFieldTrial)722 TEST_F(FieldTrialTest, DuplicateFieldTrial) {
723 scoped_refptr<FieldTrial> trial =
724 CreateFieldTrial("Some_name", 10, "Default", NULL);
725 trial->AppendGroup("Winner", 10);
726
727 // It is OK if we redundantly specify a winner.
728 FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("Some_name", "Winner");
729 EXPECT_TRUE(trial1 != NULL);
730
731 // But it is an error to try to change to a different winner.
732 FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("Some_name", "Loser");
733 EXPECT_TRUE(trial2 == NULL);
734 }
735
TEST_F(FieldTrialTest,DisableImmediately)736 TEST_F(FieldTrialTest, DisableImmediately) {
737 int default_group_number = -1;
738 scoped_refptr<FieldTrial> trial =
739 CreateFieldTrial("trial", 100, "default", &default_group_number);
740 trial->Disable();
741 ASSERT_EQ("default", trial->group_name());
742 ASSERT_EQ(default_group_number, trial->group());
743 }
744
TEST_F(FieldTrialTest,DisableAfterInitialization)745 TEST_F(FieldTrialTest, DisableAfterInitialization) {
746 scoped_refptr<FieldTrial> trial =
747 CreateFieldTrial("trial", 100, "default", NULL);
748 trial->AppendGroup("non_default", 100);
749 trial->Disable();
750 ASSERT_EQ("default", trial->group_name());
751 }
752
TEST_F(FieldTrialTest,ForcedFieldTrials)753 TEST_F(FieldTrialTest, ForcedFieldTrials) {
754 // Validate we keep the forced choice.
755 FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Use the",
756 "Force");
757 EXPECT_STREQ("Force", forced_trial->group_name().c_str());
758
759 int default_group_number = -1;
760 scoped_refptr<FieldTrial> factory_trial =
761 CreateFieldTrial("Use the", 1000, "default", &default_group_number);
762 EXPECT_EQ(factory_trial.get(), forced_trial);
763
764 int chosen_group = factory_trial->AppendGroup("Force", 100);
765 EXPECT_EQ(chosen_group, factory_trial->group());
766 int not_chosen_group = factory_trial->AppendGroup("Dark Side", 100);
767 EXPECT_NE(chosen_group, not_chosen_group);
768
769 // Since we didn't force the default group, we should not be returned the
770 // chosen group as the default group.
771 EXPECT_NE(default_group_number, chosen_group);
772 int new_group = factory_trial->AppendGroup("Duck Tape", 800);
773 EXPECT_NE(chosen_group, new_group);
774 // The new group should not be the default group either.
775 EXPECT_NE(default_group_number, new_group);
776 }
777
TEST_F(FieldTrialTest,ForcedFieldTrialsDefaultGroup)778 TEST_F(FieldTrialTest, ForcedFieldTrialsDefaultGroup) {
779 // Forcing the default should use the proper group ID.
780 FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Trial Name",
781 "Default");
782 int default_group_number = -1;
783 scoped_refptr<FieldTrial> factory_trial =
784 CreateFieldTrial("Trial Name", 1000, "Default", &default_group_number);
785 EXPECT_EQ(forced_trial, factory_trial.get());
786
787 int other_group = factory_trial->AppendGroup("Not Default", 100);
788 EXPECT_STREQ("Default", factory_trial->group_name().c_str());
789 EXPECT_EQ(default_group_number, factory_trial->group());
790 EXPECT_NE(other_group, factory_trial->group());
791
792 int new_other_group = factory_trial->AppendGroup("Not Default Either", 800);
793 EXPECT_NE(new_other_group, factory_trial->group());
794 }
795
TEST_F(FieldTrialTest,SetForced)796 TEST_F(FieldTrialTest, SetForced) {
797 // Start by setting a trial for which we ensure a winner...
798 int default_group_number = -1;
799 scoped_refptr<FieldTrial> forced_trial =
800 CreateFieldTrial("Use the", 1, "default", &default_group_number);
801 EXPECT_EQ(forced_trial, forced_trial);
802
803 int forced_group = forced_trial->AppendGroup("Force", 1);
804 EXPECT_EQ(forced_group, forced_trial->group());
805
806 // Now force it.
807 forced_trial->SetForced();
808
809 // Now try to set it up differently as a hard coded registration would.
810 scoped_refptr<FieldTrial> hard_coded_trial =
811 CreateFieldTrial("Use the", 1, "default", &default_group_number);
812 EXPECT_EQ(hard_coded_trial, forced_trial);
813
814 int would_lose_group = hard_coded_trial->AppendGroup("Force", 0);
815 EXPECT_EQ(forced_group, hard_coded_trial->group());
816 EXPECT_EQ(forced_group, would_lose_group);
817
818 // Same thing if we would have done it to win again.
819 scoped_refptr<FieldTrial> other_hard_coded_trial =
820 CreateFieldTrial("Use the", 1, "default", &default_group_number);
821 EXPECT_EQ(other_hard_coded_trial, forced_trial);
822
823 int would_win_group = other_hard_coded_trial->AppendGroup("Force", 1);
824 EXPECT_EQ(forced_group, other_hard_coded_trial->group());
825 EXPECT_EQ(forced_group, would_win_group);
826 }
827
TEST_F(FieldTrialTest,SetForcedDefaultOnly)828 TEST_F(FieldTrialTest, SetForcedDefaultOnly) {
829 const char kTrialName[] = "SetForcedDefaultOnly";
830 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
831
832 int default_group = -1;
833 scoped_refptr<FieldTrial> trial =
834 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
835 trial->SetForced();
836
837 trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, NULL);
838 EXPECT_EQ(default_group, trial->group());
839 EXPECT_EQ(kDefaultGroupName, trial->group_name());
840 }
841
TEST_F(FieldTrialTest,SetForcedDefaultWithExtraGroup)842 TEST_F(FieldTrialTest, SetForcedDefaultWithExtraGroup) {
843 const char kTrialName[] = "SetForcedDefaultWithExtraGroup";
844 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
845
846 int default_group = -1;
847 scoped_refptr<FieldTrial> trial =
848 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
849 trial->SetForced();
850
851 trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, NULL);
852 const int extra_group = trial->AppendGroup("Extra", 100);
853 EXPECT_EQ(default_group, trial->group());
854 EXPECT_NE(extra_group, trial->group());
855 EXPECT_EQ(kDefaultGroupName, trial->group_name());
856 }
857
TEST_F(FieldTrialTest,SetForcedTurnFeatureOn)858 TEST_F(FieldTrialTest, SetForcedTurnFeatureOn) {
859 const char kTrialName[] = "SetForcedTurnFeatureOn";
860 const char kExtraGroupName[] = "Extra";
861 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
862
863 // Simulate a server-side (forced) config that turns the feature on when the
864 // original hard-coded config had it disabled.
865 scoped_refptr<FieldTrial> forced_trial =
866 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, NULL);
867 forced_trial->AppendGroup(kExtraGroupName, 100);
868 forced_trial->SetForced();
869
870 int default_group = -1;
871 scoped_refptr<FieldTrial> client_trial =
872 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
873 const int extra_group = client_trial->AppendGroup(kExtraGroupName, 0);
874 EXPECT_NE(default_group, extra_group);
875
876 EXPECT_FALSE(client_trial->group_reported_);
877 EXPECT_EQ(extra_group, client_trial->group());
878 EXPECT_TRUE(client_trial->group_reported_);
879 EXPECT_EQ(kExtraGroupName, client_trial->group_name());
880 }
881
TEST_F(FieldTrialTest,SetForcedTurnFeatureOff)882 TEST_F(FieldTrialTest, SetForcedTurnFeatureOff) {
883 const char kTrialName[] = "SetForcedTurnFeatureOff";
884 const char kExtraGroupName[] = "Extra";
885 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
886
887 // Simulate a server-side (forced) config that turns the feature off when the
888 // original hard-coded config had it enabled.
889 scoped_refptr<FieldTrial> forced_trial =
890 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, NULL);
891 forced_trial->AppendGroup(kExtraGroupName, 0);
892 forced_trial->SetForced();
893
894 int default_group = -1;
895 scoped_refptr<FieldTrial> client_trial =
896 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
897 const int extra_group = client_trial->AppendGroup(kExtraGroupName, 100);
898 EXPECT_NE(default_group, extra_group);
899
900 EXPECT_FALSE(client_trial->group_reported_);
901 EXPECT_EQ(default_group, client_trial->group());
902 EXPECT_TRUE(client_trial->group_reported_);
903 EXPECT_EQ(kDefaultGroupName, client_trial->group_name());
904 }
905
TEST_F(FieldTrialTest,SetForcedChangeDefault_Default)906 TEST_F(FieldTrialTest, SetForcedChangeDefault_Default) {
907 const char kTrialName[] = "SetForcedDefaultGroupChange";
908 const char kGroupAName[] = "A";
909 const char kGroupBName[] = "B";
910 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
911
912 // Simulate a server-side (forced) config that switches which group is default
913 // and ensures that the non-forced code receives the correct group numbers.
914 scoped_refptr<FieldTrial> forced_trial =
915 CreateFieldTrial(kTrialName, 100, kGroupAName, NULL);
916 forced_trial->AppendGroup(kGroupBName, 100);
917 forced_trial->SetForced();
918
919 int default_group = -1;
920 scoped_refptr<FieldTrial> client_trial =
921 CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
922 const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
923 EXPECT_NE(default_group, extra_group);
924
925 EXPECT_FALSE(client_trial->group_reported_);
926 EXPECT_EQ(default_group, client_trial->group());
927 EXPECT_TRUE(client_trial->group_reported_);
928 EXPECT_EQ(kGroupBName, client_trial->group_name());
929 }
930
TEST_F(FieldTrialTest,SetForcedChangeDefault_NonDefault)931 TEST_F(FieldTrialTest, SetForcedChangeDefault_NonDefault) {
932 const char kTrialName[] = "SetForcedDefaultGroupChange";
933 const char kGroupAName[] = "A";
934 const char kGroupBName[] = "B";
935 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
936
937 // Simulate a server-side (forced) config that switches which group is default
938 // and ensures that the non-forced code receives the correct group numbers.
939 scoped_refptr<FieldTrial> forced_trial =
940 CreateFieldTrial(kTrialName, 100, kGroupAName, NULL);
941 forced_trial->AppendGroup(kGroupBName, 0);
942 forced_trial->SetForced();
943
944 int default_group = -1;
945 scoped_refptr<FieldTrial> client_trial =
946 CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
947 const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
948 EXPECT_NE(default_group, extra_group);
949
950 EXPECT_FALSE(client_trial->group_reported_);
951 EXPECT_EQ(extra_group, client_trial->group());
952 EXPECT_TRUE(client_trial->group_reported_);
953 EXPECT_EQ(kGroupAName, client_trial->group_name());
954 }
955
TEST_F(FieldTrialTest,Observe)956 TEST_F(FieldTrialTest, Observe) {
957 const char kTrialName[] = "TrialToObserve1";
958 const char kSecondaryGroupName[] = "SecondaryGroup";
959
960 TestFieldTrialObserver observer;
961 int default_group = -1;
962 scoped_refptr<FieldTrial> trial =
963 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
964 const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
965 const int chosen_group = trial->group();
966 EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
967
968 RunLoop().RunUntilIdle();
969 EXPECT_EQ(kTrialName, observer.trial_name());
970 if (chosen_group == default_group)
971 EXPECT_EQ(kDefaultGroupName, observer.group_name());
972 else
973 EXPECT_EQ(kSecondaryGroupName, observer.group_name());
974 }
975
TEST_F(FieldTrialTest,ObserveDisabled)976 TEST_F(FieldTrialTest, ObserveDisabled) {
977 const char kTrialName[] = "TrialToObserve2";
978
979 TestFieldTrialObserver observer;
980 int default_group = -1;
981 scoped_refptr<FieldTrial> trial =
982 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
983 trial->AppendGroup("A", 25);
984 trial->AppendGroup("B", 25);
985 trial->AppendGroup("C", 25);
986 trial->Disable();
987
988 // Observer shouldn't be notified of a disabled trial.
989 RunLoop().RunUntilIdle();
990 EXPECT_TRUE(observer.trial_name().empty());
991 EXPECT_TRUE(observer.group_name().empty());
992
993 // Observer shouldn't be notified even after a |group()| call.
994 EXPECT_EQ(default_group, trial->group());
995 RunLoop().RunUntilIdle();
996 EXPECT_TRUE(observer.trial_name().empty());
997 EXPECT_TRUE(observer.group_name().empty());
998 }
999
TEST_F(FieldTrialTest,ObserveForcedDisabled)1000 TEST_F(FieldTrialTest, ObserveForcedDisabled) {
1001 const char kTrialName[] = "TrialToObserve3";
1002
1003 TestFieldTrialObserver observer;
1004 int default_group = -1;
1005 scoped_refptr<FieldTrial> trial =
1006 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
1007 trial->AppendGroup("A", 25);
1008 trial->AppendGroup("B", 25);
1009 trial->AppendGroup("C", 25);
1010 trial->SetForced();
1011 trial->Disable();
1012
1013 // Observer shouldn't be notified of a disabled trial, even when forced.
1014 RunLoop().RunUntilIdle();
1015 EXPECT_TRUE(observer.trial_name().empty());
1016 EXPECT_TRUE(observer.group_name().empty());
1017
1018 // Observer shouldn't be notified even after a |group()| call.
1019 EXPECT_EQ(default_group, trial->group());
1020 RunLoop().RunUntilIdle();
1021 EXPECT_TRUE(observer.trial_name().empty());
1022 EXPECT_TRUE(observer.group_name().empty());
1023 }
1024
TEST_F(FieldTrialTest,DisabledTrialNotActive)1025 TEST_F(FieldTrialTest, DisabledTrialNotActive) {
1026 const char kTrialName[] = "DisabledTrial";
1027 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1028
1029 scoped_refptr<FieldTrial> trial =
1030 CreateFieldTrial(kTrialName, 100, kDefaultGroupName, NULL);
1031 trial->AppendGroup("X", 50);
1032 trial->Disable();
1033
1034 // Ensure the trial is not listed as active.
1035 FieldTrial::ActiveGroups active_groups;
1036 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
1037 EXPECT_TRUE(active_groups.empty());
1038
1039 // Ensure the trial is not listed in the |StatesToString()| result.
1040 std::string states;
1041 FieldTrialList::StatesToString(&states);
1042 EXPECT_TRUE(states.empty());
1043 }
1044
TEST_F(FieldTrialTest,ExpirationYearNotExpired)1045 TEST_F(FieldTrialTest, ExpirationYearNotExpired) {
1046 const char kTrialName[] = "NotExpired";
1047 const char kGroupName[] = "Group2";
1048 const int kProbability = 100;
1049 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1050
1051 scoped_refptr<FieldTrial> trial =
1052 CreateFieldTrial(kTrialName, kProbability, kDefaultGroupName, NULL);
1053 trial->AppendGroup(kGroupName, kProbability);
1054 EXPECT_EQ(kGroupName, trial->group_name());
1055 }
1056
TEST_F(FieldTrialTest,FloatBoundariesGiveEqualGroupSizes)1057 TEST_F(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes) {
1058 const int kBucketCount = 100;
1059
1060 // Try each boundary value |i / 100.0| as the entropy value.
1061 for (int i = 0; i < kBucketCount; ++i) {
1062 const double entropy = i / static_cast<double>(kBucketCount);
1063
1064 scoped_refptr<base::FieldTrial> trial(
1065 new base::FieldTrial("test", kBucketCount, "default", entropy));
1066 for (int j = 0; j < kBucketCount; ++j)
1067 trial->AppendGroup(base::IntToString(j), 1);
1068
1069 EXPECT_EQ(base::IntToString(i), trial->group_name());
1070 }
1071 }
1072
TEST_F(FieldTrialTest,DoesNotSurpassTotalProbability)1073 TEST_F(FieldTrialTest, DoesNotSurpassTotalProbability) {
1074 const double kEntropyValue = 1.0 - 1e-9;
1075 ASSERT_LT(kEntropyValue, 1.0);
1076
1077 scoped_refptr<base::FieldTrial> trial(
1078 new base::FieldTrial("test", 2, "default", kEntropyValue));
1079 trial->AppendGroup("1", 1);
1080 trial->AppendGroup("2", 1);
1081
1082 EXPECT_EQ("2", trial->group_name());
1083 }
1084
TEST_F(FieldTrialTest,CreateSimulatedFieldTrial)1085 TEST_F(FieldTrialTest, CreateSimulatedFieldTrial) {
1086 const char kTrialName[] = "CreateSimulatedFieldTrial";
1087 ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
1088
1089 // Different cases to test, e.g. default vs. non default group being chosen.
1090 struct {
1091 double entropy_value;
1092 const char* expected_group;
1093 } test_cases[] = {
1094 { 0.4, "A" },
1095 { 0.85, "B" },
1096 { 0.95, kDefaultGroupName },
1097 };
1098
1099 for (size_t i = 0; i < arraysize(test_cases); ++i) {
1100 TestFieldTrialObserver observer;
1101 scoped_refptr<FieldTrial> trial(
1102 FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, kDefaultGroupName,
1103 test_cases[i].entropy_value));
1104 trial->AppendGroup("A", 80);
1105 trial->AppendGroup("B", 10);
1106 EXPECT_EQ(test_cases[i].expected_group, trial->group_name());
1107
1108 // Field trial shouldn't have been registered with the list.
1109 EXPECT_FALSE(FieldTrialList::TrialExists(kTrialName));
1110 EXPECT_EQ(0u, FieldTrialList::GetFieldTrialCount());
1111
1112 // Observer shouldn't have been notified.
1113 RunLoop().RunUntilIdle();
1114 EXPECT_TRUE(observer.trial_name().empty());
1115
1116 // The trial shouldn't be in the active set of trials.
1117 FieldTrial::ActiveGroups active_groups;
1118 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
1119 EXPECT_TRUE(active_groups.empty());
1120
1121 // The trial shouldn't be listed in the |StatesToString()| result.
1122 std::string states;
1123 FieldTrialList::StatesToString(&states);
1124 EXPECT_TRUE(states.empty());
1125 }
1126 }
1127
TEST(FieldTrialTestWithoutList,StatesStringFormat)1128 TEST(FieldTrialTestWithoutList, StatesStringFormat) {
1129 std::string save_string;
1130
1131 // Scoping the first FieldTrialList, as we need another one to test the
1132 // importing function.
1133 {
1134 FieldTrialList field_trial_list(NULL);
1135 scoped_refptr<FieldTrial> trial =
1136 CreateFieldTrial("Abc", 10, "Default some name", NULL);
1137 trial->AppendGroup("cba", 10);
1138 trial->group();
1139 scoped_refptr<FieldTrial> trial2 =
1140 CreateFieldTrial("Xyz", 10, "Default xxx", NULL);
1141 trial2->AppendGroup("zyx", 10);
1142 trial2->group();
1143 scoped_refptr<FieldTrial> trial3 =
1144 CreateFieldTrial("zzz", 10, "default", NULL);
1145
1146 FieldTrialList::AllStatesToString(&save_string);
1147 }
1148
1149 // Starting with a new blank FieldTrialList.
1150 FieldTrialList field_trial_list(NULL);
1151 ASSERT_TRUE(field_trial_list.CreateTrialsFromString(
1152 save_string, FieldTrialList::DONT_ACTIVATE_TRIALS,
1153 std::set<std::string>()));
1154
1155 FieldTrial::ActiveGroups active_groups;
1156 field_trial_list.GetActiveFieldTrialGroups(&active_groups);
1157 ASSERT_EQ(2U, active_groups.size());
1158 EXPECT_EQ("Abc", active_groups[0].trial_name);
1159 EXPECT_EQ("cba", active_groups[0].group_name);
1160 EXPECT_EQ("Xyz", active_groups[1].trial_name);
1161 EXPECT_EQ("zyx", active_groups[1].group_name);
1162 EXPECT_TRUE(field_trial_list.TrialExists("zzz"));
1163 }
1164
1165 #if GTEST_HAS_DEATH_TEST
TEST(FieldTrialDeathTest,OneTimeRandomizedTrialWithoutFieldTrialList)1166 TEST(FieldTrialDeathTest, OneTimeRandomizedTrialWithoutFieldTrialList) {
1167 // Trying to instantiate a one-time randomized field trial before the
1168 // FieldTrialList is created should crash.
1169 EXPECT_DEATH(FieldTrialList::FactoryGetFieldTrial(
1170 "OneTimeRandomizedTrialWithoutFieldTrialList", 100, kDefaultGroupName,
1171 base::FieldTrialList::kNoExpirationYear, 1, 1,
1172 base::FieldTrial::ONE_TIME_RANDOMIZED, NULL), "");
1173 }
1174 #endif
1175
1176 } // namespace base
1177