Home | History | Annotate | Download | only in variations
      1 // Copyright 2013 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 "components/variations/variations_associated_data.h"
      6 
      7 #include "base/metrics/field_trial.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace chrome_variations {
     11 
     12 namespace {
     13 
     14 const VariationID TEST_VALUE_A = 3300200;
     15 const VariationID TEST_VALUE_B = 3300201;
     16 
     17 // Convenience helper to retrieve the chrome_variations::VariationID for a
     18 // FieldTrial. Note that this will do the group assignment in |trial| if not
     19 // already done.
     20 VariationID GetIDForTrial(IDCollectionKey key, base::FieldTrial* trial) {
     21   return GetGoogleVariationID(key, trial->trial_name(), trial->group_name());
     22 }
     23 
     24 // Tests whether a field trial is active (i.e. group() has been called on it).
     25 bool IsFieldTrialActive(const std::string& trial_name) {
     26   base::FieldTrial::ActiveGroups active_groups;
     27   base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
     28   for (size_t i = 0; i < active_groups.size(); ++i) {
     29     if (active_groups[i].trial_name == trial_name)
     30       return true;
     31   }
     32   return false;
     33 }
     34 
     35 // Call FieldTrialList::FactoryGetFieldTrial() with a future expiry date.
     36 scoped_refptr<base::FieldTrial> CreateFieldTrial(
     37     const std::string& trial_name,
     38     int total_probability,
     39     const std::string& default_group_name,
     40     int* default_group_number) {
     41   return base::FieldTrialList::FactoryGetFieldTrial(
     42       trial_name, total_probability, default_group_name,
     43       base::FieldTrialList::kNoExpirationYear, 1, 1,
     44       base::FieldTrial::SESSION_RANDOMIZED, default_group_number);
     45 }
     46 
     47 }  // namespace
     48 
     49 class VariationsAssociatedDataTest : public ::testing::Test {
     50  public:
     51   VariationsAssociatedDataTest() : field_trial_list_(NULL) {
     52   }
     53 
     54   virtual ~VariationsAssociatedDataTest() {
     55     // Ensure that the maps are cleared between tests, since they are stored as
     56     // process singletons.
     57     testing::ClearAllVariationIDs();
     58     testing::ClearAllVariationParams();
     59   }
     60 
     61  private:
     62   base::FieldTrialList field_trial_list_;
     63 
     64   DISALLOW_COPY_AND_ASSIGN(VariationsAssociatedDataTest);
     65 };
     66 
     67 // Test that if the trial is immediately disabled, GetGoogleVariationID just
     68 // returns the empty ID.
     69 TEST_F(VariationsAssociatedDataTest, DisableImmediately) {
     70   int default_group_number = -1;
     71   scoped_refptr<base::FieldTrial> trial(
     72       CreateFieldTrial("trial", 100, "default", &default_group_number));
     73 
     74   ASSERT_EQ(default_group_number, trial->group());
     75   ASSERT_EQ(EMPTY_ID, GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial.get()));
     76 }
     77 
     78 // Test that successfully associating the FieldTrial with some ID, and then
     79 // disabling the FieldTrial actually makes GetGoogleVariationID correctly
     80 // return the empty ID.
     81 TEST_F(VariationsAssociatedDataTest, DisableAfterInitialization) {
     82   const std::string default_name = "default";
     83   const std::string non_default_name = "non_default";
     84 
     85   scoped_refptr<base::FieldTrial> trial(
     86       CreateFieldTrial("trial", 100, default_name, NULL));
     87 
     88   trial->AppendGroup(non_default_name, 100);
     89   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial->trial_name(),
     90       default_name, TEST_VALUE_A);
     91   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial->trial_name(),
     92       non_default_name, TEST_VALUE_B);
     93   trial->Disable();
     94   ASSERT_EQ(default_name, trial->group_name());
     95   ASSERT_EQ(TEST_VALUE_A, GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial.get()));
     96 }
     97 
     98 // Test various successful association cases.
     99 TEST_F(VariationsAssociatedDataTest, AssociateGoogleVariationID) {
    100   const std::string default_name1 = "default";
    101   scoped_refptr<base::FieldTrial> trial_true(
    102       CreateFieldTrial("d1", 10, default_name1, NULL));
    103   const std::string winner = "TheWinner";
    104   int winner_group = trial_true->AppendGroup(winner, 10);
    105 
    106   // Set GoogleVariationIDs so we can verify that they were chosen correctly.
    107   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial_true->trial_name(),
    108       default_name1, TEST_VALUE_A);
    109   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial_true->trial_name(),
    110       winner, TEST_VALUE_B);
    111 
    112   EXPECT_EQ(winner_group, trial_true->group());
    113   EXPECT_EQ(winner, trial_true->group_name());
    114   EXPECT_EQ(TEST_VALUE_B,
    115             GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial_true.get()));
    116 
    117   const std::string default_name2 = "default2";
    118   scoped_refptr<base::FieldTrial> trial_false(
    119       CreateFieldTrial("d2", 10, default_name2, NULL));
    120   const std::string loser = "ALoser";
    121   const int loser_group = trial_false->AppendGroup(loser, 0);
    122 
    123   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial_false->trial_name(),
    124       default_name2, TEST_VALUE_A);
    125   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial_false->trial_name(),
    126       loser, TEST_VALUE_B);
    127 
    128   EXPECT_NE(loser_group, trial_false->group());
    129   EXPECT_EQ(TEST_VALUE_A,
    130             GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial_false.get()));
    131 }
    132 
    133 // Test that not associating a FieldTrial with any IDs ensure that the empty ID
    134 // will be returned.
    135 TEST_F(VariationsAssociatedDataTest, NoAssociation) {
    136   const std::string default_name = "default";
    137   scoped_refptr<base::FieldTrial> no_id_trial(
    138       CreateFieldTrial("d3", 10, default_name, NULL));
    139 
    140   const std::string winner = "TheWinner";
    141   const int winner_group = no_id_trial->AppendGroup(winner, 10);
    142 
    143   // Ensure that despite the fact that a normal winner is elected, it does not
    144   // have a valid VariationID associated with it.
    145   EXPECT_EQ(winner_group, no_id_trial->group());
    146   EXPECT_EQ(winner, no_id_trial->group_name());
    147   EXPECT_EQ(EMPTY_ID, GetIDForTrial(GOOGLE_WEB_PROPERTIES, no_id_trial.get()));
    148 }
    149 
    150 // Ensure that the AssociateGoogleVariationIDForce works as expected.
    151 TEST_F(VariationsAssociatedDataTest, ForceAssociation) {
    152   EXPECT_EQ(EMPTY_ID,
    153             GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group"));
    154   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group",
    155                              TEST_VALUE_A);
    156   EXPECT_EQ(TEST_VALUE_A,
    157             GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group"));
    158   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group",
    159                              TEST_VALUE_B);
    160   EXPECT_EQ(TEST_VALUE_A,
    161             GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group"));
    162   AssociateGoogleVariationIDForce(GOOGLE_WEB_PROPERTIES, "trial", "group",
    163                                   TEST_VALUE_B);
    164   EXPECT_EQ(TEST_VALUE_B,
    165             GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial", "group"));
    166 }
    167 
    168 // Ensure that two collections can coexist without affecting each other.
    169 TEST_F(VariationsAssociatedDataTest, CollectionsCoexist) {
    170   const std::string default_name = "default";
    171   int default_group_number = -1;
    172   scoped_refptr<base::FieldTrial> trial_true(
    173       CreateFieldTrial("d1", 10, default_name, &default_group_number));
    174   ASSERT_EQ(default_group_number, trial_true->group());
    175   ASSERT_EQ(default_name, trial_true->group_name());
    176 
    177   EXPECT_EQ(EMPTY_ID,
    178             GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial_true.get()));
    179   EXPECT_EQ(EMPTY_ID,
    180             GetIDForTrial(GOOGLE_WEB_PROPERTIES_TRIGGER, trial_true.get()));
    181   EXPECT_EQ(EMPTY_ID,
    182             GetIDForTrial(GOOGLE_UPDATE_SERVICE, trial_true.get()));
    183 
    184   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES, trial_true->trial_name(),
    185       default_name, TEST_VALUE_A);
    186   EXPECT_EQ(TEST_VALUE_A,
    187             GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial_true.get()));
    188   EXPECT_EQ(EMPTY_ID,
    189             GetIDForTrial(GOOGLE_UPDATE_SERVICE, trial_true.get()));
    190 
    191   AssociateGoogleVariationID(GOOGLE_UPDATE_SERVICE, trial_true->trial_name(),
    192       default_name, TEST_VALUE_A);
    193   EXPECT_EQ(TEST_VALUE_A,
    194             GetIDForTrial(GOOGLE_WEB_PROPERTIES, trial_true.get()));
    195   EXPECT_EQ(TEST_VALUE_A,
    196             GetIDForTrial(GOOGLE_UPDATE_SERVICE, trial_true.get()));
    197 
    198   trial_true = CreateFieldTrial("d2", 10, default_name, &default_group_number);
    199   ASSERT_EQ(default_group_number, trial_true->group());
    200   ASSERT_EQ(default_name, trial_true->group_name());
    201 
    202   AssociateGoogleVariationID(GOOGLE_WEB_PROPERTIES_TRIGGER,
    203                              trial_true->trial_name(), default_name,
    204                              TEST_VALUE_A);
    205   EXPECT_EQ(TEST_VALUE_A,
    206             GetIDForTrial(GOOGLE_WEB_PROPERTIES_TRIGGER, trial_true.get()));
    207   EXPECT_EQ(EMPTY_ID,
    208             GetIDForTrial(GOOGLE_UPDATE_SERVICE, trial_true.get()));
    209 
    210   AssociateGoogleVariationID(GOOGLE_UPDATE_SERVICE, trial_true->trial_name(),
    211                              default_name, TEST_VALUE_A);
    212   EXPECT_EQ(TEST_VALUE_A,
    213             GetIDForTrial(GOOGLE_WEB_PROPERTIES_TRIGGER, trial_true.get()));
    214   EXPECT_EQ(TEST_VALUE_A,
    215             GetIDForTrial(GOOGLE_UPDATE_SERVICE, trial_true.get()));
    216 }
    217 
    218 TEST_F(VariationsAssociatedDataTest, AssociateVariationParams) {
    219   const std::string kTrialName = "AssociateVariationParams";
    220 
    221   {
    222     std::map<std::string, std::string> params;
    223     params["a"] = "10";
    224     params["b"] = "test";
    225     ASSERT_TRUE(AssociateVariationParams(kTrialName, "A", params));
    226   }
    227   {
    228     std::map<std::string, std::string> params;
    229     params["a"] = "5";
    230     ASSERT_TRUE(AssociateVariationParams(kTrialName, "B", params));
    231   }
    232 
    233   base::FieldTrialList::CreateFieldTrial(kTrialName, "B");
    234   EXPECT_EQ("5", GetVariationParamValue(kTrialName, "a"));
    235   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "b"));
    236   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x"));
    237 
    238   std::map<std::string, std::string> params;
    239   EXPECT_TRUE(GetVariationParams(kTrialName, &params));
    240   EXPECT_EQ(1U, params.size());
    241   EXPECT_EQ("5", params["a"]);
    242 }
    243 
    244 TEST_F(VariationsAssociatedDataTest, AssociateVariationParams_Fail) {
    245   const std::string kTrialName = "AssociateVariationParams_Fail";
    246   const std::string kGroupName = "A";
    247 
    248   std::map<std::string, std::string> params;
    249   params["a"] = "10";
    250   ASSERT_TRUE(AssociateVariationParams(kTrialName, kGroupName, params));
    251   params["a"] = "1";
    252   params["b"] = "2";
    253   ASSERT_FALSE(AssociateVariationParams(kTrialName, kGroupName, params));
    254 
    255   base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
    256   EXPECT_EQ("10", GetVariationParamValue(kTrialName, "a"));
    257   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "b"));
    258 }
    259 
    260 TEST_F(VariationsAssociatedDataTest, AssociateVariationParams_TrialActiveFail) {
    261   const std::string kTrialName = "AssociateVariationParams_TrialActiveFail";
    262   base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
    263   ASSERT_EQ("A", base::FieldTrialList::FindFullName(kTrialName));
    264 
    265   std::map<std::string, std::string> params;
    266   params["a"] = "10";
    267   EXPECT_FALSE(AssociateVariationParams(kTrialName, "B", params));
    268   EXPECT_FALSE(AssociateVariationParams(kTrialName, "A", params));
    269 }
    270 
    271 TEST_F(VariationsAssociatedDataTest,
    272        AssociateVariationParams_DoesntActivateTrial) {
    273   const std::string kTrialName = "AssociateVariationParams_DoesntActivateTrial";
    274 
    275   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    276   scoped_refptr<base::FieldTrial> trial(
    277       CreateFieldTrial(kTrialName, 100, "A", NULL));
    278   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    279 
    280   std::map<std::string, std::string> params;
    281   params["a"] = "10";
    282   EXPECT_TRUE(AssociateVariationParams(kTrialName, "A", params));
    283   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    284 }
    285 
    286 TEST_F(VariationsAssociatedDataTest, GetVariationParams_NoTrial) {
    287   const std::string kTrialName = "GetVariationParams_NoParams";
    288 
    289   std::map<std::string, std::string> params;
    290   EXPECT_FALSE(GetVariationParams(kTrialName, &params));
    291   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x"));
    292   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "y"));
    293 }
    294 
    295 TEST_F(VariationsAssociatedDataTest, GetVariationParams_NoParams) {
    296   const std::string kTrialName = "GetVariationParams_NoParams";
    297 
    298   base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
    299 
    300   std::map<std::string, std::string> params;
    301   EXPECT_FALSE(GetVariationParams(kTrialName, &params));
    302   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x"));
    303   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "y"));
    304 }
    305 
    306 TEST_F(VariationsAssociatedDataTest, GetVariationParams_ActivatesTrial) {
    307   const std::string kTrialName = "GetVariationParams_ActivatesTrial";
    308 
    309   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    310   scoped_refptr<base::FieldTrial> trial(
    311       CreateFieldTrial(kTrialName, 100, "A", NULL));
    312   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    313 
    314   std::map<std::string, std::string> params;
    315   EXPECT_FALSE(GetVariationParams(kTrialName, &params));
    316   ASSERT_TRUE(IsFieldTrialActive(kTrialName));
    317 }
    318 
    319 TEST_F(VariationsAssociatedDataTest, GetVariationParamValue_ActivatesTrial) {
    320   const std::string kTrialName = "GetVariationParamValue_ActivatesTrial";
    321 
    322   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    323   scoped_refptr<base::FieldTrial> trial(
    324       CreateFieldTrial(kTrialName, 100, "A", NULL));
    325   ASSERT_FALSE(IsFieldTrialActive(kTrialName));
    326 
    327   std::map<std::string, std::string> params;
    328   EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x"));
    329   ASSERT_TRUE(IsFieldTrialActive(kTrialName));
    330 }
    331 
    332 }  // namespace chrome_variations
    333