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