| Index: base/test/scoped_feature_list.cc
|
| diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc
|
| index f0f3f4edfba1f1d333ef3188836cf14273795739..22b20b96e034b8965e5ffdfdcb57daa1b86d9c84 100644
|
| --- a/base/test/scoped_feature_list.cc
|
| +++ b/base/test/scoped_feature_list.cc
|
| @@ -4,22 +4,77 @@
|
|
|
| #include "base/test/scoped_feature_list.h"
|
|
|
| +#include <algorithm>
|
| #include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/stl_util.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "base/strings/string_util.h"
|
|
|
| namespace base {
|
| namespace test {
|
|
|
| namespace {
|
|
|
| -static std::string GetFeatureString(
|
| +std::vector<StringPiece> GetFeatureVector(
|
| const std::initializer_list<base::Feature>& features) {
|
| - std::string output;
|
| + std::vector<StringPiece> output;
|
| for (const base::Feature& feature : features) {
|
| - if (!output.empty())
|
| - output += ",";
|
| - output += feature.name;
|
| + output.push_back(feature.name);
|
| }
|
| +
|
| return output;
|
| +}
|
| +
|
| +// Extracts a feature name from a feature state string. For example, given
|
| +// the input "*MyLovelyFeature<SomeFieldTrial", returns "MyLovelyFeature".
|
| +StringPiece GetFeatureName(StringPiece feature) {
|
| + StringPiece feature_name = feature;
|
| +
|
| + // Remove default info.
|
| + if (feature_name.starts_with("*"))
|
| + feature_name = feature_name.substr(1);
|
| +
|
| + // Remove field_trial info.
|
| + std::size_t index = feature_name.find("<");
|
| + if (index != std::string::npos)
|
| + feature_name = feature_name.substr(0, index);
|
| +
|
| + return feature_name;
|
| +}
|
| +
|
| +struct Features {
|
| + std::vector<StringPiece> enabled_feature_list;
|
| + std::vector<StringPiece> disabled_feature_list;
|
| +};
|
| +
|
| +// Merges previously-specified feature overrides with those passed into one of
|
| +// the Init() methods. |features| should be a list of features previously
|
| +// overridden to be in the |override_state|. |merged_features| should contain
|
| +// the enabled and disabled features passed into the Init() method, plus any
|
| +// overrides merged as a result of previous calls to this function.
|
| +void OverrideFeatures(const std::string& features,
|
| + base::FeatureList::OverrideState override_state,
|
| + Features* merged_features) {
|
| + std::vector<StringPiece> features_list =
|
| + SplitStringPiece(features, ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
| +
|
| + for (StringPiece feature : features_list) {
|
| + StringPiece feature_name = GetFeatureName(feature);
|
| +
|
| + if (ContainsValue(merged_features->enabled_feature_list, feature_name) ||
|
| + ContainsValue(merged_features->disabled_feature_list, feature_name))
|
| + continue;
|
| +
|
| + if (override_state == FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE) {
|
| + merged_features->enabled_feature_list.push_back(feature);
|
| + } else {
|
| + DCHECK_EQ(override_state,
|
| + FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE);
|
| + merged_features->disabled_feature_list.push_back(feature);
|
| + }
|
| + }
|
| }
|
|
|
| } // namespace
|
| @@ -40,13 +95,6 @@
|
| InitWithFeatureList(std::move(feature_list));
|
| }
|
|
|
| -void ScopedFeatureList::InitWithFeatures(
|
| - const std::initializer_list<base::Feature>& enabled_features,
|
| - const std::initializer_list<base::Feature>& disabled_features) {
|
| - InitFromCommandLine(GetFeatureString(enabled_features),
|
| - GetFeatureString(disabled_features));
|
| -}
|
| -
|
| void ScopedFeatureList::InitWithFeatureList(
|
| std::unique_ptr<FeatureList> feature_list) {
|
| DCHECK(!original_feature_list_);
|
| @@ -62,12 +110,43 @@
|
| InitWithFeatureList(std::move(feature_list));
|
| }
|
|
|
| +void ScopedFeatureList::InitWithFeatures(
|
| + const std::initializer_list<base::Feature>& enabled_features,
|
| + const std::initializer_list<base::Feature>& disabled_features) {
|
| + Features merged_features;
|
| + merged_features.enabled_feature_list = GetFeatureVector(enabled_features);
|
| + merged_features.disabled_feature_list = GetFeatureVector(disabled_features);
|
| +
|
| + base::FeatureList* feature_list = base::FeatureList::GetInstance();
|
| +
|
| + // |current_enabled_features| and |current_disabled_features| must declare out
|
| + // of if scope to avoid them out of scope before JoinString calls because
|
| + // |merged_features| may contains StringPiece which holding pointer points to
|
| + // |current_enabled_features| and |current_disabled_features|.
|
| + std::string current_enabled_features;
|
| + std::string current_disabled_features;
|
| + if (feature_list) {
|
| + base::FeatureList::GetInstance()->GetFeatureOverrides(
|
| + ¤t_enabled_features, ¤t_disabled_features);
|
| + OverrideFeatures(current_enabled_features,
|
| + FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE,
|
| + &merged_features);
|
| + OverrideFeatures(current_disabled_features,
|
| + FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE,
|
| + &merged_features);
|
| + }
|
| +
|
| + std::string enabled = JoinString(merged_features.enabled_feature_list, ",");
|
| + std::string disabled = JoinString(merged_features.disabled_feature_list, ",");
|
| + InitFromCommandLine(enabled, disabled);
|
| +}
|
| +
|
| void ScopedFeatureList::InitAndEnableFeature(const base::Feature& feature) {
|
| - InitFromCommandLine(feature.name, std::string());
|
| + InitWithFeatures({feature}, {});
|
| }
|
|
|
| void ScopedFeatureList::InitAndDisableFeature(const base::Feature& feature) {
|
| - InitFromCommandLine(std::string(), feature.name);
|
| + InitWithFeatures({}, {feature});
|
| }
|
|
|
| } // namespace test
|
|
|