| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 #include "components/variations/variations_seed_processor.h" | 5 #include "components/variations/variations_seed_processor.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 #include <memory> | 11 #include <memory> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/feature_list.h" | 17 #include "base/feature_list.h" |
| 18 #include "base/format_macros.h" | 18 #include "base/format_macros.h" |
| 19 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
| 21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 22 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 23 #include "components/variations/processed_study.h" | 23 #include "components/variations/processed_study.h" |
| 24 #include "components/variations/study_filtering.h" |
| 24 #include "components/variations/variations_associated_data.h" | 25 #include "components/variations/variations_associated_data.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 27 |
| 27 namespace variations { | 28 namespace variations { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 // Converts |time| to Study proto format. | 32 // Converts |time| to Study proto format. |
| 32 int64_t TimeToProtoTime(const base::Time& time) { | 33 int64_t TimeToProtoTime(const base::Time& time) { |
| 33 return (time - base::Time::UnixEpoch()).InSeconds(); | 34 return (time - base::Time::UnixEpoch()).InSeconds(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 112 |
| 112 ~VariationsSeedProcessorTest() override { | 113 ~VariationsSeedProcessorTest() override { |
| 113 // Ensure that the maps are cleared between tests, since they are stored as | 114 // Ensure that the maps are cleared between tests, since they are stored as |
| 114 // process singletons. | 115 // process singletons. |
| 115 testing::ClearAllVariationIDs(); | 116 testing::ClearAllVariationIDs(); |
| 116 testing::ClearAllVariationParams(); | 117 testing::ClearAllVariationParams(); |
| 117 | 118 |
| 118 base::FeatureList::ClearInstanceForTesting(); | 119 base::FeatureList::ClearInstanceForTesting(); |
| 119 } | 120 } |
| 120 | 121 |
| 121 bool CreateTrialFromStudy(const Study* study) { | 122 bool CreateTrialFromStudy(const Study& study) { |
| 122 return CreateTrialFromStudyWithFeatureList(study, &feature_list_); | 123 return CreateTrialFromStudyWithFeatureList(study, &feature_list_); |
| 123 } | 124 } |
| 124 | 125 |
| 125 bool CreateTrialFromStudyWithFeatureList(const Study* study, | 126 bool CreateTrialFromStudyWithFeatureList(const Study& study, |
| 126 base::FeatureList* feature_list) { | 127 base::FeatureList* feature_list) { |
| 127 ProcessedStudy processed_study; | 128 ProcessedStudy processed_study; |
| 128 if (processed_study.Init(study, false)) { | 129 const bool is_expired = internal::IsStudyExpired(study, base::Time::Now()); |
| 130 if (processed_study.Init(&study, is_expired)) { |
| 129 VariationsSeedProcessor().CreateTrialFromStudy( | 131 VariationsSeedProcessor().CreateTrialFromStudy( |
| 130 processed_study, override_callback_.callback(), feature_list); | 132 processed_study, override_callback_.callback(), feature_list); |
| 131 return true; | 133 return true; |
| 132 } | 134 } |
| 133 return false; | 135 return false; |
| 134 } | 136 } |
| 135 | 137 |
| 136 protected: | 138 protected: |
| 137 base::FeatureList feature_list_; | 139 base::FeatureList feature_list_; |
| 138 TestOverrideStringCallback override_callback_; | 140 TestOverrideStringCallback override_callback_; |
| 139 | 141 |
| 140 private: | 142 private: |
| 141 DISALLOW_COPY_AND_ASSIGN(VariationsSeedProcessorTest); | 143 DISALLOW_COPY_AND_ASSIGN(VariationsSeedProcessorTest); |
| 142 }; | 144 }; |
| 143 | 145 |
| 144 TEST_F(VariationsSeedProcessorTest, AllowForceGroupAndVariationId) { | 146 TEST_F(VariationsSeedProcessorTest, AllowForceGroupAndVariationId) { |
| 145 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 147 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 146 | 148 |
| 147 base::FieldTrialList field_trial_list(NULL); | 149 base::FieldTrialList field_trial_list(nullptr); |
| 148 | 150 |
| 149 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 151 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 150 study.mutable_experiment(1)->set_google_web_experiment_id(kExperimentId); | 152 study.mutable_experiment(1)->set_google_web_experiment_id(kExperimentId); |
| 151 | 153 |
| 152 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 154 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 153 EXPECT_EQ(kFlagGroup1Name, | 155 EXPECT_EQ(kFlagGroup1Name, |
| 154 base::FieldTrialList::FindFullName(kFlagStudyName)); | 156 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 155 | 157 |
| 156 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName, | 158 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName, |
| 157 kFlagGroup1Name); | 159 kFlagGroup1Name); |
| 158 EXPECT_EQ(kExperimentId, id); | 160 EXPECT_EQ(kExperimentId, id); |
| 159 } | 161 } |
| 160 | 162 |
| 161 // Test that the group for kForcingFlag1 is forced. | 163 // Test that the group for kForcingFlag1 is forced. |
| 162 TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag1) { | 164 TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag1) { |
| 163 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 165 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 164 | 166 |
| 165 base::FieldTrialList field_trial_list(NULL); | 167 base::FieldTrialList field_trial_list(nullptr); |
| 166 | 168 |
| 167 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 169 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 168 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 170 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 169 EXPECT_EQ(kFlagGroup1Name, | 171 EXPECT_EQ(kFlagGroup1Name, |
| 170 base::FieldTrialList::FindFullName(kFlagStudyName)); | 172 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 171 } | 173 } |
| 172 | 174 |
| 173 // Test that the group for kForcingFlag2 is forced. | 175 // Test that the group for kForcingFlag2 is forced. |
| 174 TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag2) { | 176 TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag2) { |
| 175 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2); | 177 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2); |
| 176 | 178 |
| 177 base::FieldTrialList field_trial_list(NULL); | 179 base::FieldTrialList field_trial_list(nullptr); |
| 178 | 180 |
| 179 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 181 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 180 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 182 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 181 EXPECT_EQ(kFlagGroup2Name, | 183 EXPECT_EQ(kFlagGroup2Name, |
| 182 base::FieldTrialList::FindFullName(kFlagStudyName)); | 184 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 183 } | 185 } |
| 184 | 186 |
| 185 TEST_F(VariationsSeedProcessorTest, ForceGroup_ChooseFirstGroupWithFlag) { | 187 TEST_F(VariationsSeedProcessorTest, ForceGroup_ChooseFirstGroupWithFlag) { |
| 186 // Add the flag to the command line arguments so the flag group is forced. | 188 // Add the flag to the command line arguments so the flag group is forced. |
| 187 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 189 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 188 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2); | 190 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag2); |
| 189 | 191 |
| 190 base::FieldTrialList field_trial_list(NULL); | 192 base::FieldTrialList field_trial_list(nullptr); |
| 191 | 193 |
| 192 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 194 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 193 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 195 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 194 EXPECT_EQ(kFlagGroup1Name, | 196 EXPECT_EQ(kFlagGroup1Name, |
| 195 base::FieldTrialList::FindFullName(kFlagStudyName)); | 197 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 196 } | 198 } |
| 197 | 199 |
| 198 TEST_F(VariationsSeedProcessorTest, ForceGroup_DontChooseGroupWithFlag) { | 200 TEST_F(VariationsSeedProcessorTest, ForceGroup_DontChooseGroupWithFlag) { |
| 199 base::FieldTrialList field_trial_list(NULL); | 201 base::FieldTrialList field_trial_list(nullptr); |
| 200 | 202 |
| 201 // The two flag groups are given high probability, which would normally make | 203 // The two flag groups are given high probability, which would normally make |
| 202 // them very likely to be chosen. They won't be chosen since flag groups are | 204 // them very likely to be chosen. They won't be chosen since flag groups are |
| 203 // never chosen when their flag isn't present. | 205 // never chosen when their flag isn't present. |
| 204 Study study = CreateStudyWithFlagGroups(1, 999, 999); | 206 Study study = CreateStudyWithFlagGroups(1, 999, 999); |
| 205 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 207 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 206 EXPECT_EQ(kNonFlagGroupName, | 208 EXPECT_EQ(kNonFlagGroupName, |
| 207 base::FieldTrialList::FindFullName(kFlagStudyName)); | 209 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 208 } | 210 } |
| 209 | 211 |
| 210 TEST_F(VariationsSeedProcessorTest, | 212 TEST_F(VariationsSeedProcessorTest, |
| 211 NonExpiredStudyPrioritizedOverExpiredStudy) { | 213 NonExpiredStudyPrioritizedOverExpiredStudy) { |
| 212 VariationsSeedProcessor seed_processor; | 214 VariationsSeedProcessor seed_processor; |
| 213 | 215 |
| 214 const std::string kTrialName = "A"; | 216 const std::string kTrialName = "A"; |
| 215 const std::string kGroup1Name = "Group1"; | 217 const std::string kGroup1Name = "Group1"; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 226 | 228 |
| 227 const base::Time year_ago = | 229 const base::Time year_ago = |
| 228 base::Time::Now() - base::TimeDelta::FromDays(365); | 230 base::Time::Now() - base::TimeDelta::FromDays(365); |
| 229 | 231 |
| 230 const base::Version version("20.0.0.0"); | 232 const base::Version version("20.0.0.0"); |
| 231 | 233 |
| 232 // Check that adding [expired, non-expired] activates the non-expired one. | 234 // Check that adding [expired, non-expired] activates the non-expired one. |
| 233 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName)); | 235 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName)); |
| 234 { | 236 { |
| 235 base::FeatureList feature_list; | 237 base::FeatureList feature_list; |
| 236 base::FieldTrialList field_trial_list(NULL); | 238 base::FieldTrialList field_trial_list(nullptr); |
| 237 study1->set_expiry_date(TimeToProtoTime(year_ago)); | 239 study1->set_expiry_date(TimeToProtoTime(year_ago)); |
| 238 seed_processor.CreateTrialsFromSeed( | 240 seed_processor.CreateTrialsFromSeed( |
| 239 seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE, | 241 seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE, |
| 240 Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(), | 242 Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(), |
| 241 &feature_list); | 243 &feature_list); |
| 242 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName)); | 244 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName)); |
| 243 } | 245 } |
| 244 | 246 |
| 245 // Check that adding [non-expired, expired] activates the non-expired one. | 247 // Check that adding [non-expired, expired] activates the non-expired one. |
| 246 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName)); | 248 ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName)); |
| 247 { | 249 { |
| 248 base::FeatureList feature_list; | 250 base::FeatureList feature_list; |
| 249 base::FieldTrialList field_trial_list(NULL); | 251 base::FieldTrialList field_trial_list(nullptr); |
| 250 study1->clear_expiry_date(); | 252 study1->clear_expiry_date(); |
| 251 study2->set_expiry_date(TimeToProtoTime(year_ago)); | 253 study2->set_expiry_date(TimeToProtoTime(year_ago)); |
| 252 seed_processor.CreateTrialsFromSeed( | 254 seed_processor.CreateTrialsFromSeed( |
| 253 seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE, | 255 seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE, |
| 254 Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(), | 256 Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(), |
| 255 &feature_list); | 257 &feature_list); |
| 256 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName)); | 258 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName)); |
| 257 } | 259 } |
| 258 } | 260 } |
| 259 | 261 |
| 260 TEST_F(VariationsSeedProcessorTest, OverrideUIStrings) { | 262 TEST_F(VariationsSeedProcessorTest, OverrideUIStrings) { |
| 261 base::FieldTrialList field_trial_list(NULL); | 263 base::FieldTrialList field_trial_list(nullptr); |
| 262 | 264 |
| 263 Study study; | 265 Study study; |
| 264 study.set_name("Study1"); | 266 study.set_name("Study1"); |
| 265 study.set_default_experiment_name("B"); | 267 study.set_default_experiment_name("B"); |
| 266 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); | 268 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); |
| 267 | 269 |
| 268 Study_Experiment* experiment1 = AddExperiment("A", 0, &study); | 270 Study_Experiment* experiment1 = AddExperiment("A", 0, &study); |
| 269 Study_Experiment_OverrideUIString* override = | 271 Study_Experiment_OverrideUIString* override = |
| 270 experiment1->add_override_ui_string(); | 272 experiment1->add_override_ui_string(); |
| 271 | 273 |
| 272 override->set_name_hash(1234); | 274 override->set_name_hash(1234); |
| 273 override->set_value("test"); | 275 override->set_value("test"); |
| 274 | 276 |
| 275 Study_Experiment* experiment2 = AddExperiment("B", 1, &study); | 277 Study_Experiment* experiment2 = AddExperiment("B", 1, &study); |
| 276 | 278 |
| 277 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 279 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 278 | 280 |
| 279 const TestOverrideStringCallback::OverrideMap& overrides = | 281 const TestOverrideStringCallback::OverrideMap& overrides = |
| 280 override_callback_.overrides(); | 282 override_callback_.overrides(); |
| 281 | 283 |
| 282 EXPECT_TRUE(overrides.empty()); | 284 EXPECT_TRUE(overrides.empty()); |
| 283 | 285 |
| 284 study.set_name("Study2"); | 286 study.set_name("Study2"); |
| 285 experiment1->set_probability_weight(1); | 287 experiment1->set_probability_weight(1); |
| 286 experiment2->set_probability_weight(0); | 288 experiment2->set_probability_weight(0); |
| 287 | 289 |
| 288 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 290 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 289 | 291 |
| 290 EXPECT_EQ(1u, overrides.size()); | 292 EXPECT_EQ(1u, overrides.size()); |
| 291 TestOverrideStringCallback::OverrideMap::const_iterator it = | 293 TestOverrideStringCallback::OverrideMap::const_iterator it = |
| 292 overrides.find(1234); | 294 overrides.find(1234); |
| 293 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second); | 295 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second); |
| 294 } | 296 } |
| 295 | 297 |
| 296 TEST_F(VariationsSeedProcessorTest, OverrideUIStringsWithForcingFlag) { | 298 TEST_F(VariationsSeedProcessorTest, OverrideUIStringsWithForcingFlag) { |
| 297 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 299 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 298 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag()); | 300 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag()); |
| 299 | 301 |
| 300 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); | 302 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); |
| 301 Study_Experiment_OverrideUIString* override = | 303 Study_Experiment_OverrideUIString* override = |
| 302 study.mutable_experiment(1)->add_override_ui_string(); | 304 study.mutable_experiment(1)->add_override_ui_string(); |
| 303 override->set_name_hash(1234); | 305 override->set_name_hash(1234); |
| 304 override->set_value("test"); | 306 override->set_value("test"); |
| 305 | 307 |
| 306 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 308 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 307 base::FieldTrialList field_trial_list(NULL); | 309 base::FieldTrialList field_trial_list(nullptr); |
| 308 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 310 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 309 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name())); | 311 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name())); |
| 310 | 312 |
| 311 const TestOverrideStringCallback::OverrideMap& overrides = | 313 const TestOverrideStringCallback::OverrideMap& overrides = |
| 312 override_callback_.overrides(); | 314 override_callback_.overrides(); |
| 313 EXPECT_EQ(1u, overrides.size()); | 315 EXPECT_EQ(1u, overrides.size()); |
| 314 TestOverrideStringCallback::OverrideMap::const_iterator it = | 316 TestOverrideStringCallback::OverrideMap::const_iterator it = |
| 315 overrides.find(1234); | 317 overrides.find(1234); |
| 316 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second); | 318 EXPECT_EQ(base::ASCIIToUTF16("test"), it->second); |
| 317 } | 319 } |
| 318 | 320 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 AddExperiment("def", 0, &study2); | 430 AddExperiment("def", 0, &study2); |
| 429 AddExperiment("xyz", 34, &study2); | 431 AddExperiment("xyz", 34, &study2); |
| 430 EXPECT_TRUE(processed_study.Init(&study2, false)); | 432 EXPECT_TRUE(processed_study.Init(&study2, false)); |
| 431 EXPECT_TRUE(processed_study.all_assignments_to_one_group()); | 433 EXPECT_TRUE(processed_study.all_assignments_to_one_group()); |
| 432 AddExperiment("abc", 12, &study2); | 434 AddExperiment("abc", 12, &study2); |
| 433 EXPECT_TRUE(processed_study.Init(&study2, false)); | 435 EXPECT_TRUE(processed_study.Init(&study2, false)); |
| 434 EXPECT_FALSE(processed_study.all_assignments_to_one_group()); | 436 EXPECT_FALSE(processed_study.all_assignments_to_one_group()); |
| 435 } | 437 } |
| 436 | 438 |
| 437 TEST_F(VariationsSeedProcessorTest, VariationParams) { | 439 TEST_F(VariationsSeedProcessorTest, VariationParams) { |
| 438 base::FieldTrialList field_trial_list(NULL); | 440 base::FieldTrialList field_trial_list(nullptr); |
| 439 | 441 |
| 440 Study study; | 442 Study study; |
| 441 study.set_name("Study1"); | 443 study.set_name("Study1"); |
| 442 study.set_default_experiment_name("B"); | 444 study.set_default_experiment_name("B"); |
| 443 | 445 |
| 444 Study_Experiment* experiment1 = AddExperiment("A", 1, &study); | 446 Study_Experiment* experiment1 = AddExperiment("A", 1, &study); |
| 445 Study_Experiment_Param* param = experiment1->add_param(); | 447 Study_Experiment_Param* param = experiment1->add_param(); |
| 446 param->set_name("x"); | 448 param->set_name("x"); |
| 447 param->set_value("y"); | 449 param->set_value("y"); |
| 448 | 450 |
| 449 Study_Experiment* experiment2 = AddExperiment("B", 0, &study); | 451 Study_Experiment* experiment2 = AddExperiment("B", 0, &study); |
| 450 | 452 |
| 451 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 453 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 452 EXPECT_EQ("y", GetVariationParamValue("Study1", "x")); | 454 EXPECT_EQ("y", GetVariationParamValue("Study1", "x")); |
| 453 | 455 |
| 454 study.set_name("Study2"); | 456 study.set_name("Study2"); |
| 455 experiment1->set_probability_weight(0); | 457 experiment1->set_probability_weight(0); |
| 456 experiment2->set_probability_weight(1); | 458 experiment2->set_probability_weight(1); |
| 457 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 459 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 458 EXPECT_EQ(std::string(), GetVariationParamValue("Study2", "x")); | 460 EXPECT_EQ(std::string(), GetVariationParamValue("Study2", "x")); |
| 459 } | 461 } |
| 460 | 462 |
| 461 TEST_F(VariationsSeedProcessorTest, VariationParamsWithForcingFlag) { | 463 TEST_F(VariationsSeedProcessorTest, VariationParamsWithForcingFlag) { |
| 462 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 464 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 463 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag()); | 465 ASSERT_EQ(kForcingFlag1, study.experiment(1).forcing_flag()); |
| 464 Study_Experiment_Param* param = study.mutable_experiment(1)->add_param(); | 466 Study_Experiment_Param* param = study.mutable_experiment(1)->add_param(); |
| 465 param->set_name("x"); | 467 param->set_name("x"); |
| 466 param->set_value("y"); | 468 param->set_value("y"); |
| 467 | 469 |
| 468 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 470 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 469 base::FieldTrialList field_trial_list(NULL); | 471 base::FieldTrialList field_trial_list(nullptr); |
| 470 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 472 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 471 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name())); | 473 EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study.name())); |
| 472 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x")); | 474 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x")); |
| 473 } | 475 } |
| 474 | 476 |
| 475 TEST_F(VariationsSeedProcessorTest, StartsActive) { | 477 TEST_F(VariationsSeedProcessorTest, StartsActive) { |
| 476 base::FieldTrialList field_trial_list(NULL); | 478 base::FieldTrialList field_trial_list(nullptr); |
| 477 | 479 |
| 478 VariationsSeed seed; | 480 VariationsSeed seed; |
| 479 Study* study1 = seed.add_study(); | 481 Study* study1 = seed.add_study(); |
| 480 study1->set_name("A"); | 482 study1->set_name("A"); |
| 481 study1->set_default_experiment_name("Default"); | 483 study1->set_default_experiment_name("Default"); |
| 482 AddExperiment("AA", 100, study1); | 484 AddExperiment("AA", 100, study1); |
| 483 AddExperiment("Default", 0, study1); | 485 AddExperiment("Default", 0, study1); |
| 484 | 486 |
| 485 Study* study2 = seed.add_study(); | 487 Study* study2 = seed.add_study(); |
| 486 study2->set_name("B"); | 488 study2->set_name("B"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 514 | 516 |
| 515 // Now, all studies should be active. | 517 // Now, all studies should be active. |
| 516 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("A")); | 518 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("A")); |
| 517 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("B")); | 519 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("B")); |
| 518 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("C")); | 520 EXPECT_TRUE(base::FieldTrialList::IsTrialActive("C")); |
| 519 } | 521 } |
| 520 | 522 |
| 521 TEST_F(VariationsSeedProcessorTest, StartsActiveWithFlag) { | 523 TEST_F(VariationsSeedProcessorTest, StartsActiveWithFlag) { |
| 522 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 524 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 523 | 525 |
| 524 base::FieldTrialList field_trial_list(NULL); | 526 base::FieldTrialList field_trial_list(nullptr); |
| 525 | 527 |
| 526 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 528 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 527 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); | 529 study.set_activation_type(Study_ActivationType_ACTIVATION_AUTO); |
| 528 | 530 |
| 529 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 531 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 530 EXPECT_TRUE(base::FieldTrialList::IsTrialActive(kFlagStudyName)); | 532 EXPECT_TRUE(base::FieldTrialList::IsTrialActive(kFlagStudyName)); |
| 531 | 533 |
| 532 EXPECT_EQ(kFlagGroup1Name, | 534 EXPECT_EQ(kFlagGroup1Name, |
| 533 base::FieldTrialList::FindFullName(kFlagStudyName)); | 535 base::FieldTrialList::FindFullName(kFlagStudyName)); |
| 534 } | 536 } |
| 535 | 537 |
| 536 TEST_F(VariationsSeedProcessorTest, ForcingFlagAlreadyForced) { | 538 TEST_F(VariationsSeedProcessorTest, ForcingFlagAlreadyForced) { |
| 537 Study study = CreateStudyWithFlagGroups(100, 0, 0); | 539 Study study = CreateStudyWithFlagGroups(100, 0, 0); |
| 538 ASSERT_EQ(kNonFlagGroupName, study.experiment(0).name()); | 540 ASSERT_EQ(kNonFlagGroupName, study.experiment(0).name()); |
| 539 Study_Experiment_Param* param = study.mutable_experiment(0)->add_param(); | 541 Study_Experiment_Param* param = study.mutable_experiment(0)->add_param(); |
| 540 param->set_name("x"); | 542 param->set_name("x"); |
| 541 param->set_value("y"); | 543 param->set_value("y"); |
| 542 study.mutable_experiment(0)->set_google_web_experiment_id(kExperimentId); | 544 study.mutable_experiment(0)->set_google_web_experiment_id(kExperimentId); |
| 543 | 545 |
| 544 base::FieldTrialList field_trial_list(NULL); | 546 base::FieldTrialList field_trial_list(nullptr); |
| 545 base::FieldTrialList::CreateFieldTrial(kFlagStudyName, kNonFlagGroupName); | 547 base::FieldTrialList::CreateFieldTrial(kFlagStudyName, kNonFlagGroupName); |
| 546 | 548 |
| 547 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); | 549 base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); |
| 548 EXPECT_TRUE(CreateTrialFromStudy(&study)); | 550 EXPECT_TRUE(CreateTrialFromStudy(study)); |
| 549 // The previously forced experiment should still hold. | 551 // The previously forced experiment should still hold. |
| 550 EXPECT_EQ(kNonFlagGroupName, | 552 EXPECT_EQ(kNonFlagGroupName, |
| 551 base::FieldTrialList::FindFullName(study.name())); | 553 base::FieldTrialList::FindFullName(study.name())); |
| 552 | 554 |
| 553 // Check that params and experiment ids correspond. | 555 // Check that params and experiment ids correspond. |
| 554 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x")); | 556 EXPECT_EQ("y", GetVariationParamValue(study.name(), "x")); |
| 555 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName, | 557 VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, kFlagStudyName, |
| 556 kNonFlagGroupName); | 558 kNonFlagGroupName); |
| 557 EXPECT_EQ(kExperimentId, id); | 559 EXPECT_EQ(kExperimentId, id); |
| 558 } | 560 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 578 {kFeatureOnByDefault.name, nullptr, false, true}, | 580 {kFeatureOnByDefault.name, nullptr, false, true}, |
| 579 {kFeatureOffByDefault.name, nullptr, true, true}, | 581 {kFeatureOffByDefault.name, nullptr, true, true}, |
| 580 {nullptr, kFeatureOnByDefault.name, false, false}, | 582 {nullptr, kFeatureOnByDefault.name, false, false}, |
| 581 {nullptr, kFeatureOffByDefault.name, false, true}, | 583 {nullptr, kFeatureOffByDefault.name, false, true}, |
| 582 }; | 584 }; |
| 583 | 585 |
| 584 for (size_t i = 0; i < arraysize(test_cases); i++) { | 586 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 585 const auto& test_case = test_cases[i]; | 587 const auto& test_case = test_cases[i]; |
| 586 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); | 588 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); |
| 587 | 589 |
| 588 base::FieldTrialList field_trial_list(NULL); | 590 base::FieldTrialList field_trial_list(nullptr); |
| 589 base::FeatureList::ClearInstanceForTesting(); | 591 base::FeatureList::ClearInstanceForTesting(); |
| 590 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 592 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 591 | 593 |
| 592 Study study; | 594 Study study; |
| 593 study.set_name("Study1"); | 595 study.set_name("Study1"); |
| 594 study.set_default_experiment_name("B"); | 596 study.set_default_experiment_name("B"); |
| 595 AddExperiment("B", 0, &study); | 597 AddExperiment("B", 0, &study); |
| 596 | 598 |
| 597 Study_Experiment* experiment = AddExperiment("A", 1, &study); | 599 Study_Experiment* experiment = AddExperiment("A", 1, &study); |
| 598 Study_Experiment_FeatureAssociation* association = | 600 Study_Experiment_FeatureAssociation* association = |
| 599 experiment->mutable_feature_association(); | 601 experiment->mutable_feature_association(); |
| 600 if (test_case.enable_feature) | 602 if (test_case.enable_feature) |
| 601 association->add_enable_feature(test_case.enable_feature); | 603 association->add_enable_feature(test_case.enable_feature); |
| 602 else if (test_case.disable_feature) | 604 else if (test_case.disable_feature) |
| 603 association->add_disable_feature(test_case.disable_feature); | 605 association->add_disable_feature(test_case.disable_feature); |
| 604 | 606 |
| 605 EXPECT_TRUE( | 607 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 606 CreateTrialFromStudyWithFeatureList(&study, feature_list.get())); | |
| 607 base::FeatureList::SetInstance(std::move(feature_list)); | 608 base::FeatureList::SetInstance(std::move(feature_list)); |
| 608 | 609 |
| 609 // |kUnrelatedFeature| should not be affected. | 610 // |kUnrelatedFeature| should not be affected. |
| 610 EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature)); | 611 EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature)); |
| 611 | 612 |
| 612 // Before the associated feature is queried, the trial shouldn't be active. | 613 // Before the associated feature is queried, the trial shouldn't be active. |
| 613 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); | 614 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); |
| 614 | 615 |
| 615 EXPECT_EQ(test_case.expected_feature_off_state, | 616 EXPECT_EQ(test_case.expected_feature_off_state, |
| 616 base::FeatureList::IsEnabled(kFeatureOffByDefault)); | 617 base::FeatureList::IsEnabled(kFeatureOffByDefault)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 }; | 703 }; |
| 703 | 704 |
| 704 for (size_t i = 0; i < arraysize(test_cases); i++) { | 705 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 705 const auto& test_case = test_cases[i]; | 706 const auto& test_case = test_cases[i]; |
| 706 const int group = test_case.one_hundred_percent_group; | 707 const int group = test_case.one_hundred_percent_group; |
| 707 SCOPED_TRACE(base::StringPrintf( | 708 SCOPED_TRACE(base::StringPrintf( |
| 708 "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name, | 709 "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name, |
| 709 test_case.enable_features_command_line, | 710 test_case.enable_features_command_line, |
| 710 test_case.disable_features_command_line, static_cast<int>(group))); | 711 test_case.disable_features_command_line, static_cast<int>(group))); |
| 711 | 712 |
| 712 base::FieldTrialList field_trial_list(NULL); | 713 base::FieldTrialList field_trial_list(nullptr); |
| 713 base::FeatureList::ClearInstanceForTesting(); | 714 base::FeatureList::ClearInstanceForTesting(); |
| 714 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 715 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 715 feature_list->InitializeFromCommandLine( | 716 feature_list->InitializeFromCommandLine( |
| 716 test_case.enable_features_command_line, | 717 test_case.enable_features_command_line, |
| 717 test_case.disable_features_command_line); | 718 test_case.disable_features_command_line); |
| 718 | 719 |
| 719 Study study; | 720 Study study; |
| 720 study.set_name("Study1"); | 721 study.set_name("Study1"); |
| 721 study.set_default_experiment_name("Default"); | 722 study.set_default_experiment_name(kDefaultGroup); |
| 722 AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study); | 723 AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study); |
| 723 | 724 |
| 724 Study_Experiment* feature_enable = | 725 Study_Experiment* feature_enable = |
| 725 AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study); | 726 AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study); |
| 726 feature_enable->mutable_feature_association()->add_enable_feature( | 727 feature_enable->mutable_feature_association()->add_enable_feature( |
| 727 test_case.feature.name); | 728 test_case.feature.name); |
| 728 | 729 |
| 729 Study_Experiment* feature_disable = | 730 Study_Experiment* feature_disable = |
| 730 AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study); | 731 AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study); |
| 731 feature_disable->mutable_feature_association()->add_disable_feature( | 732 feature_disable->mutable_feature_association()->add_disable_feature( |
| 732 test_case.feature.name); | 733 test_case.feature.name); |
| 733 | 734 |
| 734 AddExperiment(kForcedOnGroup, 0, &study) | 735 AddExperiment(kForcedOnGroup, 0, &study) |
| 735 ->mutable_feature_association() | 736 ->mutable_feature_association() |
| 736 ->set_forcing_feature_on(test_case.feature.name); | 737 ->set_forcing_feature_on(test_case.feature.name); |
| 737 AddExperiment(kForcedOffGroup, 0, &study) | 738 AddExperiment(kForcedOffGroup, 0, &study) |
| 738 ->mutable_feature_association() | 739 ->mutable_feature_association() |
| 739 ->set_forcing_feature_off(test_case.feature.name); | 740 ->set_forcing_feature_off(test_case.feature.name); |
| 740 | 741 |
| 741 EXPECT_TRUE( | 742 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 742 CreateTrialFromStudyWithFeatureList(&study, feature_list.get())); | |
| 743 base::FeatureList::SetInstance(std::move(feature_list)); | 743 base::FeatureList::SetInstance(std::move(feature_list)); |
| 744 | 744 |
| 745 // Trial should not be activated initially, but later might get activated | 745 // Trial should not be activated initially, but later might get activated |
| 746 // depending on the expected values. | 746 // depending on the expected values. |
| 747 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); | 747 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); |
| 748 EXPECT_EQ(test_case.expected_feature_state, | 748 EXPECT_EQ(test_case.expected_feature_state, |
| 749 base::FeatureList::IsEnabled(test_case.feature)); | 749 base::FeatureList::IsEnabled(test_case.feature)); |
| 750 EXPECT_EQ(test_case.expected_trial_activated, | 750 EXPECT_EQ(test_case.expected_trial_activated, |
| 751 base::FieldTrialList::IsTrialActive(study.name())); | 751 base::FieldTrialList::IsTrialActive(study.name())); |
| 752 } | 752 } |
| 753 } | 753 } |
| 754 | 754 |
| 755 TEST_F(VariationsSeedProcessorTest, FeaturesInExpiredStudies) { |
| 756 struct base::Feature kDisabledFeature { |
| 757 "kDisabledFeature", base::FEATURE_DISABLED_BY_DEFAULT |
| 758 }; |
| 759 struct base::Feature kEnabledFeature { |
| 760 "kEnabledFeature", base::FEATURE_ENABLED_BY_DEFAULT |
| 761 }; |
| 762 const base::Time now = base::Time::Now(); |
| 763 const base::Time year_ago = now - base::TimeDelta::FromDays(365); |
| 764 const base::Time year_later = now + base::TimeDelta::FromDays(365); |
| 765 |
| 766 struct { |
| 767 const base::Feature& feature; |
| 768 bool study_force_feature_state; |
| 769 base::Time expiry_date; |
| 770 bool expected_feature_enabled; |
| 771 } test_cases[] = { |
| 772 {kDisabledFeature, true, year_ago, false}, |
| 773 {kDisabledFeature, true, year_later, true}, |
| 774 {kEnabledFeature, false, year_ago, true}, |
| 775 {kEnabledFeature, false, year_later, false}, |
| 776 }; |
| 777 |
| 778 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 779 const auto& test_case = test_cases[i]; |
| 780 SCOPED_TRACE( |
| 781 base::StringPrintf("Test[%" PRIuS "]: %s", i, test_case.feature.name)); |
| 782 |
| 783 base::FieldTrialList field_trial_list(nullptr); |
| 784 base::FeatureList::ClearInstanceForTesting(); |
| 785 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 786 feature_list->InitializeFromCommandLine(std::string(), std::string()); |
| 787 |
| 788 // Expired study with a 100% feature group and a default group that has no |
| 789 // feature association. |
| 790 Study study; |
| 791 study.set_name("Study1"); |
| 792 study.set_default_experiment_name("Default"); |
| 793 |
| 794 study.set_expiry_date(TimeToProtoTime(test_case.expiry_date)); |
| 795 |
| 796 AddExperiment("Default", 0, &study); |
| 797 Study_Experiment* feature_experiment = AddExperiment("Feature", 1, &study); |
| 798 if (test_case.study_force_feature_state) { |
| 799 feature_experiment->mutable_feature_association()->add_enable_feature( |
| 800 test_case.feature.name); |
| 801 } else { |
| 802 feature_experiment->mutable_feature_association()->add_disable_feature( |
| 803 test_case.feature.name); |
| 804 } |
| 805 |
| 806 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 807 base::FeatureList::SetInstance(std::move(feature_list)); |
| 808 |
| 809 // Tthe feature should not be enabled, because the study is expired. |
| 810 EXPECT_EQ(test_case.expected_feature_enabled, |
| 811 base::FeatureList::IsEnabled(test_case.feature)); |
| 812 } |
| 813 } |
| 814 |
| 755 } // namespace variations | 815 } // namespace variations |
| OLD | NEW |