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