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