| 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 "base/test/mock_entropy_provider.h" | 23 #include "base/test/mock_entropy_provider.h" |
| 24 #include "base/test/scoped_feature_list.h" |
| 24 #include "components/variations/processed_study.h" | 25 #include "components/variations/processed_study.h" |
| 25 #include "components/variations/study_filtering.h" | 26 #include "components/variations/study_filtering.h" |
| 26 #include "components/variations/variations_associated_data.h" | 27 #include "components/variations/variations_associated_data.h" |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
| 28 | 29 |
| 29 namespace variations { | 30 namespace variations { |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 // Converts |time| to Study proto format. | 34 // Converts |time| to Study proto format. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 class VariationsSeedProcessorTest : public ::testing::Test { | 111 class VariationsSeedProcessorTest : public ::testing::Test { |
| 111 public: | 112 public: |
| 112 VariationsSeedProcessorTest() { | 113 VariationsSeedProcessorTest() { |
| 113 } | 114 } |
| 114 | 115 |
| 115 ~VariationsSeedProcessorTest() override { | 116 ~VariationsSeedProcessorTest() override { |
| 116 // Ensure that the maps are cleared between tests, since they are stored as | 117 // Ensure that the maps are cleared between tests, since they are stored as |
| 117 // process singletons. | 118 // process singletons. |
| 118 testing::ClearAllVariationIDs(); | 119 testing::ClearAllVariationIDs(); |
| 119 testing::ClearAllVariationParams(); | 120 testing::ClearAllVariationParams(); |
| 120 | |
| 121 base::FeatureList::ClearInstanceForTesting(); | |
| 122 } | 121 } |
| 123 | 122 |
| 124 bool CreateTrialFromStudy(const Study& study) { | 123 bool CreateTrialFromStudy(const Study& study) { |
| 125 return CreateTrialFromStudyWithFeatureListAndEntropyOverride( | 124 return CreateTrialFromStudyWithFeatureListAndEntropyOverride( |
| 126 study, nullptr, &feature_list_); | 125 study, nullptr, &feature_list_); |
| 127 } | 126 } |
| 128 | 127 |
| 129 bool CreateTrialFromStudyWithEntropyOverride( | 128 bool CreateTrialFromStudyWithEntropyOverride( |
| 130 const Study& study, | 129 const Study& study, |
| 131 const base::FieldTrial::EntropyProvider* override_entropy_provider) { | 130 const base::FieldTrial::EntropyProvider* override_entropy_provider) { |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 {kFeatureOffByDefault.name, nullptr, true, true}, | 613 {kFeatureOffByDefault.name, nullptr, true, true}, |
| 615 {nullptr, kFeatureOnByDefault.name, false, false}, | 614 {nullptr, kFeatureOnByDefault.name, false, false}, |
| 616 {nullptr, kFeatureOffByDefault.name, false, true}, | 615 {nullptr, kFeatureOffByDefault.name, false, true}, |
| 617 }; | 616 }; |
| 618 | 617 |
| 619 for (size_t i = 0; i < arraysize(test_cases); i++) { | 618 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 620 const auto& test_case = test_cases[i]; | 619 const auto& test_case = test_cases[i]; |
| 621 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); | 620 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); |
| 622 | 621 |
| 623 base::FieldTrialList field_trial_list(nullptr); | 622 base::FieldTrialList field_trial_list(nullptr); |
| 624 base::FeatureList::ClearInstanceForTesting(); | |
| 625 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 623 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 626 | 624 |
| 627 Study study; | 625 Study study; |
| 628 study.set_name("Study1"); | 626 study.set_name("Study1"); |
| 629 study.set_default_experiment_name("B"); | 627 study.set_default_experiment_name("B"); |
| 630 AddExperiment("B", 0, &study); | 628 AddExperiment("B", 0, &study); |
| 631 | 629 |
| 632 Study_Experiment* experiment = AddExperiment("A", 1, &study); | 630 Study_Experiment* experiment = AddExperiment("A", 1, &study); |
| 633 Study_Experiment_FeatureAssociation* association = | 631 Study_Experiment_FeatureAssociation* association = |
| 634 experiment->mutable_feature_association(); | 632 experiment->mutable_feature_association(); |
| 635 if (test_case.enable_feature) | 633 if (test_case.enable_feature) |
| 636 association->add_enable_feature(test_case.enable_feature); | 634 association->add_enable_feature(test_case.enable_feature); |
| 637 else if (test_case.disable_feature) | 635 else if (test_case.disable_feature) |
| 638 association->add_disable_feature(test_case.disable_feature); | 636 association->add_disable_feature(test_case.disable_feature); |
| 639 | 637 |
| 640 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); | 638 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 641 base::FeatureList::SetInstance(std::move(feature_list)); | 639 base::test::ScopedFeatureList scoped_feature_list; |
| 640 scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| 642 | 641 |
| 643 // |kUnrelatedFeature| should not be affected. | 642 // |kUnrelatedFeature| should not be affected. |
| 644 EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature)); | 643 EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature)); |
| 645 | 644 |
| 646 // Before the associated feature is queried, the trial shouldn't be active. | 645 // Before the associated feature is queried, the trial shouldn't be active. |
| 647 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); | 646 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); |
| 648 | 647 |
| 649 EXPECT_EQ(test_case.expected_feature_off_state, | 648 EXPECT_EQ(test_case.expected_feature_off_state, |
| 650 base::FeatureList::IsEnabled(kFeatureOffByDefault)); | 649 base::FeatureList::IsEnabled(kFeatureOffByDefault)); |
| 651 EXPECT_EQ(test_case.expected_feature_on_state, | 650 EXPECT_EQ(test_case.expected_feature_on_state, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 | 736 |
| 738 for (size_t i = 0; i < arraysize(test_cases); i++) { | 737 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 739 const auto& test_case = test_cases[i]; | 738 const auto& test_case = test_cases[i]; |
| 740 const int group = test_case.one_hundred_percent_group; | 739 const int group = test_case.one_hundred_percent_group; |
| 741 SCOPED_TRACE(base::StringPrintf( | 740 SCOPED_TRACE(base::StringPrintf( |
| 742 "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name, | 741 "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name, |
| 743 test_case.enable_features_command_line, | 742 test_case.enable_features_command_line, |
| 744 test_case.disable_features_command_line, static_cast<int>(group))); | 743 test_case.disable_features_command_line, static_cast<int>(group))); |
| 745 | 744 |
| 746 base::FieldTrialList field_trial_list(nullptr); | 745 base::FieldTrialList field_trial_list(nullptr); |
| 747 base::FeatureList::ClearInstanceForTesting(); | |
| 748 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 746 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 749 feature_list->InitializeFromCommandLine( | 747 feature_list->InitializeFromCommandLine( |
| 750 test_case.enable_features_command_line, | 748 test_case.enable_features_command_line, |
| 751 test_case.disable_features_command_line); | 749 test_case.disable_features_command_line); |
| 752 | 750 |
| 753 Study study; | 751 Study study; |
| 754 study.set_name("Study1"); | 752 study.set_name("Study1"); |
| 755 study.set_default_experiment_name(kDefaultGroup); | 753 study.set_default_experiment_name(kDefaultGroup); |
| 756 AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study); | 754 AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study); |
| 757 | 755 |
| 758 Study_Experiment* feature_enable = | 756 Study_Experiment* feature_enable = |
| 759 AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study); | 757 AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study); |
| 760 feature_enable->mutable_feature_association()->add_enable_feature( | 758 feature_enable->mutable_feature_association()->add_enable_feature( |
| 761 test_case.feature.name); | 759 test_case.feature.name); |
| 762 | 760 |
| 763 Study_Experiment* feature_disable = | 761 Study_Experiment* feature_disable = |
| 764 AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study); | 762 AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study); |
| 765 feature_disable->mutable_feature_association()->add_disable_feature( | 763 feature_disable->mutable_feature_association()->add_disable_feature( |
| 766 test_case.feature.name); | 764 test_case.feature.name); |
| 767 | 765 |
| 768 AddExperiment(kForcedOnGroup, 0, &study) | 766 AddExperiment(kForcedOnGroup, 0, &study) |
| 769 ->mutable_feature_association() | 767 ->mutable_feature_association() |
| 770 ->set_forcing_feature_on(test_case.feature.name); | 768 ->set_forcing_feature_on(test_case.feature.name); |
| 771 AddExperiment(kForcedOffGroup, 0, &study) | 769 AddExperiment(kForcedOffGroup, 0, &study) |
| 772 ->mutable_feature_association() | 770 ->mutable_feature_association() |
| 773 ->set_forcing_feature_off(test_case.feature.name); | 771 ->set_forcing_feature_off(test_case.feature.name); |
| 774 | 772 |
| 775 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); | 773 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 776 base::FeatureList::SetInstance(std::move(feature_list)); | 774 base::test::ScopedFeatureList scoped_feature_list; |
| 775 scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| 777 | 776 |
| 778 // Trial should not be activated initially, but later might get activated | 777 // Trial should not be activated initially, but later might get activated |
| 779 // depending on the expected values. | 778 // depending on the expected values. |
| 780 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); | 779 EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name())); |
| 781 EXPECT_EQ(test_case.expected_feature_state, | 780 EXPECT_EQ(test_case.expected_feature_state, |
| 782 base::FeatureList::IsEnabled(test_case.feature)); | 781 base::FeatureList::IsEnabled(test_case.feature)); |
| 783 EXPECT_EQ(test_case.expected_trial_activated, | 782 EXPECT_EQ(test_case.expected_trial_activated, |
| 784 base::FieldTrialList::IsTrialActive(study.name())); | 783 base::FieldTrialList::IsTrialActive(study.name())); |
| 785 } | 784 } |
| 786 } | 785 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 807 {kEnabledFeature, false, year_ago, true}, | 806 {kEnabledFeature, false, year_ago, true}, |
| 808 {kEnabledFeature, false, year_later, false}, | 807 {kEnabledFeature, false, year_later, false}, |
| 809 }; | 808 }; |
| 810 | 809 |
| 811 for (size_t i = 0; i < arraysize(test_cases); i++) { | 810 for (size_t i = 0; i < arraysize(test_cases); i++) { |
| 812 const auto& test_case = test_cases[i]; | 811 const auto& test_case = test_cases[i]; |
| 813 SCOPED_TRACE( | 812 SCOPED_TRACE( |
| 814 base::StringPrintf("Test[%" PRIuS "]: %s", i, test_case.feature.name)); | 813 base::StringPrintf("Test[%" PRIuS "]: %s", i, test_case.feature.name)); |
| 815 | 814 |
| 816 base::FieldTrialList field_trial_list(nullptr); | 815 base::FieldTrialList field_trial_list(nullptr); |
| 817 base::FeatureList::ClearInstanceForTesting(); | |
| 818 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 816 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 819 feature_list->InitializeFromCommandLine(std::string(), std::string()); | 817 feature_list->InitializeFromCommandLine(std::string(), std::string()); |
| 820 | 818 |
| 821 // Expired study with a 100% feature group and a default group that has no | 819 // Expired study with a 100% feature group and a default group that has no |
| 822 // feature association. | 820 // feature association. |
| 823 Study study; | 821 Study study; |
| 824 study.set_name("Study1"); | 822 study.set_name("Study1"); |
| 825 study.set_default_experiment_name("Default"); | 823 study.set_default_experiment_name("Default"); |
| 826 | 824 |
| 827 study.set_expiry_date(TimeToProtoTime(test_case.expiry_date)); | 825 study.set_expiry_date(TimeToProtoTime(test_case.expiry_date)); |
| 828 | 826 |
| 829 AddExperiment("Default", 0, &study); | 827 AddExperiment("Default", 0, &study); |
| 830 Study_Experiment* feature_experiment = AddExperiment("Feature", 1, &study); | 828 Study_Experiment* feature_experiment = AddExperiment("Feature", 1, &study); |
| 831 if (test_case.study_force_feature_state) { | 829 if (test_case.study_force_feature_state) { |
| 832 feature_experiment->mutable_feature_association()->add_enable_feature( | 830 feature_experiment->mutable_feature_association()->add_enable_feature( |
| 833 test_case.feature.name); | 831 test_case.feature.name); |
| 834 } else { | 832 } else { |
| 835 feature_experiment->mutable_feature_association()->add_disable_feature( | 833 feature_experiment->mutable_feature_association()->add_disable_feature( |
| 836 test_case.feature.name); | 834 test_case.feature.name); |
| 837 } | 835 } |
| 838 | 836 |
| 839 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); | 837 EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get())); |
| 840 base::FeatureList::SetInstance(std::move(feature_list)); | 838 base::test::ScopedFeatureList scoped_feature_list; |
| 839 scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| 841 | 840 |
| 842 // Tthe feature should not be enabled, because the study is expired. | 841 // Tthe feature should not be enabled, because the study is expired. |
| 843 EXPECT_EQ(test_case.expected_feature_enabled, | 842 EXPECT_EQ(test_case.expected_feature_enabled, |
| 844 base::FeatureList::IsEnabled(test_case.feature)); | 843 base::FeatureList::IsEnabled(test_case.feature)); |
| 845 } | 844 } |
| 846 } | 845 } |
| 847 | 846 |
| 848 TEST_F(VariationsSeedProcessorTest, LowEntropyStudyTest) { | 847 TEST_F(VariationsSeedProcessorTest, LowEntropyStudyTest) { |
| 849 const std::string kTrial1Name = "A"; | 848 const std::string kTrial1Name = "A"; |
| 850 const std::string kTrial2Name = "B"; | 849 const std::string kTrial2Name = "B"; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 // Since no experiment in study1 sends experiment IDs, it will use the high | 886 // Since no experiment in study1 sends experiment IDs, it will use the high |
| 888 // entropy provider, which selects the non-default group. | 887 // entropy provider, which selects the non-default group. |
| 889 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrial1Name)); | 888 EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrial1Name)); |
| 890 | 889 |
| 891 // Since an experiment in study2 has google_web_experiment_id set, it will use | 890 // Since an experiment in study2 has google_web_experiment_id set, it will use |
| 892 // the low entropy provider, which selects the default group. | 891 // the low entropy provider, which selects the default group. |
| 893 EXPECT_EQ(kDefaultName, base::FieldTrialList::FindFullName(kTrial2Name)); | 892 EXPECT_EQ(kDefaultName, base::FieldTrialList::FindFullName(kTrial2Name)); |
| 894 } | 893 } |
| 895 | 894 |
| 896 } // namespace variations | 895 } // namespace variations |
| OLD | NEW |