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, ¶ms)); 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, ¶ms)); 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, ¶ms)); 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, ¶ms)); 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