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