scoped_feature_list.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_TEST_SCOPED_FEATURE_LIST_H_
  5. #define BASE_TEST_SCOPED_FEATURE_LIST_H_
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/feature_list.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/metrics/field_trial.h"
  14. #include "base/metrics/field_trial_params.h"
  15. #include "base/types/pass_key.h"
  16. namespace base {
  17. namespace test {
  18. // ScopedFeatureList resets the global FeatureList instance to a new empty
  19. // instance and restores the original instance upon destruction. When using the
  20. // non-deprecated APIs, a corresponding FieldTrialList is also created.
  21. //
  22. // Note: Re-using the same object is not allowed. To reset the feature
  23. // list and initialize it anew, destroy an existing scoped list and init
  24. // a new one.
  25. //
  26. // If multiple instances of this class are used in a nested fashion, they
  27. // should be destroyed in the opposite order of their Init*() methods being
  28. // called.
  29. //
  30. // ScopedFeatureList needs to be initialized on the main thread (via one of
  31. // Init*() methods) before running code that inspects the state of features,
  32. // such as in the constructor of the test harness.
  33. //
  34. // WARNING: To be clear, in multithreaded test environments (such as browser
  35. // tests) there may background threads using FeatureList before the test body is
  36. // even entered. In these cases it is imperative that ScopedFeatureList be
  37. // initialized BEFORE those threads are started, hence the recommendation to do
  38. // initialization in the test harness's constructor.
  39. class ScopedFeatureList final {
  40. public:
  41. struct Features;
  42. struct FeatureWithStudyGroup;
  43. // Constructs the instance in a non-initialized state.
  44. ScopedFeatureList();
  45. // Shorthand for immediately initializing with InitAndEnableFeature().
  46. explicit ScopedFeatureList(const Feature& enable_feature);
  47. ScopedFeatureList(const ScopedFeatureList&) = delete;
  48. ScopedFeatureList& operator=(const ScopedFeatureList&) = delete;
  49. ~ScopedFeatureList();
  50. struct FeatureAndParams {
  51. FeatureAndParams(const Feature& feature, const FieldTrialParams& params);
  52. ~FeatureAndParams();
  53. FeatureAndParams(const FeatureAndParams& other);
  54. const Feature& feature;
  55. const FieldTrialParams params;
  56. };
  57. // Resets the instance to a non-initialized state.
  58. void Reset();
  59. // Initializes and registers a FeatureList instance without any additional
  60. // enabled or disabled features. Existing state, if any, will be kept.
  61. // This is equivalent to calling InitWithFeatures({}, {}).
  62. void Init();
  63. // Initializes a FeatureList instance without any additional enabled or
  64. // disabled features. Existing state, if any, will be discarded.
  65. // Using this function is not generally recommended, as doing so in a test
  66. // removes the ability to run the test while passing additional
  67. // --enable-features flags from the command line.
  68. void InitWithEmptyFeatureAndFieldTrialLists();
  69. // Initializes a FeatureList instance and FieldTrialLists to be null and
  70. // clear all field trial parameters.
  71. // WARNING: This should not be generally used except for tests that require
  72. // manually instantiating objects like FieldTrialList, for example when
  73. // mocking an EntropyProvider.
  74. void InitWithNullFeatureAndFieldTrialLists();
  75. // WARNING: This method will reset any globally configured features to their
  76. // default values, which can hide feature interaction bugs. Please use
  77. // sparingly. https://crbug.com/713390
  78. // Initializes and registers the given FeatureList instance.
  79. void InitWithFeatureList(std::unique_ptr<FeatureList> feature_list);
  80. // Initializes and registers a FeatureList instance based on the current
  81. // FeatureList and overridden with the given enabled features and the
  82. // specified field trial parameters, and the given disabled features
  83. // with the given enabled and disabled features (comma-separated names).
  84. // Note: This creates a scoped global field trial list if there is not
  85. // currently one.
  86. void InitFromCommandLine(const std::string& enable_features,
  87. const std::string& disable_features);
  88. // Initializes and registers a FeatureList instance based on the current
  89. // FeatureList and overridden with the given enabled and disabled features.
  90. // Any feature overrides already present in the global FeatureList will
  91. // continue to apply, unless they conflict with the overrides passed into this
  92. // method. This is important for testing potentially unexpected feature
  93. // interactions.
  94. void InitWithFeatures(const std::vector<Feature>& enabled_features,
  95. const std::vector<Feature>& disabled_features);
  96. // Initializes and registers a FeatureList instance based on the current
  97. // FeatureList and overridden with single enabled feature.
  98. void InitAndEnableFeature(const Feature& feature);
  99. // Initializes and registers a FeatureList instance based on the current
  100. // FeatureList and overridden with single enabled feature and associated field
  101. // trial parameters.
  102. // Note: this creates a scoped global field trial list if there is not
  103. // currently one.
  104. void InitAndEnableFeatureWithParameters(
  105. const Feature& feature,
  106. const FieldTrialParams& feature_parameters);
  107. // Initializes and registers a FeatureList instance based on the current
  108. // FeatureList and overridden with the given enabled features and the
  109. // specified field trial parameters, and the given disabled features.
  110. // Note: This creates a scoped global field trial list if there is not
  111. // currently one.
  112. void InitWithFeaturesAndParameters(
  113. const std::vector<FeatureAndParams>& enabled_features,
  114. const std::vector<Feature>& disabled_features);
  115. // Initializes and registers a FeatureList instance based on the current
  116. // FeatureList and overridden with single disabled feature.
  117. void InitAndDisableFeature(const Feature& feature);
  118. // Initializes and registers a FeatureList instance based on the current
  119. // FeatureList and overridden with a single feature either enabled or
  120. // disabled depending on |enabled|.
  121. void InitWithFeatureState(const Feature& feature, bool enabled);
  122. private:
  123. using PassKey = base::PassKey<ScopedFeatureList>;
  124. // Initializes and registers a FeatureList instance based on the current
  125. // FeatureList and overridden with the given enabled and disabled features.
  126. // Any feature overrides already present in the global FeatureList will
  127. // continue to apply, unless they conflict with the overrides passed into this
  128. // method.
  129. // Features to enable may be specified through either |enabled_features| or
  130. // |enabled_feature_and_params|, but not both (i.e. one of these must be
  131. // empty).
  132. void InitWithFeaturesImpl(
  133. const std::vector<Feature>& enabled_features,
  134. const std::vector<FeatureAndParams>& enabled_features_and_params,
  135. const std::vector<Feature>& disabled_features,
  136. bool keep_existing_states = true);
  137. // Initializes and registers a FeatureList instance based on the current
  138. // FeatureList and overridden with the given enabled and disabled features.
  139. // Any feature overrides already present in the global FeatureList will
  140. // continue to apply, unless they conflict with the overrides passed into this
  141. // method.
  142. // If |create_associated_field_trials| is true, associated field trials are
  143. // always created independent of feature parameters. If false, field trials
  144. // for features whose parameters are specified will be created.
  145. // If |keep_existing_states| is true, keep all states and override them
  146. // according to the |merged_features|. Otherwise, clear all states and
  147. // newly initialize all states with |merged_features|.
  148. void InitWithMergedFeatures(Features&& merged_features,
  149. bool create_associated_field_trials,
  150. bool keep_existing_states);
  151. bool init_called_ = false;
  152. std::unique_ptr<FeatureList> original_feature_list_;
  153. raw_ptr<base::FieldTrialList> original_field_trial_list_ = nullptr;
  154. std::string original_params_;
  155. std::unique_ptr<base::FieldTrialList> field_trial_list_;
  156. };
  157. } // namespace test
  158. } // namespace base
  159. #endif // BASE_TEST_SCOPED_FEATURE_LIST_H_