| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // 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 <utility> |
| |
| #include "base/command_line.h" |
| #include "base/macros.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/field_trial_params.h" |
| #include "base/optional.h" |
| #include "base/stl_util.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 "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/device_form_factor.h" |
| |
| namespace variations { |
| namespace { |
| |
| class TestOverrideStringCallback { |
| public: |
| typedef std::map<uint32_t, std::u16string> OverrideMap; |
| |
| TestOverrideStringCallback() |
| : callback_(base::BindRepeating(&TestOverrideStringCallback::Override, |
| base::Unretained(this))) {} |
| |
| virtual ~TestOverrideStringCallback() {} |
| |
| 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_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestOverrideStringCallback); |
| }; |
| |
| // TODO(crbug.com/1167566): 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: |
| VersionCallback GetVersionForSimulationCallback() override { |
| return base::BindOnce([] { 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; } |
| |
| private: |
| // VariationsServiceClient: |
| version_info::Channel GetChannel() override { |
| return version_info::Channel::UNKNOWN; |
| } |
| }; |
| |
| class FieldTrialUtilTest : public ::testing::Test { |
| public: |
| FieldTrialUtilTest() {} |
| |
| ~FieldTrialUtilTest() override { |
| // Ensure that the maps are cleared between tests, since they are stored as |
| // process singletons. |
| testing::ClearAllVariationIDs(); |
| testing::ClearAllVariationParams(); |
| } |
| |
| protected: |
| TestOverrideStringCallback override_callback_; |
| TestVariationsServiceClient variation_service_client_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FieldTrialUtilTest); |
| }; |
| |
| } // 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("/", GetVariationParamValue(kTrialName, "a")); |
| EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "b")); |
| EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams(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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| {"TestGroup1", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params_0, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_1[] = |
| {{"x", "3"}, {"y", "4"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| {"TestGroup2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params_0, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| {"TestGroup2-2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params_1, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1, 2}, |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 2 |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", GetVariationParamValue("TestTrial1", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial1", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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")); |
| } |
| |
| 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(base::size(all_platforms) == Study::Platform_ARRAYSIZE, |
| "|all_platforms| must include all platforms."); |
| |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| |
| for (size_t i = 0; i < base::size(all_platforms); ++i) { |
| const Study::Platform platform = all_platforms[i]; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1} |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 1 |
| }; |
| |
| base::FeatureList feature_list; |
| AssociateParamsFromFieldTrialConfig( |
| kConfig, override_callback_.callback(), platform, |
| variation_service_client_.GetCurrentFormFactor(), &feature_list); |
| |
| EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = |
| {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = |
| {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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("", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| platforms, |
| 2, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = |
| {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = |
| {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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, |
| }; |
| const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = |
| {{"x", "1"}, {"y", "2"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", &platform, 1, form_factors, 4, base::nullopt, nullptr, |
| array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, |
| nullptr, 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = |
| {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = |
| {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", &platform, 1, &form_factor, 1, base::nullopt, nullptr, |
| array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, |
| nullptr, 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1} |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 1 |
| }; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", &platform, 1, &form_factor, 1, base::nullopt, nullptr, |
| array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, |
| nullptr, 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = |
| {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = |
| {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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("", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(GetVariationParams("TestTrial", ¶ms)); |
| |
| EXPECT_EQ("", base::FieldTrialList::FindFullName("TestTrial")); |
| } |
| } |
| |
| TEST_F(FieldTrialUtilTest, AssociateFeaturesFromFieldTrialConfig) { |
| const base::Feature kFeatureA{"A", base::FEATURE_DISABLED_BY_DEFAULT}; |
| const base::Feature kFeatureB{"B", base::FEATURE_ENABLED_BY_DEFAULT}; |
| const base::Feature kFeatureC{"C", base::FEATURE_DISABLED_BY_DEFAULT}; |
| const 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; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| {"TestGroup1", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| enable_features, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| {"TestGroup2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| disable_features, |
| 2, |
| nullptr, |
| nullptr, |
| 0}, |
| {"TestGroup2-2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| }; |
| |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1, 2}, |
| }; |
| |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 2 |
| }; |
| |
| 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; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { |
| {"TestGroup1", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { |
| {"TestGroup2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| {"ForcedGroup2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| "flag-2", |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { |
| {"TestGroup3", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| nullptr, |
| 0}, |
| {"ForcedGroup3", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| "flag-3", |
| nullptr, |
| 0}, |
| {"ForcedGroup3-2", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| nullptr, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| "flag-3-2", |
| nullptr, |
| 0}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, |
| {"TestTrial2", array_kFieldTrialConfig_experiments_1, 2}, |
| {"TestTrial3", array_kFieldTrialConfig_experiments_2, 3}, |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 3 |
| }; |
| |
| 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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", &platform, 1, nullptr, 0, base::nullopt, nullptr, |
| array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr, |
| array_kFieldTrialConfig_override_ui_string, 2}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1} |
| }; |
| const FieldTrialTestingConfig kConfig = { |
| array_kFieldTrialConfig_studies, 1 |
| }; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::SysInfo::IsLowEndDevice(), |
| nullptr, |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| !base::SysInfo::IsLowEndDevice(), |
| nullptr, |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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("", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| min_os_version.c_str(), |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_TRUE(GetVariationParams("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"}}; |
| const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { |
| {"TestGroup", |
| &platform, |
| 1, |
| {}, |
| 0, |
| base::nullopt, |
| min_os_version.c_str(), |
| array_kFieldTrialConfig_params, |
| 2, |
| nullptr, |
| 0, |
| nullptr, |
| 0, |
| nullptr}, |
| }; |
| const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { |
| {"TestTrial", array_kFieldTrialConfig_experiments, 1}}; |
| const FieldTrialTestingConfig kConfig = {array_kFieldTrialConfig_studies, 1}; |
| |
| // 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("", GetVariationParamValue("TestTrial", "x")); |
| EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); |
| |
| std::map<std::string, std::string> params; |
| EXPECT_FALSE(GetVariationParams("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)); |
| } |
| } // namespace variations |