| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Tests for the Experiment Helpers. | 5 // Tests for the Experiment Helpers. |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/metrics/field_trial.h" | 11 #include "base/metrics/field_trial.h" |
| 12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/common/metrics/experiments_helper.h" | 14 #include "chrome/common/metrics/experiments_helper.h" |
| 14 #include "content/public/test/test_browser_thread.h" | 15 #include "content/public/test/test_browser_thread.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 17 |
| 18 namespace experiments_helper { |
| 19 |
| 17 namespace { | 20 namespace { |
| 18 | 21 |
| 19 // Convenience helper to retrieve the chrome_variations::ID for a FieldTrial. | 22 // Convenience helper to retrieve the chrome_variations::ID for a FieldTrial. |
| 20 // Note that this will do the group assignment in |trial| if not already done. | 23 // Note that this will do the group assignment in |trial| if not already done. |
| 21 chrome_variations::ID GetIDForTrial(base::FieldTrial* trial) { | 24 chrome_variations::ID GetIDForTrial(base::FieldTrial* trial) { |
| 22 return experiments_helper::GetGoogleVariationID(trial->name(), | 25 return GetGoogleVariationID(trial->name(), trial->group_name()); |
| 23 trial->group_name()); | |
| 24 } | 26 } |
| 25 | 27 |
| 26 } // namespace | 28 } // namespace |
| 27 | 29 |
| 28 class ExperimentsHelperTest : public ::testing::Test { | 30 class ExperimentsHelperTest : public ::testing::Test { |
| 29 public: | 31 public: |
| 30 ExperimentsHelperTest() { | 32 ExperimentsHelperTest() { |
| 31 // Since the API can only be called on the UI thread, we have to fake that | 33 // Since the API can only be called on the UI thread, we have to fake that |
| 32 // we're on it. | 34 // we're on it. |
| 33 ui_thread_.reset(new content::TestBrowserThread( | 35 ui_thread_.reset(new content::TestBrowserThread( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 {"abcdefghijklmonpqrstuvwxyz", 787728696u}, | 67 {"abcdefghijklmonpqrstuvwxyz", 787728696u}, |
| 66 {"0123456789ABCDEF", 348858318U} | 68 {"0123456789ABCDEF", 348858318U} |
| 67 }; | 69 }; |
| 68 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(known_hashes); ++i) { | 70 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(known_hashes); ++i) { |
| 69 EXPECT_EQ(known_hashes[i].hash_value, | 71 EXPECT_EQ(known_hashes[i].hash_value, |
| 70 testing::TestHashName(known_hashes[i].name)); | 72 testing::TestHashName(known_hashes[i].name)); |
| 71 } | 73 } |
| 72 } | 74 } |
| 73 | 75 |
| 74 TEST_F(ExperimentsHelperTest, GetFieldTrialSelectedGroups) { | 76 TEST_F(ExperimentsHelperTest, GetFieldTrialSelectedGroups) { |
| 75 typedef std::set<experiments_helper::SelectedGroupId, | 77 typedef std::set<SelectedGroupId, SelectedGroupIdCompare> SelectedGroupIdSet; |
| 76 experiments_helper::SelectedGroupIdCompare> SelectedGroupIdSet; | |
| 77 std::string trial_one("trial one"); | 78 std::string trial_one("trial one"); |
| 78 std::string group_one("group one"); | 79 std::string group_one("group one"); |
| 79 std::string trial_two("trial two"); | 80 std::string trial_two("trial two"); |
| 80 std::string group_two("group two"); | 81 std::string group_two("group two"); |
| 81 | 82 |
| 82 base::FieldTrial::SelectedGroups selected_groups; | 83 base::FieldTrial::SelectedGroups selected_groups; |
| 83 base::FieldTrial::SelectedGroup selected_group; | 84 base::FieldTrial::SelectedGroup selected_group; |
| 84 selected_group.trial = trial_one; | 85 selected_group.trial = trial_one; |
| 85 selected_group.group = group_one; | 86 selected_group.group = group_one; |
| 86 selected_groups.push_back(selected_group); | 87 selected_groups.push_back(selected_group); |
| 87 | 88 |
| 88 selected_group.trial = trial_two; | 89 selected_group.trial = trial_two; |
| 89 selected_group.group = group_two; | 90 selected_group.group = group_two; |
| 90 selected_groups.push_back(selected_group); | 91 selected_groups.push_back(selected_group); |
| 91 | 92 |
| 92 // Create our expected groups of IDs. | 93 // Create our expected groups of IDs. |
| 93 SelectedGroupIdSet expected_groups; | 94 SelectedGroupIdSet expected_groups; |
| 94 experiments_helper::SelectedGroupId name_group_id; | 95 SelectedGroupId name_group_id; |
| 95 name_group_id.name = testing::TestHashName(trial_one); | 96 name_group_id.name = testing::TestHashName(trial_one); |
| 96 name_group_id.group = testing::TestHashName(group_one); | 97 name_group_id.group = testing::TestHashName(group_one); |
| 97 expected_groups.insert(name_group_id); | 98 expected_groups.insert(name_group_id); |
| 98 name_group_id.name = testing::TestHashName(trial_two); | 99 name_group_id.name = testing::TestHashName(trial_two); |
| 99 name_group_id.group = testing::TestHashName(group_two); | 100 name_group_id.group = testing::TestHashName(group_two); |
| 100 expected_groups.insert(name_group_id); | 101 expected_groups.insert(name_group_id); |
| 101 | 102 |
| 102 std::vector<experiments_helper::SelectedGroupId> selected_group_ids; | 103 std::vector<SelectedGroupId> selected_group_ids; |
| 103 testing::TestGetFieldTrialSelectedGroupIdsForSelectedGroups( | 104 testing::TestGetFieldTrialSelectedGroupIdsForSelectedGroups( |
| 104 selected_groups, &selected_group_ids); | 105 selected_groups, &selected_group_ids); |
| 105 EXPECT_EQ(2U, selected_group_ids.size()); | 106 EXPECT_EQ(2U, selected_group_ids.size()); |
| 106 for (size_t i = 0; i < selected_group_ids.size(); ++i) { | 107 for (size_t i = 0; i < selected_group_ids.size(); ++i) { |
| 107 SelectedGroupIdSet::iterator expected_group = | 108 SelectedGroupIdSet::iterator expected_group = |
| 108 expected_groups.find(selected_group_ids[i]); | 109 expected_groups.find(selected_group_ids[i]); |
| 109 EXPECT_FALSE(expected_group == expected_groups.end()); | 110 EXPECT_FALSE(expected_group == expected_groups.end()); |
| 110 expected_groups.erase(expected_group); | 111 expected_groups.erase(expected_group); |
| 111 } | 112 } |
| 112 EXPECT_EQ(0U, expected_groups.size()); | 113 EXPECT_EQ(0U, expected_groups.size()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 130 // disabling the FieldTrial actually makes GetGoogleVariationID correctly | 131 // disabling the FieldTrial actually makes GetGoogleVariationID correctly |
| 131 // return the empty ID. | 132 // return the empty ID. |
| 132 TEST_F(ExperimentsHelperTest, DisableAfterInitialization) { | 133 TEST_F(ExperimentsHelperTest, DisableAfterInitialization) { |
| 133 const std::string default_name = "default"; | 134 const std::string default_name = "default"; |
| 134 const std::string non_default_name = "non_default"; | 135 const std::string non_default_name = "non_default"; |
| 135 | 136 |
| 136 scoped_refptr<base::FieldTrial> trial( | 137 scoped_refptr<base::FieldTrial> trial( |
| 137 base::FieldTrialList::FactoryGetFieldTrial("trial", 100, default_name, | 138 base::FieldTrialList::FactoryGetFieldTrial("trial", 100, default_name, |
| 138 next_year_, 12, 12, NULL)); | 139 next_year_, 12, 12, NULL)); |
| 139 trial->AppendGroup(non_default_name, 100); | 140 trial->AppendGroup(non_default_name, 100); |
| 140 experiments_helper::AssociateGoogleVariationID( | 141 AssociateGoogleVariationID( |
| 141 trial->name(), default_name, chrome_variations::kTestValueA); | 142 trial->name(), default_name, chrome_variations::kTestValueA); |
| 142 experiments_helper::AssociateGoogleVariationID( | 143 AssociateGoogleVariationID( |
| 143 trial->name(), non_default_name, chrome_variations::kTestValueB); | 144 trial->name(), non_default_name, chrome_variations::kTestValueB); |
| 144 ASSERT_EQ(non_default_name, trial->group_name()); | 145 ASSERT_EQ(non_default_name, trial->group_name()); |
| 145 ASSERT_EQ(chrome_variations::kTestValueB, GetIDForTrial(trial.get())); | 146 ASSERT_EQ(chrome_variations::kTestValueB, GetIDForTrial(trial.get())); |
| 146 trial->Disable(); | 147 trial->Disable(); |
| 147 ASSERT_EQ(default_name, trial->group_name()); | 148 ASSERT_EQ(default_name, trial->group_name()); |
| 148 ASSERT_EQ(chrome_variations::kTestValueA, GetIDForTrial(trial.get())); | 149 ASSERT_EQ(chrome_variations::kTestValueA, GetIDForTrial(trial.get())); |
| 149 } | 150 } |
| 150 | 151 |
| 151 // Test various successful association cases. | 152 // Test various successful association cases. |
| 152 TEST_F(ExperimentsHelperTest, AssociateGoogleVariationID) { | 153 TEST_F(ExperimentsHelperTest, AssociateGoogleVariationID) { |
| 153 const std::string default_name1 = "default1"; | 154 const std::string default_name1 = "default1"; |
| 154 scoped_refptr<base::FieldTrial> trial_true( | 155 scoped_refptr<base::FieldTrial> trial_true( |
| 155 base::FieldTrialList::FactoryGetFieldTrial("d1", 10, default_name1, | 156 base::FieldTrialList::FactoryGetFieldTrial("d1", 10, default_name1, |
| 156 next_year_, 12, 31, NULL)); | 157 next_year_, 12, 31, NULL)); |
| 157 const std::string winner = "TheWinner"; | 158 const std::string winner = "TheWinner"; |
| 158 int winner_group = trial_true->AppendGroup(winner, 10); | 159 int winner_group = trial_true->AppendGroup(winner, 10); |
| 159 | 160 |
| 160 // Set GoogleVariationIDs so we can verify that they were chosen correctly. | 161 // Set GoogleVariationIDs so we can verify that they were chosen correctly. |
| 161 experiments_helper::AssociateGoogleVariationID( | 162 AssociateGoogleVariationID( |
| 162 trial_true->name(), default_name1, chrome_variations::kTestValueA); | 163 trial_true->name(), default_name1, chrome_variations::kTestValueA); |
| 163 experiments_helper::AssociateGoogleVariationID( | 164 AssociateGoogleVariationID( |
| 164 trial_true->name(), winner, chrome_variations::kTestValueB); | 165 trial_true->name(), winner, chrome_variations::kTestValueB); |
| 165 | 166 |
| 166 EXPECT_EQ(winner_group, trial_true->group()); | 167 EXPECT_EQ(winner_group, trial_true->group()); |
| 167 EXPECT_EQ(winner, trial_true->group_name()); | 168 EXPECT_EQ(winner, trial_true->group_name()); |
| 168 EXPECT_EQ(chrome_variations::kTestValueB, GetIDForTrial(trial_true.get())); | 169 EXPECT_EQ(chrome_variations::kTestValueB, GetIDForTrial(trial_true.get())); |
| 169 | 170 |
| 170 const std::string default_name2 = "default2"; | 171 const std::string default_name2 = "default2"; |
| 171 scoped_refptr<base::FieldTrial> trial_false( | 172 scoped_refptr<base::FieldTrial> trial_false( |
| 172 base::FieldTrialList::FactoryGetFieldTrial("d2", 10, default_name2, | 173 base::FieldTrialList::FactoryGetFieldTrial("d2", 10, default_name2, |
| 173 next_year_, 12, 31, NULL)); | 174 next_year_, 12, 31, NULL)); |
| 174 const std::string loser = "ALoser"; | 175 const std::string loser = "ALoser"; |
| 175 int loser_group = trial_false->AppendGroup(loser, 0); | 176 int loser_group = trial_false->AppendGroup(loser, 0); |
| 176 | 177 |
| 177 experiments_helper::AssociateGoogleVariationID( | 178 AssociateGoogleVariationID( |
| 178 trial_false->name(), default_name2, chrome_variations::kTestValueA); | 179 trial_false->name(), default_name2, chrome_variations::kTestValueA); |
| 179 experiments_helper::AssociateGoogleVariationID( | 180 AssociateGoogleVariationID( |
| 180 trial_false->name(), loser, chrome_variations::kTestValueB); | 181 trial_false->name(), loser, chrome_variations::kTestValueB); |
| 181 | 182 |
| 182 EXPECT_NE(loser_group, trial_false->group()); | 183 EXPECT_NE(loser_group, trial_false->group()); |
| 183 EXPECT_EQ(chrome_variations::kTestValueA, GetIDForTrial(trial_false.get())); | 184 EXPECT_EQ(chrome_variations::kTestValueA, GetIDForTrial(trial_false.get())); |
| 184 } | 185 } |
| 185 | 186 |
| 186 // Test that not associating a FieldTrial with any IDs ensure that the empty ID | 187 // Test that not associating a FieldTrial with any IDs ensure that the empty ID |
| 187 // will be returned. | 188 // will be returned. |
| 188 TEST_F(ExperimentsHelperTest, NoAssociation) { | 189 TEST_F(ExperimentsHelperTest, NoAssociation) { |
| 189 const std::string default_name = "default"; | 190 const std::string default_name = "default"; |
| 190 scoped_refptr<base::FieldTrial> no_id_trial( | 191 scoped_refptr<base::FieldTrial> no_id_trial( |
| 191 base::FieldTrialList::FactoryGetFieldTrial("d3", 10, default_name, | 192 base::FieldTrialList::FactoryGetFieldTrial("d3", 10, default_name, |
| 192 next_year_, 12, 31, NULL)); | 193 next_year_, 12, 31, NULL)); |
| 193 const std::string winner = "TheWinner"; | 194 const std::string winner = "TheWinner"; |
| 194 int winner_group = no_id_trial->AppendGroup(winner, 10); | 195 int winner_group = no_id_trial->AppendGroup(winner, 10); |
| 195 | 196 |
| 196 // Ensure that despite the fact that a normal winner is elected, it does not | 197 // Ensure that despite the fact that a normal winner is elected, it does not |
| 197 // have a valid chrome_variations::ID associated with it. | 198 // have a valid chrome_variations::ID associated with it. |
| 198 EXPECT_EQ(winner_group, no_id_trial->group()); | 199 EXPECT_EQ(winner_group, no_id_trial->group()); |
| 199 EXPECT_EQ(winner, no_id_trial->group_name()); | 200 EXPECT_EQ(winner, no_id_trial->group_name()); |
| 200 EXPECT_EQ(chrome_variations::kEmptyID, GetIDForTrial(no_id_trial.get())); | 201 EXPECT_EQ(chrome_variations::kEmptyID, GetIDForTrial(no_id_trial.get())); |
| 201 } | 202 } |
| 202 | 203 |
| 203 // Ensure that the AssociateGoogleVariationIDForce works as expected. | 204 // Ensure that the AssociateGoogleVariationIDForce works as expected. |
| 204 TEST_F(ExperimentsHelperTest, ForceAssociation) { | 205 TEST_F(ExperimentsHelperTest, ForceAssociation) { |
| 205 EXPECT_EQ(chrome_variations::kEmptyID, | 206 EXPECT_EQ(chrome_variations::kEmptyID, |
| 206 experiments_helper::GetGoogleVariationID("trial", "group")); | 207 GetGoogleVariationID("trial", "group")); |
| 207 experiments_helper::AssociateGoogleVariationID("trial", "group", | 208 AssociateGoogleVariationID("trial", "group", |
| 208 chrome_variations::kTestValueA); | 209 chrome_variations::kTestValueA); |
| 209 EXPECT_EQ(chrome_variations::kTestValueA, | 210 EXPECT_EQ(chrome_variations::kTestValueA, |
| 210 experiments_helper::GetGoogleVariationID("trial", "group")); | 211 GetGoogleVariationID("trial", "group")); |
| 211 experiments_helper::AssociateGoogleVariationID("trial", "group", | 212 AssociateGoogleVariationID("trial", "group", chrome_variations::kTestValueB); |
| 212 chrome_variations::kTestValueB); | |
| 213 EXPECT_EQ(chrome_variations::kTestValueA, | 213 EXPECT_EQ(chrome_variations::kTestValueA, |
| 214 experiments_helper::GetGoogleVariationID("trial", "group")); | 214 GetGoogleVariationID("trial", "group")); |
| 215 experiments_helper::AssociateGoogleVariationIDForce("trial", "group", | 215 AssociateGoogleVariationIDForce("trial", "group", |
| 216 chrome_variations::kTestValueB); | 216 chrome_variations::kTestValueB); |
| 217 EXPECT_EQ(chrome_variations::kTestValueB, | 217 EXPECT_EQ(chrome_variations::kTestValueB, |
| 218 experiments_helper::GetGoogleVariationID("trial", "group")); | 218 GetGoogleVariationID("trial", "group")); |
| 219 } | 219 } |
| 220 |
| 221 TEST_F(ExperimentsHelperTest, GenerateExperimentChunks) { |
| 222 const char* kExperimentStrings[] = { |
| 223 "1d3048f1-9de009d0", |
| 224 "cd73da34-cf196cb", |
| 225 "6214fa18-9e6dc24d", |
| 226 "4dcb0cd6-d31c4ca1", |
| 227 "9d5bce6-30d7d8ac", |
| 228 }; |
| 229 const char* kExpectedChunks1[] = { |
| 230 "1d3048f1-9de009d0", |
| 231 }; |
| 232 const char* kExpectedChunks2[] = { |
| 233 "1d3048f1-9de009d0,cd73da34-cf196cb", |
| 234 }; |
| 235 const char* kExpectedChunks3[] = { |
| 236 "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", |
| 237 }; |
| 238 const char* kExpectedChunks4[] = { |
| 239 "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", |
| 240 "4dcb0cd6-d31c4ca1", |
| 241 }; |
| 242 const char* kExpectedChunks5[] = { |
| 243 "1d3048f1-9de009d0,cd73da34-cf196cb,6214fa18-9e6dc24d", |
| 244 "4dcb0cd6-d31c4ca1,9d5bce6-30d7d8ac", |
| 245 }; |
| 246 |
| 247 struct { |
| 248 size_t strings_length; |
| 249 size_t expected_chunks_length; |
| 250 const char** expected_chunks; |
| 251 } cases[] = { |
| 252 { 0, 0, NULL }, |
| 253 { 1, arraysize(kExpectedChunks1), kExpectedChunks1 }, |
| 254 { 2, arraysize(kExpectedChunks2), kExpectedChunks2 }, |
| 255 { 3, arraysize(kExpectedChunks3), kExpectedChunks3 }, |
| 256 { 4, arraysize(kExpectedChunks4), kExpectedChunks4 }, |
| 257 { 5, arraysize(kExpectedChunks5), kExpectedChunks5 }, |
| 258 }; |
| 259 |
| 260 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |
| 261 ASSERT_LE(cases[i].strings_length, arraysize(kExperimentStrings)); |
| 262 |
| 263 std::vector<string16> experiments; |
| 264 for (size_t j = 0; j < cases[i].strings_length; ++j) |
| 265 experiments.push_back(UTF8ToUTF16(kExperimentStrings[j])); |
| 266 |
| 267 std::vector<string16> chunks; |
| 268 GenerateExperimentChunks(experiments, &chunks); |
| 269 ASSERT_EQ(cases[i].expected_chunks_length, chunks.size()); |
| 270 for (size_t j = 0; j < chunks.size(); ++j) |
| 271 EXPECT_EQ(UTF8ToUTF16(cases[i].expected_chunks[j]), chunks[j]); |
| 272 } |
| 273 } |
| 274 |
| 275 } // namespace experiments_helper |
| OLD | NEW |