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