summaryrefslogtreecommitdiff
path: root/base/test/scoped_feature_list.h
blob: 6e13543ff19729125eda52d438838f7d1583dc10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2016 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.

#ifndef BASE_TEST_SCOPED_FEATURE_LIST_H_
#define BASE_TEST_SCOPED_FEATURE_LIST_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"

namespace base {
namespace test {

// ScopedFeatureList resets the global FeatureList instance to a new empty
// instance and restores the original instance upon destruction.
// Note: Re-using the same object is not allowed. To reset the feature
// list and initialize it anew, destroy an existing scoped list and init
// a new one.
//
// ScopedFeatureList needs to be initialized (via one of Init... methods)
// before running code that inspects the state of features.  In practice this
// means:
// - In browser tests, one of Init... methods should be called from the
//   overriden ::testing::Test::SetUp method. For example:
//     void SetUp() override {
//       scoped_feature_list_.InitAndEnableFeature(features::kMyFeatureHere);
//       InProcessBrowserTest::SetUp();
//     }
class ScopedFeatureList final {
 public:
  ScopedFeatureList();
  ~ScopedFeatureList();

  // WARNING: This method will reset any globally configured features to their
  // default values, which can hide feature interaction bugs. Please use
  // sparingly.  https://crbug.com/713390
  // Initializes and registers a FeatureList instance with no overrides.
  void Init();

  // WARNING: This method will reset any globally configured features to their
  // default values, which can hide feature interaction bugs. Please use
  // sparingly.  https://crbug.com/713390
  // Initializes and registers the given FeatureList instance.
  void InitWithFeatureList(std::unique_ptr<FeatureList> feature_list);

  // WARNING: This method will reset any globally configured features to their
  // default values, which can hide feature interaction bugs. Please use
  // sparingly.  https://crbug.com/713390
  // Initializes and registers a FeatureList instance with only the given
  // enabled and disabled features (comma-separated names).
  void InitFromCommandLine(const std::string& enable_features,
                           const std::string& disable_features);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with the given enabled and disabled features.
  // Any feature overrides already present in the global FeatureList will
  // continue to apply, unless they conflict with the overrides passed into this
  // method. This is important for testing potentially unexpected feature
  // interactions.
  void InitWithFeatures(const std::vector<Feature>& enabled_features,
                        const std::vector<Feature>& disabled_features);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with single enabled feature.
  void InitAndEnableFeature(const Feature& feature);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with single enabled feature and associated field
  // trial parameters.
  // Note: this creates a scoped global field trial list if there is not
  // currently one.
  void InitAndEnableFeatureWithParameters(
      const Feature& feature,
      const std::map<std::string, std::string>& feature_parameters);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with single disabled feature.
  void InitAndDisableFeature(const Feature& feature);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overriden with a single feature either enabled or
  // disabled depending on |enabled|.
  void InitWithFeatureState(const Feature& feature, bool enabled);

 private:
  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with the given enabled and disabled features.
  // Any feature overrides already present in the global FeatureList will
  // continue to apply, unless they conflict with the overrides passed into this
  // method.
  // Field trials will apply to the enabled features, in the same order. The
  // number of trials must be less (or equal) than the number of enabled
  // features.
  // Trials are expected to outlive the ScopedFeatureList.
  void InitWithFeaturesAndFieldTrials(
      const std::vector<Feature>& enabled_features,
      const std::vector<FieldTrial*>& trials_for_enabled_features,
      const std::vector<Feature>& disabled_features);

  // Initializes and registers a FeatureList instance based on present
  // FeatureList and overridden with single enabled feature and associated field
  // trial override.
  // |trial| is expected to outlive the ScopedFeatureList.
  void InitAndEnableFeatureWithFieldTrialOverride(const Feature& feature,
                                                  FieldTrial* trial);

  bool init_called_ = false;
  std::unique_ptr<FeatureList> original_feature_list_;
  scoped_refptr<FieldTrial> field_trial_override_;
  std::unique_ptr<base::FieldTrialList> field_trial_list_;

  DISALLOW_COPY_AND_ASSIGN(ScopedFeatureList);
};

}  // namespace test
}  // namespace base

#endif  // BASE_TEST_SCOPED_FEATURE_LIST_H_