| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/variations/field_trial_config/field_trial_util.h" |
| |
| #include <map> |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/containers/span.h" |
| #include "base/memory/raw_span.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/field_trial_params.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/system/sys_info.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "components/variations/client_filterable_state.h" |
| #include "components/variations/field_trial_config/fieldtrial_testing_config.h" |
| #include "components/variations/service/variations_service_client.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "components/variations/variations_seed_processor.h" |
| #include "components/variations/variations_switches.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace variations { |
| namespace { |
| |
| class ExperimentBuilder { |
| public: |
| ExperimentBuilder() = default; |
| |
| FieldTrialTestingExperiment Build() const { |
| return { |
| name, |
| platforms, |
| form_factors, |
| is_low_end_device, |
| disable_benchmarking, |
| min_os_version, |
| params, |
| enable_features, |
| disable_features, |
| forcing_flag, |
| override_ui_string, |
| hardware_classes, |
| exclude_hardware_classes, |
| }; |
| } |
| |
| const char* name = nullptr; |
| base::raw_span<const Study::Platform> platforms = {}; |
| base::raw_span<const Study::FormFactor> form_factors = {}; |
| std::optional<bool> is_low_end_device = std::nullopt; |
| std::optional<bool> disable_benchmarking = std::nullopt; |
| const char* min_os_version = nullptr; |
| base::raw_span<const FieldTrialTestingExperimentParams> params = {}; |
| base::raw_span<const char*> enable_features = {}; |
| base::raw_span<const char*> disable_features = {}; |
| const char* forcing_flag = nullptr; |
| base::raw_span<const OverrideUIString> override_ui_string = {}; |
| base::raw_span<const char*> hardware_classes = {}; |
| base::raw_span<const char*> exclude_hardware_classes = {}; |
| }; |
| |
| class TestOverrideStringCallback { |
| public: |
| typedef std::map<uint32_t, std::u16string> OverrideMap; |
| |
| TestOverrideStringCallback() |
| : callback_(base::BindRepeating(&TestOverrideStringCallback::Override, |
| base::Unretained(this))) {} |
| |
| TestOverrideStringCallback(const TestOverrideStringCallback&) = delete; |
| TestOverrideStringCallback& operator=(const TestOverrideStringCallback&) = |
| delete; |
| |
| virtual ~TestOverrideStringCallback() = default; |
| |
| const VariationsSeedProcessor::UIStringOverrideCallback& callback() const { |
| return callback_; |
| } |
| |
| const OverrideMap& overrides() const { return overrides_; } |
| |
| private: |
| void Override(uint32_t hash, const std::u16string& string) { |
| overrides_[hash] = string; |
| } |
| |
| VariationsSeedProcessor::UIStringOverrideCallback callback_; |
| OverrideMap overrides_; |
| }; |
| |
| // TODO(crbug.com/40742801): Remove when fake VariationsServiceClient created. |
| class TestVariationsServiceClient : public VariationsServiceClient { |
| public: |
| TestVariationsServiceClient() = default; |
| TestVariationsServiceClient(const TestVariationsServiceClient&) = delete; |
| TestVariationsServiceClient& operator=(const TestVariationsServiceClient&) = |
| delete; |
| ~TestVariationsServiceClient() override = default; |
| |
| // VariationsServiceClient: |
| base::Version GetVersionForSimulation() override { return base::Version(); } |
| scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() |
| override { |
| return nullptr; |
| } |
| network_time::NetworkTimeTracker* GetNetworkTimeTracker() override { |
| return nullptr; |
| } |
| bool OverridesRestrictParameter(std::string* parameter) override { |
| return false; |
| } |
| bool IsEnterprise() override { return false; } |
| void RemoveGoogleGroupsFromPrefsForDeletedProfiles( |
| PrefService* local_state) override {} |
| |
| private: |
| // VariationsServiceClient: |
| version_info::Channel GetChannel() override { |
| return version_info::Channel::UNKNOWN; |
| } |
| }; |
| |
| class FieldTrialUtilTest : public ::testing::Test { |
| public: |
| FieldTrialUtilTest() = default; |
| |
| FieldTrialUtilTest(const FieldTrialUtilTest&) = delete; |
| FieldTrialUtilTest& operator=(const FieldTrialUtilTest&) = delete; |
| |
| ~FieldTrialUtilTest() override { |
| // Ensure that the maps are cleared between tests, since they are stored as |
| // process singletons. |
| test::ClearAllVariationIDs(); |
| test::ClearAllVariationParams(); |
| } |
| |
| protected: |
| TestOverrideStringCallback override_callback_; |
| TestVariationsServiceClient variation_service_client_; |
| }; |
| |
| } // namespace |
| |
| TEST_F(FieldTrialUtilTest, AssociateParamsFromString) { |
| const std::string kTrialName = "AssociateVariationParams"; |
| const std::string kVariationsString = |
| "AssociateVariationParams.A:a/10/b/test,AssociateVariationParams.B:a/%2F"; |
| ASSERT_TRUE(AssociateParamsFromString(kVariationsString)); |
| |
| base::FieldTrialList::CreateFieldTrial(kTrialName, "B"); |
| EXPECT_EQ("/", base::GetFieldTrialParamValue(kTrialName, "a")); |
| EXPECT_EQ(std::string(), base::GetFieldTrialParamValue(kTrialName, "b")); |
| EXPECT_EQ(std::string(), base::GetFieldTrialParamValue(kTrialName, "x")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams(kTrialName, ¶ms)); |
| EXPECT_EQ(1U, params.size()); |
| EXPECT_EQ("/", params["a"]); |
| } |
| |
| TEST_F(FieldTrialUtilTest, AssociateParamsFromStringWithSameTrial) { |
| const std::string kTrialName = "AssociateVariationParams"; |
| const std::string kVariationsString = |
| "AssociateVariationParams.A:a/10/b/test,AssociateVariationParams.A:a/x"; |
| ASSERT_FALSE(AssociateParamsFromString(kVariationsString)); |
| } |
| |
| TEST_F(FieldTrialUtilTest, AssociateParamsFromFieldTrialConfig) { |
| const Study::Platform platform = Study::PLATFORM_LINUX; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_0[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder study_0_experiment_0_builder; |
| study_0_experiment_0_builder.name = "TestGroup1"; |
| study_0_experiment_0_builder.platforms = base::span_from_ref(platform); |
| study_0_experiment_0_builder.params = array_kFieldTrialConfig_params_0; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| study_0_experiment_0_builder.Build(), |
| }; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_1[] = |
| {{"x", "3"}, {"y", "4"}}; |
| ExperimentBuilder study_1_experiment_0_builder; |
| study_1_experiment_0_builder.name = "TestGroup2"; |
| study_1_experiment_0_builder.platforms = base::span_from_ref(platform); |
| study_1_experiment_0_builder.params = array_kFieldTrialConfig_params_0; |
| ExperimentBuilder study_1_experiment_1_builder; |
| study_1_experiment_1_builder.name = "TestGroup2-2"; |
| study_1_experiment_1_builder.platforms = base::span_from_ref(platform); |
| study_1_experiment_1_builder.params = array_kFieldTrialConfig_params_1; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| study_1_experiment_0_builder.Build(), |
| study_1_experiment_1_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1}, |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial1", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial1", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial1", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup1", base::FieldTrialList::FindFullName("TestTrial1")); |
| EXPECT_EQ("TestGroup2", base::FieldTrialList::FindFullName("TestTrial2")); |
| } |
| |
| // Verifies that studies in the field trial config should be skipped if they |
| // enable/disable features that were overridden through the command line. |
| TEST_F(FieldTrialUtilTest, FieldTrialConfigSkipOverridden) { |
| // Create a testing config equivalent to: |
| // { |
| // "TestTrial0": [ |
| // { |
| // "platforms": ["linux"], |
| // "experiments": [ |
| // { |
| // "name": "TestGroup0", |
| // "enable_features": ["A"] |
| // } |
| // ] |
| // } |
| // ], |
| // "TestTrial1": [ |
| // { |
| // "platforms": ["linux"], |
| // "experiments": [ |
| // { |
| // "name": "TestGroup1", |
| // "disable_features": ["A"] |
| // } |
| // ] |
| // } |
| // ], |
| // "TestTrial2": [ |
| // { |
| // "platforms": ["linux"], |
| // "experiments": [ |
| // { |
| // "name": "TestGroup2", |
| // "enable_features": ["C"], |
| // "disable_features": ["D"] |
| // } |
| // ] |
| // } |
| // ] |
| // } |
| const Study::Platform platform = Study::PLATFORM_LINUX; |
| |
| const char* enable_features_0[] = {"A"}; |
| ExperimentBuilder experiment_0_builder; |
| experiment_0_builder.name = "TestGroup0"; |
| experiment_0_builder.platforms = base::span_from_ref(platform); |
| experiment_0_builder.enable_features = enable_features_0; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| experiment_0_builder.Build(), |
| }; |
| |
| const char* disable_features_1[] = {"B"}; |
| ExperimentBuilder experiment_1_builder; |
| experiment_1_builder.name = "TestGroup1"; |
| experiment_1_builder.platforms = base::span_from_ref(platform); |
| experiment_1_builder.disable_features = disable_features_1; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| experiment_1_builder.Build(), |
| }; |
| |
| const char* enable_features2[] = {"C"}; |
| const char* disable_features_2[] = {"D"}; |
| ExperimentBuilder experiment_2_builder; |
| experiment_2_builder.name = "TestGroup2"; |
| experiment_2_builder.platforms = base::span_from_ref(platform); |
| experiment_0_builder.enable_features = enable_features2; |
| experiment_2_builder.disable_features = disable_features_2; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { |
| experiment_2_builder.Build(), |
| }; |
| |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {/*name=*/"TestTrial0", |
| /*experiments=*/array_kFieldTrialConfig_experiments_0}, |
| {/*name=*/"TestTrial1", |
| /*experiments=*/array_kFieldTrialConfig_experiments_1}, |
| {/*name=*/"TestTrial2", |
| /*experiments=*/array_kFieldTrialConfig_experiments_2}, |
| }; |
| |
| const FieldTrialTestingConfig kConfig = { |
| /*studies=*/array_kFieldTrialConfig_studies}; |
| |
| base::FeatureList feature_list; |
| // Enable feature "A" and disable feature "B" as if they were enabled/disabled |
| // using the |--enable-features| and |--disable-features| switches. |
| base::FieldTrialList::CreateFieldTrial("Study", "Experiment"); |
| feature_list.InitFromCommandLine(/*enable_features=*/"A<Study", |
| /*disable_features=*/"B"); |
| |
| // Associate the |kConfig| field trial config. |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| // Expect only TestTrial2 to have been registered as it is the only study to |
| // not enable/disable features A or B. |
| EXPECT_FALSE(base::FieldTrialList::TrialExists("TestTrial0")); |
| EXPECT_FALSE(base::FieldTrialList::TrialExists("TestTrial1")); |
| EXPECT_TRUE(base::FieldTrialList::TrialExists("TestTrial2")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithEachPlatform) { |
| const Study::Platform all_platforms[] = { |
| Study::PLATFORM_ANDROID, // Comment to prevent clang format bin packing. |
| Study::PLATFORM_ANDROID_WEBLAYER, |
| Study::PLATFORM_ANDROID_WEBVIEW, |
| Study::PLATFORM_CHROMEOS, |
| Study::PLATFORM_CHROMEOS_LACROS, |
| Study::PLATFORM_FUCHSIA, |
| Study::PLATFORM_IOS, |
| Study::PLATFORM_LINUX, |
| Study::PLATFORM_MAC, |
| Study::PLATFORM_WINDOWS, |
| }; |
| |
| // Break if platforms are added without updating |all_platforms|. |
| static_assert(std::size(all_platforms) == Study::Platform_ARRAYSIZE, |
| "|all_platforms| must include all platforms."); |
| |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| |
| for (Study::Platform platform : all_platforms) { |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithDifferentPlatform) { |
| const Study::Platform platform = Study::PLATFORM_ANDROID; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The platforms don't match, so trial shouldn't be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithMultiplePlatforms) { |
| const Study::Platform platforms[] = |
| {Study::PLATFORM_ANDROID, Study::PLATFORM_ANDROID_WEBVIEW}; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = platforms; |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // One of the platforms matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithAllFormFactors) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const Study::FormFactor form_factors[] = { |
| Study::DESKTOP, |
| Study::PHONE, |
| Study::TABLET, |
| Study::MEET_DEVICE, |
| Study::FOLDABLE, |
| }; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.form_factors = form_factors; |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // One of the form_factors matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithSingleFormFactor) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const Study::FormFactor form_factor = |
| variation_service_client_.GetCurrentFormFactor(); |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.form_factors = base::span_from_ref(form_factor); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // One of the form_factors matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithDifferentFormFactor) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const Study::FormFactor current_form_factor = |
| variation_service_client_.GetCurrentFormFactor(); |
| const Study::FormFactor all_form_factors[] = { |
| Study::DESKTOP, |
| Study::PHONE, |
| Study::TABLET, |
| Study::MEET_DEVICE, |
| }; |
| for (const Study::FormFactor form_factor : all_form_factors) { |
| if (form_factor == current_form_factor) { |
| continue; |
| } |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.form_factors = base::span_from_ref(form_factor); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The form factor don't match, so trial shouldn't be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| } |
| |
| TEST_F(FieldTrialUtilTest, AssociateFeaturesFromFieldTrialConfig) { |
| static BASE_FEATURE(kFeatureA, "A", base::FEATURE_DISABLED_BY_DEFAULT); |
| static BASE_FEATURE(kFeatureB, "B", base::FEATURE_ENABLED_BY_DEFAULT); |
| static BASE_FEATURE(kFeatureC, "C", base::FEATURE_DISABLED_BY_DEFAULT); |
| static BASE_FEATURE(kFeatureD, "D", base::FEATURE_ENABLED_BY_DEFAULT); |
| |
| const char* enable_features[] = {"A", "B"}; |
| const char* disable_features[] = {"C", "D"}; |
| |
| const Study::Platform platform = Study::PLATFORM_LINUX; |
| ExperimentBuilder study_0_experiment_0_builder; |
| study_0_experiment_0_builder.name = "TestGroup1"; |
| study_0_experiment_0_builder.platforms = base::span_from_ref(platform); |
| study_0_experiment_0_builder.enable_features = enable_features; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| study_0_experiment_0_builder.Build(), |
| }; |
| ExperimentBuilder study_1_experiment_0_builder; |
| study_1_experiment_0_builder.name = "TestGroup2"; |
| study_1_experiment_0_builder.platforms = base::span_from_ref(platform); |
| study_1_experiment_0_builder.disable_features = disable_features; |
| ExperimentBuilder study_1_experiment_1_builder; |
| study_1_experiment_1_builder.name = "TestGroup2-2"; |
| study_1_experiment_1_builder.platforms = base::span_from_ref(platform); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| study_1_experiment_0_builder.Build(), |
| study_1_experiment_1_builder.Build(), |
| }; |
| |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1}, |
| }; |
| |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), feature_list.get()); |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatureList(std::move(feature_list)); |
| |
| // Check the resulting feature and field trial states. Trials should not be |
| // active until their associated features are queried. |
| EXPECT_FALSE(base::FieldTrialList::IsTrialActive("TestTrial1")); |
| EXPECT_TRUE(base::FeatureList::IsEnabled(kFeatureA)); |
| EXPECT_TRUE(base::FeatureList::IsEnabled(kFeatureB)); |
| EXPECT_TRUE(base::FieldTrialList::IsTrialActive("TestTrial1")); |
| |
| EXPECT_FALSE(base::FieldTrialList::IsTrialActive("TestTrial2")); |
| EXPECT_FALSE(base::FeatureList::IsEnabled(kFeatureC)); |
| EXPECT_FALSE(base::FeatureList::IsEnabled(kFeatureD)); |
| EXPECT_TRUE(base::FieldTrialList::IsTrialActive("TestTrial2")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) { |
| const Study::Platform platform = Study::PLATFORM_LINUX; |
| ExperimentBuilder study_0_experiment_0_builder; |
| study_0_experiment_0_builder.name = "TestGroup1"; |
| study_0_experiment_0_builder.platforms = base::span_from_ref(platform); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| study_0_experiment_0_builder.Build(), |
| }; |
| ExperimentBuilder study_1_experiment_0_builder; |
| study_1_experiment_0_builder.name = "TestGroup2"; |
| study_1_experiment_0_builder.platforms = base::span_from_ref(platform); |
| ExperimentBuilder study_1_experiment_1_builder; |
| study_1_experiment_1_builder.name = "ForcedGroup2"; |
| study_1_experiment_1_builder.platforms = base::span_from_ref(platform); |
| study_1_experiment_1_builder.forcing_flag = "flag-2"; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| study_1_experiment_0_builder.Build(), |
| study_1_experiment_1_builder.Build(), |
| }; |
| ExperimentBuilder study_2_experiment_0_builder; |
| study_2_experiment_0_builder.name = "TestGroup3"; |
| study_2_experiment_0_builder.platforms = base::span_from_ref(platform); |
| ExperimentBuilder study_2_experiment_1_builder; |
| study_2_experiment_1_builder.name = "ForcedGroup3"; |
| study_2_experiment_1_builder.platforms = base::span_from_ref(platform); |
| study_2_experiment_1_builder.forcing_flag = "flag-3"; |
| ExperimentBuilder study_2_experiment_2_builder; |
| study_2_experiment_2_builder.name = "ForcedGroup3-2"; |
| study_2_experiment_2_builder.platforms = base::span_from_ref(platform); |
| study_2_experiment_2_builder.forcing_flag = "flag-3-2"; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { |
| study_2_experiment_0_builder.Build(), |
| study_2_experiment_1_builder.Build(), |
| study_2_experiment_2_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1}, |
| {"TestTrial3", array_kFieldTrialConfig_experiments_2}, |
| }; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| base::CommandLine::ForCurrentProcess()->AppendSwitch("flag-2"); |
| base::CommandLine::ForCurrentProcess()->AppendSwitch("flag-3"); |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("TestGroup1", base::FieldTrialList::FindFullName("TestTrial1")); |
| EXPECT_EQ("ForcedGroup2", base::FieldTrialList::FindFullName("TestTrial2")); |
| EXPECT_EQ("ForcedGroup3", base::FieldTrialList::FindFullName("TestTrial3")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithUIStringOverrides) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| const OverrideUIString array_kFieldTrialConfig_override_ui_string[] = |
| {{1234, "test1"}, {5678, "test2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| experiment_builder.override_ui_string = |
| array_kFieldTrialConfig_override_ui_string; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // One of the form_factors matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| const TestOverrideStringCallback::OverrideMap& overrides = |
| override_callback_.overrides(); |
| EXPECT_EQ(2u, overrides.size()); |
| auto it = overrides.find(1234); |
| EXPECT_EQ(u"test1", it->second); |
| it = overrides.find(5678); |
| EXPECT_EQ(u"test2", it->second); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithIsLowEndDeviceMatch) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| experiment_builder.is_low_end_device = base::SysInfo::IsLowEndDevice(); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The is_low_end_device filter matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithIsLowEndDeviceMismatch) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| experiment_builder.is_low_end_device = !base::SysInfo::IsLowEndDevice(); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The is_low_end_device don't match, so trial shouldn't be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithMinOsVersionMatch) { |
| base::Version version = ClientFilterableState::GetOSVersion(); |
| std::string min_os_version = version.GetString(); |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| experiment_builder.min_os_version = min_os_version.c_str(); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The min_os_version filter matches, so trial should be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F( |
| FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithEnableBenchmarkingAndDisableBenchmarking) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| |
| // When both enable-benchmarking and 'disable_benchmarking' are set, |
| // the trial should not be added. |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableBenchmarking); |
| experiment_builder.disable_benchmarking = true; |
| |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The 'disable_benchmarking' field should prevent this trial from being |
| // added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F( |
| FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithEnableBenchmarkingAndNoDisableBenchmarking) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| |
| // If enable-benchmarking is set, and the experiment doesn't set |
| // 'disable_benchmarking', the trial should be added. |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableBenchmarking); |
| experiment_builder.disable_benchmarking = false; |
| |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The 'disable_benchmarking' field should prevent this trial from being |
| // added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F( |
| FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithNoEnableBenchmarkingWithDisableBenchmarking) { |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| |
| // If there is no --enable-benchmarking switch, the trial should be added. |
| experiment_builder.disable_benchmarking = true; |
| |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The 'disable_benchmarking' field out should prevent this trial from being |
| // added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| EXPECT_EQ(2U, params.size()); |
| EXPECT_EQ("1", params["x"]); |
| EXPECT_EQ("2", params["y"]); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithMinOsVersionMismatch) { |
| base::Version version = ClientFilterableState::GetOSVersion(); |
| base::Version higher_version = |
| base::Version({version.components()[0] + 1, 0, 0}); |
| std::string min_os_version = higher_version.GetString(); |
| const Study::Platform platform = Study::PLATFORM_WINDOWS; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = { |
| {"x", "1"}, {"y", "2"}}; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.params = array_kFieldTrialConfig_params; |
| experiment_builder.min_os_version = min_os_version.c_str(); |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| experiment_builder.Build(), |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies}; |
| |
| // The min_os_version doesn't match, so trial shouldn't be added. |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); |
| EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, TestEscapeValue) { |
| std::string str = "trail.:/,*"; |
| std::string escaped_str = EscapeValue(str); |
| EXPECT_EQ(escaped_str.find('.'), std::string::npos); |
| EXPECT_EQ(escaped_str.find(':'), std::string::npos); |
| EXPECT_EQ(escaped_str.find('/'), std::string::npos); |
| EXPECT_EQ(escaped_str.find(','), std::string::npos); |
| EXPECT_EQ(escaped_str.find('*'), std::string::npos); |
| |
| // Make sure the EscapeValue function is the inverse of base::UnescapeValue. |
| EXPECT_EQ(str, base::UnescapeValue(escaped_str)); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithHardwareClassMatch) { |
| std::string hardware_class = ClientFilterableState::GetHardwareClass(); |
| std::string unmatched_hardware_class = hardware_class + "foo"; |
| const char* classes[] = { |
| hardware_class.c_str(), |
| unmatched_hardware_class.c_str(), |
| }; |
| |
| Study::Platform platform = Study::PLATFORM_CHROMEOS; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.hardware_classes = classes; |
| FieldTrialTestingExperiment experiment[]{experiment_builder.Build()}; |
| |
| FieldTrialTestingStudy study[]{{ |
| /*name=*/"TestTrial", |
| /*experiments=*/experiment, |
| }}; |
| |
| FieldTrialTestingConfig config = { |
| /*studies=*/study, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| config, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithHardwareClassMismatch) { |
| std::string hardware_class = ClientFilterableState::GetHardwareClass(); |
| std::string unmatched_hardware_class = hardware_class + "foo"; |
| const char* classes[] = { |
| unmatched_hardware_class.c_str(), |
| }; |
| |
| Study::Platform platform = Study::PLATFORM_CHROMEOS; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.hardware_classes = classes; |
| FieldTrialTestingExperiment experiment[]{experiment_builder.Build()}; |
| |
| FieldTrialTestingStudy study[]{{ |
| /*name=*/"TestTrial", |
| /*experiments=*/experiment, |
| }}; |
| |
| FieldTrialTestingConfig config = { |
| /*studies=*/study, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| config, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithExcludHardwareClassMatch) { |
| std::string hardware_class = ClientFilterableState::GetHardwareClass(); |
| std::string unmatched_hardware_class = hardware_class + "foo"; |
| const char* classes[] = { |
| hardware_class.c_str(), |
| unmatched_hardware_class.c_str(), |
| }; |
| |
| Study::Platform platform = Study::PLATFORM_CHROMEOS; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.exclude_hardware_classes = classes; |
| FieldTrialTestingExperiment experiment[]{experiment_builder.Build()}; |
| |
| FieldTrialTestingStudy study[]{{ |
| /*name=*/"TestTrial", |
| /*experiments=*/experiment, |
| }}; |
| |
| FieldTrialTestingConfig config = { |
| /*studies=*/study, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| config, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| |
| TEST_F(FieldTrialUtilTest, |
| AssociateParamsFromFieldTrialConfigWithExcludHardwareClassMismatch) { |
| std::string hardware_class = ClientFilterableState::GetHardwareClass(); |
| std::string unmatched_hardware_class = hardware_class + "foo"; |
| const char* classes[] = { |
| unmatched_hardware_class.c_str(), |
| }; |
| |
| Study::Platform platform = Study::PLATFORM_CHROMEOS; |
| ExperimentBuilder experiment_builder; |
| experiment_builder.name = "TestGroup"; |
| experiment_builder.platforms = base::span_from_ref(platform); |
| experiment_builder.exclude_hardware_classes = classes; |
| FieldTrialTestingExperiment experiment[]{experiment_builder.Build()}; |
| |
| FieldTrialTestingStudy study[]{{ |
| /*name=*/"TestTrial", |
| /*experiments=*/experiment, |
| }}; |
| |
| FieldTrialTestingConfig config = { |
| /*studies=*/study, |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| config, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("TestGroup", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) |
| |
| } // namespace variations |