Commit 2bab8d57 authored by Xi Han's avatar Xi Han Committed by Commit Bot

Make field trials set from CommandLine work for CachedFeatureFlags.

Bug: 1056327
Change-Id: I490f176ae56d5fc08b76df0777e0d5af1529b0f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2082317Reviewed-by: default avatarWei-Yin Chen (陳威尹) <wychen@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarHenrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Xi Han <hanxi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#749247}
parent 93b817d1
...@@ -30,6 +30,15 @@ public abstract class BaseSwitches { ...@@ -30,6 +30,15 @@ public abstract class BaseSwitches {
// Enables the reached code profiler. // Enables the reached code profiler.
public static final String ENABLE_REACHED_CODE_PROFILER = "enable-reached-code-profiler"; public static final String ENABLE_REACHED_CODE_PROFILER = "enable-reached-code-profiler";
// Comma-separated list of feature names to enable.
public static final String ENABLE_FEATURES = "enable-features";
// This option can be used to force field trials when testing changes locally.
public static final String FORCE_FIELD_TRIALS_SWITCH = "force-fieldtrials";
// The field trial parameters and their values when testing changes locally.
public static final String FORCE_FIELD_TRIAL_PARAMS_SWITCH = "force-fieldtrial-params";
// Prevent instantiation. // Prevent instantiation.
private BaseSwitches() {} private BaseSwitches() {}
} }
...@@ -14,6 +14,7 @@ chrome_test_java_sources = [ ...@@ -14,6 +14,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java", "javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java",
"javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java", "javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java",
"javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java", "javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java",
"javatests/src/org/chromium/chrome/browser/FieldTrialsTest.java",
"javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java",
"javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java", "javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java",
"javatests/src/org/chromium/chrome/browser/InstalledAppTest.java", "javatests/src/org/chromium/chrome/browser/InstalledAppTest.java",
......
...@@ -51,6 +51,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; ...@@ -51,6 +51,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher; import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.FieldTrials;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.ui.test.util.UiRestriction; import org.chromium.ui.test.util.UiRestriction;
...@@ -77,6 +78,10 @@ public class StartSurfaceTest { ...@@ -77,6 +78,10 @@ public class StartSurfaceTest {
@Before @Before
public void setUp() { public void setUp() {
// TODO(https://crbug.com/1060622): Removes the if check block.
if (StartSurfaceConfiguration.isStartSurfaceSinglePaneEnabled()) {
FieldTrials.getInstance().reset();
}
CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, true); CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, true);
EmbeddedTestServer testServer = EmbeddedTestServer testServer =
......
// Copyright 2020 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.
package org.chromium.chrome.browser;
import android.support.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.flags.BooleanCachedFieldTrialParameter;
import org.chromium.chrome.browser.flags.CachedFeatureFlags;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.DoubleCachedFieldTrialParameter;
import org.chromium.chrome.browser.flags.IntCachedFieldTrialParameter;
import org.chromium.chrome.browser.flags.StringCachedFieldTrialParameter;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.FieldTrials;
/**
* Tests for {@link FieldTrials}.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
public final class FieldTrialsTest {
private static final String sFeature1 = ChromeFeatureList.TEST_DEFAULT_DISABLED;
private static final String sFeature2 = ChromeFeatureList.TEST_DEFAULT_ENABLED;
@Rule
public ChromeActivityTestRule<? extends ChromeActivity> mActivityRule =
new ChromeActivityTestRule(ChromeTabbedActivity.class);
@Rule
public TestRule mProcessor = new Features.InstrumentationProcessor();
@Before
public void setup() {
mActivityRule.startMainActivityOnBlankPage();
}
@Test
@SmallTest
// clang-format off
@CommandLineFlags.Add({"enable-features=" + sFeature1 + "<Study",
"force-fieldtrials=Study/Group", "force-fieldtrial-params=Study.Group:a1/b1"})
public void testOneFeatureTrialGroup() {
// clang-format on
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature1));
Assert.assertEquals("b1", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a1"));
Assert.assertTrue(CachedFeatureFlags.isEnabled(sFeature1));
StringCachedFieldTrialParameter parameterA1 =
new StringCachedFieldTrialParameter(sFeature1, "a1", "default");
Assert.assertEquals("b1", CachedFeatureFlags.getValue(parameterA1));
}
@Test
@SmallTest
// clang-format off
@CommandLineFlags.Add({"enable-features=" + sFeature1 + "<Study," + sFeature2 + "<Study",
"force-fieldtrials=Study/Group", "force-fieldtrial-params=Study.Group:a1/b1/a2/b2"})
public void testTwoFeaturesWithSameTrialGroup() {
// clang-format on
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature1));
Assert.assertEquals("b1", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a1"));
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature1));
Assert.assertEquals("b2", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a2"));
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature2));
Assert.assertEquals("b1", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a1"));
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature2));
Assert.assertEquals("b2", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a2"));
Assert.assertTrue(CachedFeatureFlags.isEnabled(sFeature1));
Assert.assertTrue(CachedFeatureFlags.isEnabled(sFeature2));
StringCachedFieldTrialParameter parameterA1 =
new StringCachedFieldTrialParameter(sFeature1, "a1", "");
Assert.assertEquals("b1", CachedFeatureFlags.getValue(parameterA1));
StringCachedFieldTrialParameter parameterA2 =
new StringCachedFieldTrialParameter(sFeature1, "a2", "");
Assert.assertEquals("b2", CachedFeatureFlags.getValue(parameterA2));
StringCachedFieldTrialParameter parameterB1 =
new StringCachedFieldTrialParameter(sFeature2, "a1", "");
Assert.assertEquals("b1", CachedFeatureFlags.getValue(parameterB1));
StringCachedFieldTrialParameter parameterB2 =
new StringCachedFieldTrialParameter(sFeature2, "a2", "");
Assert.assertEquals("b2", CachedFeatureFlags.getValue(parameterB2));
}
@Test
@SmallTest
// clang-format off
@CommandLineFlags.Add({"enable-features=" + sFeature1 + "<Study1," + sFeature2 + "<Study2",
"force-fieldtrials=Study1/Group1/Study2/Group2",
"force-fieldtrial-params=Study1.Group1:a1/0.5/a2/100,Study2.Group2:a3/true"})
public void testTwoFeaturesWithDifferentTrialGroupsAndMutipleTypesOfValues() {
// clang-format on
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature1));
Assert.assertTrue(ChromeFeatureList.isEnabled(sFeature2));
Assert.assertEquals("0.5", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a1"));
Assert.assertEquals("100", ChromeFeatureList.getFieldTrialParamByFeature(sFeature1, "a2"));
Assert.assertEquals("true", ChromeFeatureList.getFieldTrialParamByFeature(sFeature2, "a3"));
Assert.assertTrue(CachedFeatureFlags.isEnabled(sFeature1));
Assert.assertTrue(CachedFeatureFlags.isEnabled(sFeature2));
DoubleCachedFieldTrialParameter parameterA1 =
new DoubleCachedFieldTrialParameter(sFeature1, "a1", 0.1);
Assert.assertEquals(0.5, CachedFeatureFlags.getValue(parameterA1), 1e-7);
IntCachedFieldTrialParameter parameterA2 =
new IntCachedFieldTrialParameter(sFeature1, "a2", 0);
Assert.assertEquals(100, CachedFeatureFlags.getValue(parameterA2));
BooleanCachedFieldTrialParameter parameterB =
new BooleanCachedFieldTrialParameter(sFeature2, "a3", false);
Assert.assertEquals(true, CachedFeatureFlags.getValue(parameterB));
}
}
...@@ -24,6 +24,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; ...@@ -24,6 +24,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations; import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.browser.FieldTrials;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.test.util.UiRestriction; import org.chromium.ui.test.util.UiRestriction;
...@@ -42,6 +43,9 @@ public class BottomToolbarWithStartSurfaceTest { ...@@ -42,6 +43,9 @@ public class BottomToolbarWithStartSurfaceTest {
@Before @Before
public void setUp() { public void setUp() {
// TODO(https://crbug.com/1060622): Removes this.
FieldTrials.getInstance().reset();
CachedFeatureFlags.setForTesting(ChromeFeatureList.CHROME_DUET, true); CachedFeatureFlags.setForTesting(ChromeFeatureList.CHROME_DUET, true);
CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, true); CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, true);
} }
......
...@@ -10,6 +10,7 @@ android_library("java") { ...@@ -10,6 +10,7 @@ android_library("java") {
"android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java", "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java",
"android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameter.java",
"android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java", "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java",
"android/java/src/org/chromium/chrome/browser/flags/DoubleCachedFieldTrialParameter.java",
"android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java",
"android/java/src/org/chromium/chrome/browser/flags/StringCachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/StringCachedFieldTrialParameter.java",
] ]
......
...@@ -9,6 +9,7 @@ import androidx.annotation.VisibleForTesting; ...@@ -9,6 +9,7 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.FieldTrialList; import org.chromium.base.FieldTrialList;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.CheckDiscard;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
...@@ -118,6 +119,8 @@ public class CachedFeatureFlags { ...@@ -118,6 +119,8 @@ public class CachedFeatureFlags {
private static Map<String, String> sStringValuesReturned = new HashMap<>(); private static Map<String, String> sStringValuesReturned = new HashMap<>();
private static Map<String, Integer> sIntValuesReturned = new HashMap<>(); private static Map<String, Integer> sIntValuesReturned = new HashMap<>();
private static Map<String, Double> sDoubleValuesReturned = new HashMap<>(); private static Map<String, Double> sDoubleValuesReturned = new HashMap<>();
@CheckDiscard("Validation is performed in tests and in debug builds.")
private static Map<String, String> sOverridesTestFeatures;
private static String sReachedCodeProfilerTrialGroup; private static String sReachedCodeProfilerTrialGroup;
/** /**
...@@ -191,6 +194,7 @@ public class CachedFeatureFlags { ...@@ -191,6 +194,7 @@ public class CachedFeatureFlags {
@VisibleForTesting @VisibleForTesting
public static void setFeaturesForTesting(Map<String, Boolean> features) { public static void setFeaturesForTesting(Map<String, Boolean> features) {
assert features != null; assert features != null;
sOverridesTestFeatures = new HashMap<>();
for (Map.Entry<String, Boolean> entry : features.entrySet()) { for (Map.Entry<String, Boolean> entry : features.entrySet()) {
String key = entry.getKey(); String key = entry.getKey();
...@@ -203,6 +207,14 @@ public class CachedFeatureFlags { ...@@ -203,6 +207,14 @@ public class CachedFeatureFlags {
} }
} }
@VisibleForTesting
public static void setFieldTrialsForTesting(
String featureName, String variationName, String variationValue) {
StringCachedFieldTrialParameter parameter =
new StringCachedFieldTrialParameter(featureName, variationName, variationValue);
sOverridesTestFeatures.put(parameter.getSharedPreferenceKey(), variationValue);
}
/** /**
* Caches flags that must take effect on startup but are set via native code. * Caches flags that must take effect on startup but are set via native code.
*/ */
...@@ -274,6 +286,17 @@ public class CachedFeatureFlags { ...@@ -274,6 +286,17 @@ public class CachedFeatureFlags {
parameter.getSharedPreferenceKey(), parameter.getDefaultValue()); parameter.getSharedPreferenceKey(), parameter.getDefaultValue());
} }
/**
* TODO(crbug.com/1012975): Move this to DoubleCachedFieldTrialParameter when
* CachedFeatureFlags is in chrome/browser/flags.
*
* @return the value of the field trial parameter that should be used in this run.
*/
public static double getValue(DoubleCachedFieldTrialParameter parameter) {
return getConsistentDoubleValue(
parameter.getSharedPreferenceKey(), parameter.getDefaultValue());
}
/** /**
* Cache whether warming up network service process is enabled, so that the value * Cache whether warming up network service process is enabled, so that the value
* can be made available immediately on next start up. * can be made available immediately on next start up.
...@@ -320,6 +343,13 @@ public class CachedFeatureFlags { ...@@ -320,6 +343,13 @@ public class CachedFeatureFlags {
} }
static boolean getConsistentBooleanValue(String preferenceName, boolean defaultValue) { static boolean getConsistentBooleanValue(String preferenceName, boolean defaultValue) {
if (sOverridesTestFeatures != null) {
String value = sOverridesTestFeatures.get(preferenceName);
if (value != null) {
return Boolean.valueOf(value);
}
}
Boolean flag = sBoolValuesReturned.get(preferenceName); Boolean flag = sBoolValuesReturned.get(preferenceName);
if (flag == null) { if (flag == null) {
flag = SharedPreferencesManager.getInstance().readBoolean(preferenceName, defaultValue); flag = SharedPreferencesManager.getInstance().readBoolean(preferenceName, defaultValue);
...@@ -329,6 +359,13 @@ public class CachedFeatureFlags { ...@@ -329,6 +359,13 @@ public class CachedFeatureFlags {
} }
static String getConsistentStringValue(String preferenceName, String defaultValue) { static String getConsistentStringValue(String preferenceName, String defaultValue) {
if (sOverridesTestFeatures != null) {
String stringValue = sOverridesTestFeatures.get(preferenceName);
if (stringValue != null) {
return stringValue;
}
}
String value = sStringValuesReturned.get(preferenceName); String value = sStringValuesReturned.get(preferenceName);
if (value == null) { if (value == null) {
value = SharedPreferencesManager.getInstance().readString(preferenceName, defaultValue); value = SharedPreferencesManager.getInstance().readString(preferenceName, defaultValue);
...@@ -338,6 +375,13 @@ public class CachedFeatureFlags { ...@@ -338,6 +375,13 @@ public class CachedFeatureFlags {
} }
static int getConsistentIntValue(String preferenceName, int defaultValue) { static int getConsistentIntValue(String preferenceName, int defaultValue) {
if (sOverridesTestFeatures != null) {
String stringValue = sOverridesTestFeatures.get(preferenceName);
if (stringValue != null) {
return Integer.valueOf(stringValue);
}
}
Integer value = sIntValuesReturned.get(preferenceName); Integer value = sIntValuesReturned.get(preferenceName);
if (value == null) { if (value == null) {
value = SharedPreferencesManager.getInstance().readInt(preferenceName, defaultValue); value = SharedPreferencesManager.getInstance().readInt(preferenceName, defaultValue);
...@@ -347,6 +391,13 @@ public class CachedFeatureFlags { ...@@ -347,6 +391,13 @@ public class CachedFeatureFlags {
} }
static double getConsistentDoubleValue(String preferenceName, double defaultValue) { static double getConsistentDoubleValue(String preferenceName, double defaultValue) {
if (sOverridesTestFeatures != null) {
String stringValue = sOverridesTestFeatures.get(preferenceName);
if (stringValue != null) {
return Double.valueOf(stringValue);
}
}
Double value = sDoubleValuesReturned.get(preferenceName); Double value = sDoubleValuesReturned.get(preferenceName);
if (value == null) { if (value == null) {
value = SharedPreferencesManager.getInstance().readDouble(preferenceName, defaultValue); value = SharedPreferencesManager.getInstance().readDouble(preferenceName, defaultValue);
...@@ -370,6 +421,9 @@ public class CachedFeatureFlags { ...@@ -370,6 +421,9 @@ public class CachedFeatureFlags {
sStringValuesReturned.clear(); sStringValuesReturned.clear();
sIntValuesReturned.clear(); sIntValuesReturned.clear();
sDoubleValuesReturned.clear(); sDoubleValuesReturned.clear();
if (sOverridesTestFeatures != null) {
sOverridesTestFeatures.clear();
}
} }
@VisibleForTesting @VisibleForTesting
......
...@@ -174,6 +174,7 @@ android_library("chrome_java_test_support") { ...@@ -174,6 +174,7 @@ android_library("chrome_java_test_support") {
"javatests/src/org/chromium/chrome/test/util/ViewUtils.java", "javatests/src/org/chromium/chrome/test/util/ViewUtils.java",
"javatests/src/org/chromium/chrome/test/util/WaitForFocusHelper.java", "javatests/src/org/chromium/chrome/test/util/WaitForFocusHelper.java",
"javatests/src/org/chromium/chrome/test/util/browser/Features.java", "javatests/src/org/chromium/chrome/test/util/browser/Features.java",
"javatests/src/org/chromium/chrome/test/util/browser/FieldTrials.java",
"javatests/src/org/chromium/chrome/test/util/browser/LocationSettingsTestUtil.java", "javatests/src/org/chromium/chrome/test/util/browser/LocationSettingsTestUtil.java",
"javatests/src/org/chromium/chrome/test/util/browser/RecyclerViewTestUtils.java", "javatests/src/org/chromium/chrome/test/util/browser/RecyclerViewTestUtils.java",
"javatests/src/org/chromium/chrome/test/util/browser/TabLoadObserver.java", "javatests/src/org/chromium/chrome/test/util/browser/TabLoadObserver.java",
......
...@@ -97,6 +97,7 @@ public class Features { ...@@ -97,6 +97,7 @@ public class Features {
mergeFeatureLists("enable-features", true); mergeFeatureLists("enable-features", true);
mergeFeatureLists("disable-features", false); mergeFeatureLists("disable-features", false);
CachedFeatureFlags.setFeaturesForTesting(mRegisteredState); CachedFeatureFlags.setFeaturesForTesting(mRegisteredState);
FieldTrials.getInstance().applyFieldTrials();
} }
/** /**
...@@ -127,6 +128,7 @@ public class Features { ...@@ -127,6 +128,7 @@ public class Features {
ChromeFeatureList.setTestFeatures(null); ChromeFeatureList.setTestFeatures(null);
ChromeFeatureList.resetTestCanUseDefaultsForTesting(); ChromeFeatureList.resetTestCanUseDefaultsForTesting();
CachedFeatureFlags.resetFlagsForTesting(); CachedFeatureFlags.resetFlagsForTesting();
FieldTrials.getInstance().reset();
} }
/** /**
...@@ -147,6 +149,12 @@ public class Features { ...@@ -147,6 +149,12 @@ public class Features {
* {@link CommandLine}. * {@link CommandLine}.
*/ */
public static class InstrumentationProcessor extends Processor { public static class InstrumentationProcessor extends Processor {
@Override
protected void collectFeatures() {
super.collectFeatures();
FieldTrials.getInstance().collectFieldTrials();
}
@Override @Override
protected void applyFeatures() { protected void applyFeatures() {
getInstance().applyForInstrumentation(); getInstance().applyForInstrumentation();
...@@ -176,7 +184,7 @@ public class Features { ...@@ -176,7 +184,7 @@ public class Features {
protected abstract void applyFeatures(); protected abstract void applyFeatures();
private void collectFeatures() { protected void collectFeatures() {
for (Annotation annotation : getAnnotations()) { for (Annotation annotation : getAnnotations()) {
if (annotation instanceof EnableFeatures) { if (annotation instanceof EnableFeatures) {
getInstance().enable(((EnableFeatures) annotation).value()); getInstance().enable(((EnableFeatures) annotation).value());
......
// Copyright 2020 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.
package org.chromium.chrome.test.util.browser;
import org.chromium.base.BaseSwitches;
import org.chromium.base.CommandLine;
import org.chromium.base.Log;
import org.chromium.chrome.browser.flags.CachedFeatureFlags;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Helps with setting Field Trial parameters during instrumentation tests. It parses the field
* trials info from CommandLine, and applies the overrides to {@link CachedFeatureFlags}.
*/
public class FieldTrials {
private static FieldTrials sInstance;
private Map<String, Map<String, String>> mTrialToParamValueMap = new HashMap<>();
private Map<String, Set<String>> mTrialToFeatureNameMap = new HashMap<>();
private static final String TAG = "FieldTrials";
private FieldTrials() {}
public static FieldTrials getInstance() {
if (sInstance == null) sInstance = new FieldTrials();
return sInstance;
}
/**
* Collects field trial info from the CommandLine.
*/
public void collectFieldTrials() {
CommandLine commandLine = CommandLine.getInstance();
String forceFieldTrials =
commandLine.getSwitchValue(BaseSwitches.FORCE_FIELD_TRIALS_SWITCH);
String forceFieldTrialParams =
commandLine.getSwitchValue(BaseSwitches.FORCE_FIELD_TRIAL_PARAMS_SWITCH);
String enableFeatures = commandLine.getSwitchValue(BaseSwitches.ENABLE_FEATURES);
if (forceFieldTrials == null || forceFieldTrialParams == null || enableFeatures == null) {
return;
}
Set<String> enableFeaturesSet = new HashSet<>();
Collections.addAll(enableFeaturesSet, enableFeatures.split(","));
try {
updateTrialToParamValueMap(forceFieldTrialParams.split(","));
updateTrialFeatureMap(forceFieldTrials.split("/"), enableFeaturesSet);
} catch (Exception e) {
Log.e(TAG,
"The format of field trials parameters declared isn't correct:"
+ BaseSwitches.FORCE_FIELD_TRIALS_SWITCH + "=" + forceFieldTrials + ", "
+ BaseSwitches.FORCE_FIELD_TRIAL_PARAMS_SWITCH + "="
+ forceFieldTrialParams + ".");
return;
}
}
/**
* Builds a map for each trial to a set of <param, value> pairs.
* @param fieldTrialParams The format is: {"Trial1.Group1:param1/value1/param2/value2",
* "Trial2.Group2:param3/value3"}
*/
private void updateTrialToParamValueMap(String[] fieldTrialParams) throws Exception {
for (String fieldTrialParam : fieldTrialParams) {
// The format of {@link fieldTrialParam} is:
// "Trial1.Group1:param1/value1/param2/value2".
int separatorIndex = fieldTrialParam.indexOf(".");
if (separatorIndex == -1) {
throw new Exception("The trial name and group name should be"
+ " separated by a '.'.");
}
String trialName = fieldTrialParam.substring(0, separatorIndex);
String[] groupParamPairs = fieldTrialParam.substring(separatorIndex + 1).split(":");
if (groupParamPairs.length != 2) {
throw new Exception("The group name and field trial parameters"
+ " should be separated by a ':'.");
}
String[] paramValuePair = groupParamPairs[1].split("/");
if (paramValuePair.length % 2 != 0) {
throw new Exception("The param and value of the field trial group:" + trialName
+ "." + groupParamPairs[0] + " isn't paired up!");
}
Map<String, String> paramValueMap = mTrialToParamValueMap.get(trialName);
if (paramValueMap == null) {
paramValueMap = new HashMap<>();
mTrialToParamValueMap.put(trialName, paramValueMap);
}
for (int count = 0; count < paramValuePair.length; count += 2) {
paramValueMap.put(paramValuePair[count], paramValuePair[count + 1]);
}
}
}
/**
* Builds a map for each trial to a set of features.
* @param trialGroups The format is {"Trial1", "Group1", "Trial2", "Group2"}
* @param enableFeatures The format is {"Feature1<Trial1", "Feature2", "Feature3<Trial2"}
*/
private void updateTrialFeatureMap(String[] trialGroups, Set<String> enableFeatures)
throws Exception {
if (trialGroups.length % 2 != 0) {
throw new Exception("The field trial and group info aren't paired up!");
}
for (String enableFeature : enableFeatures) {
String[] featureTrial = enableFeature.split("<");
if (featureTrial.length < 2) continue;
String featureName = featureTrial[0];
String trialName = featureTrial[1];
Set<String> featureSet = mTrialToFeatureNameMap.get(trialName);
if (featureSet == null) {
featureSet = new HashSet<>();
mTrialToFeatureNameMap.put(trialName, featureSet);
}
featureSet.add(featureName);
}
}
/**
* Applies the <feature, param, value> info to CachedFeatureFlags, and enables these features
* in CachedFeatureFlags.
*/
public void applyFieldTrials() {
if (mTrialToFeatureNameMap.isEmpty() || mTrialToParamValueMap.isEmpty()) {
return;
}
for (Map.Entry<String, Map<String, String>> entry : mTrialToParamValueMap.entrySet()) {
String trialName = entry.getKey();
Set<String> featureSet = mTrialToFeatureNameMap.get(trialName);
for (String featureName : featureSet) {
Map<String, String> params = entry.getValue();
for (Map.Entry<String, String> param : params.entrySet()) {
CachedFeatureFlags.setForTesting(featureName, true);
CachedFeatureFlags.setFieldTrialsForTesting(
featureName, param.getKey(), param.getValue());
}
}
}
}
public void reset() {
mTrialToFeatureNameMap.clear();
mTrialToParamValueMap.clear();
sInstance = null;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment