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