Commit 4bbced7e authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

Simplify CommandLineFlags, don't allow .Remove on classes

This is part 1 of 3(?). The end goal is make CommandLineFlags work for
batched tests.

Part 1 (this CL) gets rid of ordering concerns between
class/method/field level flags by only allowing the test methods
themselves to remove flags. We only had one existing case of wanting to
do this, and it was actually a no-op.

Part 2 will split out performing class-level CommandLineFlags parsing,
and method-level CommandLine parsing.

Part 3 will remove the reset() when applying CommandLineFlags
modifications, and have CommandLineFlags undo the changes it makes for
the test/class when the test/class finishes running.

Bug: 989569
Change-Id: Icc2d3c9afca13febf55cc0e5dbaeff882ca2e9b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2216288Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772722}
parent e591db3a
...@@ -72,11 +72,14 @@ public final class CommandLineFlags { ...@@ -72,11 +72,14 @@ public final class CommandLineFlags {
/** /**
* Removes command-line flags from the {@link org.chromium.base.CommandLine} from this test. * Removes command-line flags from the {@link org.chromium.base.CommandLine} from this test.
* *
* Note that this can only remove flags added via {@link Add} above. * Note that this can only be applied to test methods. This restriction is due to complexities
* in resolving the order that annotations are applied, and given how rare it is to need to
* remove command line flags, this annotation must be applied directly to each test method
* wishing to remove a flag.
*/ */
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE}) @Target({ElementType.METHOD})
public @interface Remove { public @interface Remove {
String[] value(); String[] value();
} }
...@@ -93,7 +96,9 @@ public final class CommandLineFlags { ...@@ -93,7 +96,9 @@ public final class CommandLineFlags {
CommandLineInitUtil.initCommandLine(getTestCmdLineFile()); CommandLineInitUtil.initCommandLine(getTestCmdLineFile());
Set<String> enableFeatures = new HashSet<String>(getFeatureValues(ENABLE_FEATURES)); Set<String> enableFeatures = new HashSet<String>(getFeatureValues(ENABLE_FEATURES));
Set<String> disableFeatures = new HashSet<String>(getFeatureValues(DISABLE_FEATURES)); Set<String> disableFeatures = new HashSet<String>(getFeatureValues(DISABLE_FEATURES));
Set<String> flags = getFlags(element);
Set<String> flags = new HashSet<>();
updateFlagsForElement(element, flags);
for (String flag : flags) { for (String flag : flags) {
String[] parsedFlags = flag.split("=", 2); String[] parsedFlags = flag.split("=", 2);
if (parsedFlags.length == 1) { if (parsedFlags.length == 1) {
...@@ -120,32 +125,20 @@ public final class CommandLineFlags { ...@@ -120,32 +125,20 @@ public final class CommandLineFlags {
} }
} }
private static Set<String> getFlags(AnnotatedElement type) {
Set<String> rule_flags = new HashSet<>();
updateFlagsForElement(type, rule_flags);
return rule_flags;
}
private static void updateFlagsForElement(AnnotatedElement element, Set<String> flags) { private static void updateFlagsForElement(AnnotatedElement element, Set<String> flags) {
if (element instanceof Class<?>) { if (element instanceof Class<?>) {
// Get flags from rules within the class. // Get flags from rules within the class.
for (Field field : ((Class<?>) element).getFields()) { for (Field field : ((Class<?>) element).getFields()) {
if (field.isAnnotationPresent(Rule.class)) { if (field.isAnnotationPresent(Rule.class)) {
// The order in which fields are returned is undefined, so, for consistency, // The order in which fields are returned is undefined, so, for consistency,
// a rule must not remove a flag added by a different rule. Ensure this by // a rule must only ever add flags.
// initially getting the flags into a new set. updateFlagsForElement(field.getType(), flags);
Set<String> rule_flags = getFlags(field.getType());
flags.addAll(rule_flags);
} }
} }
for (Method method : ((Class<?>) element).getMethods()) { for (Method method : ((Class<?>) element).getMethods()) {
if (method.isAnnotationPresent(Rule.class)) { Assert.assertFalse("@Rule annotations on methods are unsupported. Cause: "
// The order in which methods are returned is undefined, so, for consistency, + method.toGenericString(),
// a rule must not remove a flag added by a different rule. Ensure this by method.isAnnotationPresent(Rule.class));
// initially getting the flags into a new set.
Set<String> rule_flags = getFlags(method.getReturnType());
flags.addAll(rule_flags);
}
} }
} }
......
...@@ -13,6 +13,7 @@ import org.robolectric.annotation.Config; ...@@ -13,6 +13,7 @@ import org.robolectric.annotation.Config;
import org.chromium.base.test.params.ParameterizedCommandLineFlags; import org.chromium.base.test.params.ParameterizedCommandLineFlags;
import org.chromium.base.test.params.ParameterizedCommandLineFlags.Switches; import org.chromium.base.test.params.ParameterizedCommandLineFlags.Switches;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CommandLineFlags;
import java.util.Arrays; import java.util.Arrays;
...@@ -31,9 +32,8 @@ public class TestListInstrumentationRunListenerTest { ...@@ -31,9 +32,8 @@ public class TestListInstrumentationRunListenerTest {
public void testB() {} public void testB() {}
} }
@CommandLineFlags.Remove("hello") @Batch("foo")
private static class ChildClass extends ParentClass { private static class ChildClass extends ParentClass {}
}
private static class Groups { private static class Groups {
// clang-format off // clang-format off
...@@ -141,8 +141,8 @@ public class TestListInstrumentationRunListenerTest { ...@@ -141,8 +141,8 @@ public class TestListInstrumentationRunListenerTest {
" 'CommandLineFlags$Add': {", " 'CommandLineFlags$Add': {",
" 'value': ['hello']", " 'value': ['hello']",
" },", " },",
" 'CommandLineFlags$Remove': {", " 'Batch': {",
" 'value': ['hello']", " 'value': 'foo'",
" }", " }",
"}" "}"
); );
...@@ -201,4 +201,3 @@ public class TestListInstrumentationRunListenerTest { ...@@ -201,4 +201,3 @@ public class TestListInstrumentationRunListenerTest {
Assert.assertEquals(expectedJsonString, json.toString()); Assert.assertEquals(expectedJsonString, json.toString());
} }
} }
...@@ -16,12 +16,13 @@ import android.support.test.filters.SmallTest; ...@@ -16,12 +16,13 @@ import android.support.test.filters.SmallTest;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.CommandLine;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.FlakyTest;
...@@ -45,7 +46,6 @@ import java.util.concurrent.TimeoutException; ...@@ -45,7 +46,6 @@ import java.util.concurrent.TimeoutException;
* Tests for the first run experience. * Tests for the first run experience.
*/ */
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Remove(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
public class FirstRunTest { public class FirstRunTest {
@Rule @Rule
public SyncTestRule mSyncTestRule = new SyncTestRule() { public SyncTestRule mSyncTestRule = new SyncTestRule() {
...@@ -118,6 +118,12 @@ public class FirstRunTest { ...@@ -118,6 +118,12 @@ public class FirstRunTest {
private final TestObserver mTestObserver = new TestObserver(); private final TestObserver mTestObserver = new TestObserver();
private FirstRunActivity mActivity; private FirstRunActivity mActivity;
@Before
public void setUp() {
Assert.assertFalse(
CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE));
}
@After @After
public void tearDown() { public void tearDown() {
if (mActivity != null) mActivity.finish(); if (mActivity != null) mActivity.finish();
......
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