summaryrefslogtreecommitdiff
path: root/base/test/android/junit/src/org/chromium
diff options
context:
space:
mode:
Diffstat (limited to 'base/test/android/junit/src/org/chromium')
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java49
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java64
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java119
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java72
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java32
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java105
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java77
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java133
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java108
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java201
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java193
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java95
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java129
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java130
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java132
15 files changed, 1639 insertions, 0 deletions
diff --git a/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java b/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java
new file mode 100644
index 0000000000..3ca756ad9a
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java
@@ -0,0 +1,49 @@
+// Copyright 2015 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.base.test;
+
+import org.junit.runners.model.InitializationError;
+import org.robolectric.DefaultTestLifecycle;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.TestLifecycle;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.CommandLine;
+import org.chromium.base.ContextUtils;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+import java.lang.reflect.Method;
+
+/**
+ * A Robolectric Test Runner that initializes base globals.
+ */
+public class BaseRobolectricTestRunner extends LocalRobolectricTestRunner {
+ /**
+ * Enables a per-test setUp / tearDown hook.
+ */
+ public static class BaseTestLifecycle extends DefaultTestLifecycle {
+ @Override
+ public void beforeTest(Method method) {
+ ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
+ CommandLine.init(null);
+ super.beforeTest(method);
+ }
+
+ @Override
+ public void afterTest(Method method) {
+ ApplicationStatus.destroyForJUnitTests();
+ super.afterTest(method);
+ }
+ }
+
+ public BaseRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ @Override
+ protected Class<? extends TestLifecycle> getTestLifecycleClass() {
+ return BaseTestLifecycle.class;
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java b/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java
new file mode 100644
index 0000000000..722bd1acfe
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java
@@ -0,0 +1,64 @@
+// Copyright 2017 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.base.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.Statement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test SetUpStatement is working as intended with SetUpTestRule.
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class SetUpStatementTest {
+ private Statement mBase;
+ private SetUpTestRule<TestRule> mRule;
+ private List<Integer> mList;
+
+ @Before
+ public void setUp() {
+ mBase = new Statement() {
+ @Override
+ public void evaluate() {
+ mList.add(1);
+ }
+ };
+ mList = new ArrayList<>();
+ mRule = new SetUpTestRule<TestRule>() {
+ @Override
+ public void setUp() {
+ mList.add(0);
+ }
+
+ @Override
+ public TestRule shouldSetUp(boolean toSetUp) {
+ return null;
+ }
+ };
+ }
+
+ @Test
+ public void testSetUpStatementShouldSetUp() throws Throwable {
+ SetUpStatement statement = new SetUpStatement(mBase, mRule, true);
+ statement.evaluate();
+ Integer[] expected = {0, 1};
+ Assert.assertArrayEquals(expected, mList.toArray());
+ }
+
+ @Test
+ public void testSetUpStatementShouldNotSetUp() throws Throwable {
+ SetUpStatement statement = new SetUpStatement(mBase, mRule, false);
+ statement.evaluate();
+ Integer[] expected = {1};
+ Assert.assertArrayEquals(expected, mList.toArray());
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java b/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java
new file mode 100644
index 0000000000..63fa5601fb
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java
@@ -0,0 +1,119 @@
+// Copyright 2017 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.base.test;
+
+import static org.chromium.base.test.TestListInstrumentationRunListener.getAnnotationJSON;
+import static org.chromium.base.test.TestListInstrumentationRunListener.getTestMethodJSON;
+
+import org.json.JSONObject;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.util.CommandLineFlags;
+
+import java.util.Arrays;
+
+/**
+ * Robolectric test to ensure static methods in TestListInstrumentationRunListener works properly.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class TestListInstrumentationRunListenerTest {
+ @CommandLineFlags.Add("hello")
+ private static class ParentClass {
+ public void testA() {}
+
+ @CommandLineFlags.Add("world")
+ public void testB() {}
+ }
+
+ @CommandLineFlags.Remove("hello")
+ private static class ChildClass extends ParentClass {
+ }
+
+ @Test
+ public void testGetTestMethodJSON_testA() throws Throwable {
+ Description desc = Description.createTestDescription(
+ ParentClass.class, "testA",
+ ParentClass.class.getMethod("testA").getAnnotations());
+ JSONObject json = getTestMethodJSON(desc);
+ String expectedJsonString =
+ "{"
+ + "'method': 'testA',"
+ + "'annotations': {}"
+ + "}";
+ expectedJsonString = expectedJsonString
+ .replaceAll("\\s", "")
+ .replaceAll("'", "\"");
+ Assert.assertEquals(expectedJsonString, json.toString());
+ }
+
+ @Test
+ public void testGetTestMethodJSON_testB() throws Throwable {
+ Description desc = Description.createTestDescription(
+ ParentClass.class, "testB",
+ ParentClass.class.getMethod("testB").getAnnotations());
+ JSONObject json = getTestMethodJSON(desc);
+ String expectedJsonString =
+ "{"
+ + "'method': 'testB',"
+ + "'annotations': {"
+ + " 'Add': {"
+ + " 'value': ['world']"
+ + " }"
+ + " }"
+ + "}";
+ expectedJsonString = expectedJsonString
+ .replaceAll("\\s", "")
+ .replaceAll("'", "\"");
+ Assert.assertEquals(expectedJsonString, json.toString());
+ }
+
+
+ @Test
+ public void testGetTestMethodJSONForInheritedClass() throws Throwable {
+ Description desc = Description.createTestDescription(
+ ChildClass.class, "testB",
+ ChildClass.class.getMethod("testB").getAnnotations());
+ JSONObject json = getTestMethodJSON(desc);
+ String expectedJsonString =
+ "{"
+ + "'method': 'testB',"
+ + "'annotations': {"
+ + " 'Add': {"
+ + " 'value': ['world']"
+ + " }"
+ + " }"
+ + "}";
+ expectedJsonString = expectedJsonString
+ .replaceAll("\\s", "")
+ .replaceAll("'", "\"");
+ Assert.assertEquals(expectedJsonString, json.toString());
+ }
+
+ @Test
+ public void testGetAnnotationJSONForParentClass() throws Throwable {
+ JSONObject json = getAnnotationJSON(Arrays.asList(ParentClass.class.getAnnotations()));
+ String expectedJsonString = "{'Add':{'value':['hello']}}";
+ expectedJsonString = expectedJsonString
+ .replaceAll("\\s", "")
+ .replaceAll("'", "\"");
+ Assert.assertEquals(expectedJsonString, json.toString());
+ }
+
+ @Test
+ public void testGetAnnotationJSONForChildClass() throws Throwable {
+ JSONObject json = getAnnotationJSON(Arrays.asList(ChildClass.class.getAnnotations()));
+ String expectedJsonString = "{'Add':{'value':['hello']},'Remove':{'value':['hello']}}";
+ expectedJsonString = expectedJsonString
+ .replaceAll("\\s", "")
+ .replaceAll("'", "\"");
+ Assert.assertEquals(expectedJsonString, json.toString());
+ }
+}
+
diff --git a/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java b/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java
new file mode 100644
index 0000000000..c75e7948f0
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java
@@ -0,0 +1,72 @@
+// Copyright 2015 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.base.test.asynctask;
+
+import static org.junit.Assert.fail;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowApplication;
+
+import org.chromium.base.AsyncTask;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Executes async tasks on a background thread and waits on the result on the main thread.
+ * This is useful for users of AsyncTask on Roboelectric who check if the code is actually being
+ * run on a background thread (i.e. through the use of {@link ThreadUtils#runningOnUiThread()}).
+ * @param <Params> type for execute function parameters
+ * @param <Progress> type for reporting Progress
+ * @param <Result> type for reporting result
+ */
+@Implements(AsyncTask.class)
+public class BackgroundShadowAsyncTask<Params, Progress, Result>
+ extends ShadowAsyncTask<Params, Progress, Result> {
+ private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
+
+ @Override
+ @Implementation
+ @SafeVarargs
+ public final AsyncTask<Params, Progress, Result> execute(final Params... params) {
+ try {
+ return sExecutorService
+ .submit(new Callable<AsyncTask<Params, Progress, Result>>() {
+ @Override
+ public AsyncTask<Params, Progress, Result> call() throws Exception {
+ return BackgroundShadowAsyncTask.super.execute(params);
+ }
+ })
+ .get();
+ } catch (Exception ex) {
+ fail(ex.getMessage());
+ return null;
+ }
+ }
+
+ @Override
+ @Implementation
+ public final Result get() {
+ try {
+ runBackgroundTasks();
+ return BackgroundShadowAsyncTask.super.get();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static void runBackgroundTasks() throws Exception {
+ sExecutorService
+ .submit(new Runnable() {
+ @Override
+ public void run() {
+ ShadowApplication.runBackgroundTasks();
+ }
+ })
+ .get();
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java b/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java
new file mode 100644
index 0000000000..bd581c1377
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java
@@ -0,0 +1,32 @@
+// Copyright 2015 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.base.test.asynctask;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.AsyncTask;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Forces async tasks to execute with the default executor.
+ * This works around Robolectric not working out of the box with custom executors.
+ *
+ * @param <Params>
+ * @param <Progress>
+ * @param <Result>
+ */
+@Implements(AsyncTask.class)
+public class CustomShadowAsyncTask<Params, Progress, Result>
+ extends ShadowAsyncTask<Params, Progress, Result> {
+ @SafeVarargs
+ @Override
+ @Implementation
+ public final AsyncTask<Params, Progress, Result> executeOnExecutor(
+ Executor executor, Params... params) {
+ return super.execute(params);
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java
new file mode 100644
index 0000000000..6ffccad44b
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java
@@ -0,0 +1,105 @@
+// Copyright 2017 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.base.test.params;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
+import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
+import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterAfter;
+import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore;
+import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example test that uses ParameterizedRunner
+ */
+@RunWith(ParameterizedRunner.class)
+@UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+public class ExampleParameterizedTest {
+ @ClassParameter
+ private static List<ParameterSet> sClassParams =
+ Arrays.asList(new ParameterSet().value("hello", "world").name("HelloWorld"),
+ new ParameterSet().value("Xxxx", "Yyyy").name("XxxxYyyy"),
+ new ParameterSet().value("aa", "yy").name("AaYy"));
+
+ public static class MethodParamsA implements ParameterProvider {
+ private static List<ParameterSet> sMethodParamA =
+ Arrays.asList(new ParameterSet().value(1, 2).name("OneTwo"),
+ new ParameterSet().value(2, 3).name("TwoThree"),
+ new ParameterSet().value(3, 4).name("ThreeFour"));
+
+ @Override
+ public List<ParameterSet> getParameters() {
+ return sMethodParamA;
+ }
+ }
+
+ public static class MethodParamsB implements ParameterProvider {
+ private static List<ParameterSet> sMethodParamB =
+ Arrays.asList(new ParameterSet().value("a", "b").name("Ab"),
+ new ParameterSet().value("b", "c").name("Bc"),
+ new ParameterSet().value("c", "d").name("Cd"),
+ new ParameterSet().value("d", "e").name("De"));
+
+ @Override
+ public List<ParameterSet> getParameters() {
+ return sMethodParamB;
+ }
+ }
+
+ private String mStringA;
+ private String mStringB;
+
+ public ExampleParameterizedTest(String a, String b) {
+ mStringA = a;
+ mStringB = b;
+ }
+
+ @Test
+ public void testSimple() {
+ Assert.assertEquals(
+ "A and B string length aren't equal", mStringA.length(), mStringB.length());
+ }
+
+ @Rule
+ public MethodRule mMethodParamAnnotationProcessor = new MethodParamAnnotationRule();
+
+ private Integer mSum;
+
+ @UseMethodParameterBefore(MethodParamsA.class)
+ public void setupWithOnlyA(int intA, int intB) {
+ mSum = intA + intB;
+ }
+
+ @Test
+ @UseMethodParameter(MethodParamsA.class)
+ public void testWithOnlyA(int intA, int intB) {
+ Assert.assertEquals(intA + 1, intB);
+ Assert.assertEquals(mSum, Integer.valueOf(intA + intB));
+ mSum = null;
+ }
+
+ private String mConcatenation;
+
+ @Test
+ @UseMethodParameter(MethodParamsB.class)
+ public void testWithOnlyB(String a, String b) {
+ Assert.assertTrue(!a.equals(b));
+ mConcatenation = a + b;
+ }
+
+ @UseMethodParameterAfter(MethodParamsB.class)
+ public void teardownWithOnlyB(String a, String b) {
+ Assert.assertEquals(mConcatenation, a + b);
+ mConcatenation = null;
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java
new file mode 100644
index 0000000000..6d854c57e6
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java
@@ -0,0 +1,77 @@
+// Copyright 2018 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.base.test.params;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.TestClass;
+
+import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
+
+import java.util.Collections;
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ParameterizedRunnerDelegateCommonTest {
+ /**
+ * Create a test object using the list of class parameter set
+ *
+ * @param testClass the {@link TestClass} object for current test class
+ * @param classParameterSet the parameter set needed for the test class constructor
+ */
+ private static Object createTest(TestClass testClass, ParameterSet classParameterSet)
+ throws ParameterizedTestInstantiationException {
+ return new ParameterizedRunnerDelegateCommon(
+ testClass, classParameterSet, Collections.emptyList())
+ .createTest();
+ }
+
+ static class BadTestClassWithMoreThanOneConstructor {
+ public BadTestClassWithMoreThanOneConstructor() {}
+ @SuppressWarnings("unused")
+ public BadTestClassWithMoreThanOneConstructor(String argument) {}
+ }
+
+ static class BadTestClassWithTwoArgumentConstructor {
+ @SuppressWarnings("unused")
+ public BadTestClassWithTwoArgumentConstructor(int a, int b) {}
+ }
+
+ static abstract class BadTestClassAbstract {
+ public BadTestClassAbstract() {}
+ }
+
+ static class BadTestClassConstructorThrows {
+ public BadTestClassConstructorThrows() {
+ throw new RuntimeException();
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateTestWithMoreThanOneConstructor() throws Throwable {
+ TestClass testClass = new TestClass(BadTestClassWithMoreThanOneConstructor.class);
+ createTest(testClass, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateTestWithIncorrectArguments() throws Throwable {
+ TestClass testClass = new TestClass(BadTestClassWithTwoArgumentConstructor.class);
+ ParameterSet pSet = new ParameterSet().value(1, 2, 3);
+ createTest(testClass, pSet);
+ }
+
+ @Test(expected = ParameterizedTestInstantiationException.class)
+ public void testCreateTestWithAbstractClass() throws ParameterizedTestInstantiationException {
+ TestClass testClass = new TestClass(BadTestClassAbstract.class);
+ createTest(testClass, null);
+ }
+
+ @Test(expected = ParameterizedTestInstantiationException.class)
+ public void testCreateTestWithThrowingConstructor()
+ throws ParameterizedTestInstantiationException {
+ TestClass testClass = new TestClass(BadTestClassConstructorThrows.class);
+ createTest(testClass, null);
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java
new file mode 100644
index 0000000000..723382d71d
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java
@@ -0,0 +1,133 @@
+// Copyright 2017 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.base.test.params;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.TestClass;
+
+import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
+import org.chromium.base.test.params.ParameterizedRunnerDelegateFactory.ParameterizedRunnerDelegateInstantiationException;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test for org.chromium.base.test.params.ParameterizedRunnerDelegateFactory
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ParameterizedRunnerDelegateFactoryTest {
+ /**
+ * This RunnerDelegate calls `super.collectInitializationErrors()` and would
+ * cause BlockJUnit4ClassRunner to validate test classes.
+ */
+ public static class BadExampleRunnerDelegate
+ extends BlockJUnit4ClassRunner implements ParameterizedRunnerDelegate {
+ public static class LalaTestClass {}
+
+ private final List<FrameworkMethod> mParameterizedFrameworkMethodList;
+
+ BadExampleRunnerDelegate(Class<?> klass,
+ List<FrameworkMethod> parameterizedFrameworkMethods) throws InitializationError {
+ super(klass);
+ mParameterizedFrameworkMethodList = parameterizedFrameworkMethods;
+ }
+
+ @Override
+ public void collectInitializationErrors(List<Throwable> errors) {
+ super.collectInitializationErrors(errors); // This is wrong!!
+ }
+
+ @Override
+ public List<FrameworkMethod> computeTestMethods() {
+ return mParameterizedFrameworkMethodList;
+ }
+
+ @Override
+ public Object createTest() {
+ return null;
+ }
+ }
+
+ static class ExampleTestClass {
+ static class MethodParamsA implements ParameterProvider {
+ @Override
+ public Iterable<ParameterSet> getParameters() {
+ return Arrays.asList(
+ new ParameterSet().value("a").name("testWithValue_a"),
+ new ParameterSet().value("b").name("testWithValue_b")
+ );
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @UseMethodParameter(MethodParamsA.class)
+ @Test
+ public void testA(String a) {}
+
+ static class MethodParamsB implements ParameterProvider {
+ @Override
+ public Iterable<ParameterSet> getParameters() {
+ return Arrays.asList(
+ new ParameterSet().value(1).name("testWithValue_1"),
+ new ParameterSet().value(2).name("testWithValue_2"),
+ new ParameterSet().value(3).name("testWithValue_3")
+ );
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @UseMethodParameter(MethodParamsB.class)
+ @Test
+ public void testB(int b) {}
+
+ @Test
+ public void testByMyself() {}
+ }
+
+ /**
+ * This test validates ParameterizedRunnerDelegateFactory throws exception when
+ * a runner delegate does not override the collectInitializationErrors method.
+ */
+ @Test(expected = ParameterizedRunnerDelegateInstantiationException.class)
+ public void testBadRunnerDelegateWithIncorrectValidationCall() throws Throwable {
+ ParameterizedRunnerDelegateFactory factory = new ParameterizedRunnerDelegateFactory();
+ TestClass testClass = new TestClass(BadExampleRunnerDelegate.LalaTestClass.class);
+ factory.createRunner(testClass, null, BadExampleRunnerDelegate.class);
+ }
+
+ @Test
+ public void testGenerateParameterizedFrameworkMethod() throws Throwable {
+ List<FrameworkMethod> methods =
+ ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList(
+ new TestClass(ExampleTestClass.class), "");
+
+ Assert.assertEquals(methods.size(), 6);
+
+ Map<String, Method> expectedTests = new HashMap<>();
+ Method testMethodA = ExampleTestClass.class.getDeclaredMethod("testA", String.class);
+ Method testMethodB = ExampleTestClass.class.getDeclaredMethod("testB", int.class);
+ Method testMethodByMyself = ExampleTestClass.class.getDeclaredMethod("testByMyself");
+ expectedTests.put("testA__testWithValue_a", testMethodA);
+ expectedTests.put("testA__testWithValue_b", testMethodA);
+ expectedTests.put("testB__testWithValue_1", testMethodB);
+ expectedTests.put("testB__testWithValue_2", testMethodB);
+ expectedTests.put("testB__testWithValue_3", testMethodB);
+ expectedTests.put("testByMyself", testMethodByMyself);
+ for (FrameworkMethod method : methods) {
+ Assert.assertNotNull(expectedTests.get(method.getName()));
+ Assert.assertEquals(expectedTests.get(method.getName()), method.getMethod());
+ expectedTests.remove(method.getName());
+ }
+ Assert.assertTrue(expectedTests.isEmpty());
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java
new file mode 100644
index 0000000000..170ff69eaf
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java
@@ -0,0 +1,108 @@
+// Copyright 2017 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.base.test.params;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
+import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
+import org.chromium.base.test.params.ParameterizedRunner.IllegalParameterArgumentException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test for org.chromium.base.test.params.ParameterizedRunner
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ParameterizedRunnerTest {
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class BadTestClassWithMoreThanOneConstructor {
+ @ClassParameter
+ static List<ParameterSet> sClassParams = new ArrayList<>();
+
+ public BadTestClassWithMoreThanOneConstructor() {}
+
+ public BadTestClassWithMoreThanOneConstructor(String x) {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class BadTestClassWithNonListParameters {
+ @ClassParameter
+ static String[] sMethodParamA = {"1", "2"};
+
+ @Test
+ public void test() {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class BadTestClassWithoutNeedForParameterization {
+ @Test
+ public void test() {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class BadTestClassWithNonStaticParameterSetList {
+ @ClassParameter
+ public List<ParameterSet> mClassParams = new ArrayList<>();
+
+ @Test
+ public void test() {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class BadTestClassWithMultipleClassParameter {
+ @ClassParameter
+ private static List<ParameterSet> sParamA = new ArrayList<>();
+
+ @ClassParameter
+ private static List<ParameterSet> sParamB = new ArrayList<>();
+ }
+
+ @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
+ public void testEmptyParameterSet() {
+ List<ParameterSet> paramList = new ArrayList<>();
+ paramList.add(new ParameterSet());
+ ParameterizedRunner.validateWidth(paramList);
+ }
+
+ @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
+ public void testUnequalWidthParameterSetList() {
+ List<ParameterSet> paramList = new ArrayList<>();
+ paramList.add(new ParameterSet().value(1, 2));
+ paramList.add(new ParameterSet().value(3, 4, 5));
+ ParameterizedRunner.validateWidth(paramList);
+ }
+
+ @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
+ public void testUnequalWidthParameterSetListWithNull() {
+ List<ParameterSet> paramList = new ArrayList<>();
+ paramList.add(new ParameterSet().value(null));
+ paramList.add(new ParameterSet().value(1, 2));
+ ParameterizedRunner.validateWidth(paramList);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBadClassWithNonListParameters() throws Throwable {
+ new ParameterizedRunner(BadTestClassWithNonListParameters.class);
+ }
+
+ @Test(expected = IllegalParameterArgumentException.class)
+ public void testBadClassWithNonStaticParameterSetList() throws Throwable {
+ new ParameterizedRunner(BadTestClassWithNonStaticParameterSetList.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBadClassWithoutNeedForParameterization() throws Throwable {
+ new ParameterizedRunner(BadTestClassWithoutNeedForParameterization.class);
+ }
+
+ @Test(expected = Exception.class)
+ public void testBadClassWithMoreThanOneConstructor() throws Throwable {
+ new ParameterizedRunner(BadTestClassWithMoreThanOneConstructor.class);
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java
new file mode 100644
index 0000000000..e79f5c5304
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java
@@ -0,0 +1,201 @@
+// Copyright 2017 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.base.test.params;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.TestClass;
+
+import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
+import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
+import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Test for verify the names and test method Description works properly
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ParameterizedTestNameTest {
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class TestClassWithClassParameterAppendName {
+ @ClassParameter
+ static List<ParameterSet> sAllName = Arrays.asList(
+ new ParameterSet().value("hello").name("Hello"),
+ new ParameterSet().value("world").name("World")
+ );
+
+ public TestClassWithClassParameterAppendName(String a) {}
+
+ @Test
+ public void test() {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class TestClassWithClassParameterDefaultName {
+ @ClassParameter
+ static List<ParameterSet> sAllName = Arrays.asList(
+ new ParameterSet().value("hello"),
+ new ParameterSet().value("world")
+ );
+
+ public TestClassWithClassParameterDefaultName(String a) {}
+
+ @Test
+ public void test() {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class TestClassWithMethodParameter {
+ static class AppendNameParams implements ParameterProvider {
+ @Override
+ public Iterable<ParameterSet> getParameters() {
+ return Arrays.asList(
+ new ParameterSet().value("hello").name("Hello"),
+ new ParameterSet().value("world").name("World")
+ );
+ }
+ }
+
+ static class DefaultNameParams implements ParameterProvider {
+ @Override
+ public Iterable<ParameterSet> getParameters() {
+ return Arrays.asList(
+ new ParameterSet().value("hello"),
+ new ParameterSet().value("world")
+ );
+ }
+ }
+
+ @UseMethodParameter(AppendNameParams.class)
+ @Test
+ public void test(String a) {}
+
+ @UseMethodParameter(DefaultNameParams.class)
+ @Test
+ public void testDefaultName(String b) {}
+ }
+
+ @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
+ public static class TestClassWithMixedParameter {
+ @ClassParameter
+ static List<ParameterSet> sAllName = Arrays.asList(
+ new ParameterSet().value("hello").name("Hello"),
+ new ParameterSet().value("world").name("World")
+ );
+
+ static class AppendNameParams implements ParameterProvider {
+ @Override
+ public Iterable<ParameterSet> getParameters() {
+ return Arrays.asList(
+ new ParameterSet().value("1").name("A"),
+ new ParameterSet().value("2").name("B")
+ );
+ }
+ }
+
+ public TestClassWithMixedParameter(String a) {}
+
+ @UseMethodParameter(AppendNameParams.class)
+ @Test
+ public void testA(String a) {}
+
+ @Test
+ public void test() {}
+ }
+
+ @Test
+ public void testClassParameterAppendName() throws Throwable {
+ List<Runner> runners = ParameterizedRunner.createRunners(
+ new TestClass(TestClassWithClassParameterAppendName.class));
+ List<String> expectedTestNames =
+ new LinkedList<String>(Arrays.asList("test__Hello", "test__World"));
+ List<String> computedMethodNames = new ArrayList<>();
+ for (Runner r : runners) {
+ BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
+ for (FrameworkMethod method : castedRunner.computeTestMethods()) {
+ computedMethodNames.add(method.getName());
+ Assert.assertTrue("This test name is not expected: " + method.getName(),
+ expectedTestNames.contains(method.getName()));
+ expectedTestNames.remove(method.getName());
+ method.getName();
+ }
+ }
+ Assert.assertTrue(
+ String.format(
+ "These names were provided: %s, these expected names are not found: %s",
+ Arrays.toString(computedMethodNames.toArray()),
+ Arrays.toString(expectedTestNames.toArray())),
+ expectedTestNames.isEmpty());
+ }
+
+ @Test
+ public void testClassParameterDefaultName() throws Throwable {
+ List<Runner> runners = ParameterizedRunner.createRunners(
+ new TestClass(TestClassWithClassParameterDefaultName.class));
+ List<String> expectedTestNames = new LinkedList<String>(Arrays.asList("test", "test"));
+ for (Runner r : runners) {
+ @SuppressWarnings("unchecked")
+ BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
+ for (FrameworkMethod method : castedRunner.computeTestMethods()) {
+ Assert.assertTrue("This test name is not expected: " + method.getName(),
+ expectedTestNames.contains(method.getName()));
+ expectedTestNames.remove(method.getName());
+ method.getName();
+ }
+ }
+ Assert.assertTrue("These expected names are not found: "
+ + Arrays.toString(expectedTestNames.toArray()),
+ expectedTestNames.isEmpty());
+ }
+
+ @Test
+ public void testMethodParameter() throws Throwable {
+ List<Runner> runners = ParameterizedRunner.createRunners(
+ new TestClass(TestClassWithMethodParameter.class));
+ List<String> expectedTestNames = new LinkedList<String>(
+ Arrays.asList("test__Hello", "test__World", "testDefaultName", "testDefaultName"));
+ for (Runner r : runners) {
+ BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
+ for (FrameworkMethod method : castedRunner.computeTestMethods()) {
+ Assert.assertTrue("This test name is not expected: " + method.getName(),
+ expectedTestNames.contains(method.getName()));
+ expectedTestNames.remove(method.getName());
+ method.getName();
+ }
+ }
+ Assert.assertTrue("These expected names are not found: "
+ + Arrays.toString(expectedTestNames.toArray()),
+ expectedTestNames.isEmpty());
+ }
+
+ @Test
+ public void testMixedParameterTestA() throws Throwable {
+ List<Runner> runners =
+ ParameterizedRunner.createRunners(new TestClass(TestClassWithMixedParameter.class));
+ List<String> expectedTestNames =
+ new LinkedList<String>(Arrays.asList("testA__Hello_A", "testA__World_A",
+ "testA__Hello_B", "testA__World_B", "test__Hello", "test__World"));
+ for (Runner r : runners) {
+ BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
+ for (FrameworkMethod method : castedRunner.computeTestMethods()) {
+ Assert.assertTrue("This test name is not expected: " + method.getName(),
+ expectedTestNames.contains(method.getName()));
+ expectedTestNames.remove(method.getName());
+ method.getName();
+ }
+ }
+ Assert.assertTrue("These expected names are not found: "
+ + Arrays.toString(expectedTestNames.toArray()),
+ expectedTestNames.isEmpty());
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java b/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java
new file mode 100644
index 0000000000..a147435355
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java
@@ -0,0 +1,193 @@
+// Copyright 2015 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.base.test.util;
+
+import android.os.Build;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/** Unit tests for the DisableIf annotation and its SkipCheck implementation. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 21)
+public class DisableIfTest {
+ @Test
+ public void testSdkIsLessThanAndIsLessThan() {
+ TestCase sdkIsLessThan = new TestCase("sdkIsLessThan") {
+ @DisableIf.Build(sdk_is_less_than = 22)
+ public void sdkIsLessThan() {}
+ };
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sdkIsLessThan));
+ }
+
+ @Test
+ public void testSdkIsLessThanButIsEqual() {
+ TestCase sdkIsEqual = new TestCase("sdkIsEqual") {
+ @DisableIf.Build(sdk_is_less_than = 21)
+ public void sdkIsEqual() {}
+ };
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsEqual));
+ }
+
+ @Test
+ public void testSdkIsLessThanButIsGreaterThan() {
+ TestCase sdkIsGreaterThan = new TestCase("sdkIsGreaterThan") {
+ @DisableIf.Build(sdk_is_less_than = 20)
+ public void sdkIsGreaterThan() {}
+ };
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsGreaterThan));
+ }
+
+ @Test
+ public void testSdkIsGreaterThanButIsLessThan() {
+ TestCase sdkIsLessThan = new TestCase("sdkIsLessThan") {
+ @DisableIf.Build(sdk_is_greater_than = 22)
+ public void sdkIsLessThan() {}
+ };
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsLessThan));
+ }
+
+ @Test
+ public void testSdkIsGreaterThanButIsEqual() {
+ TestCase sdkIsEqual = new TestCase("sdkIsEqual") {
+ @DisableIf.Build(sdk_is_greater_than = 21)
+ public void sdkIsEqual() {}
+ };
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsEqual));
+ }
+
+ @Test
+ public void testSdkIsGreaterThanAndIsGreaterThan() {
+ TestCase sdkIsGreaterThan = new TestCase("sdkIsGreaterThan") {
+ @DisableIf.Build(sdk_is_greater_than = 20)
+ public void sdkIsGreaterThan() {}
+ };
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sdkIsGreaterThan));
+ }
+
+ @Test
+ public void testSupportedAbiIncludesAndCpuAbiMatches() {
+ TestCase supportedAbisCpuAbiMatch = new TestCase("supportedAbisCpuAbiMatch") {
+ @DisableIf.Build(supported_abis_includes = "foo")
+ public void supportedAbisCpuAbiMatch() {}
+ };
+ String[] originalAbis = Build.SUPPORTED_ABIS;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
+ new String[] {"foo", "bar"});
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(supportedAbisCpuAbiMatch));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
+ }
+ }
+
+ @Test
+ public void testSupportedAbiIncludesAndCpuAbi2Matches() {
+ TestCase supportedAbisCpuAbi2Match = new TestCase("supportedAbisCpuAbi2Match") {
+ @DisableIf.Build(supported_abis_includes = "bar")
+ public void supportedAbisCpuAbi2Match() {}
+ };
+ String[] originalAbis = Build.SUPPORTED_ABIS;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
+ new String[] {"foo", "bar"});
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(supportedAbisCpuAbi2Match));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
+ }
+ }
+
+ @Test
+ public void testSupportedAbiIncludesButNoMatch() {
+ TestCase supportedAbisNoMatch = new TestCase("supportedAbisNoMatch") {
+ @DisableIf.Build(supported_abis_includes = "baz")
+ public void supportedAbisNoMatch() {}
+ };
+ String[] originalAbis = Build.SUPPORTED_ABIS;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
+ new String[] {"foo", "bar"});
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(supportedAbisNoMatch));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
+ }
+ }
+
+ @Test
+ public void testHardwareIsMatches() {
+ TestCase hardwareIsMatches = new TestCase("hardwareIsMatches") {
+ @DisableIf.Build(hardware_is = "hammerhead")
+ public void hardwareIsMatches() {}
+ };
+ String originalHardware = Build.HARDWARE;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "hammerhead");
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(hardwareIsMatches));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
+ }
+ }
+
+ @Test
+ public void testHardwareIsDoesntMatch() {
+ TestCase hardwareIsDoesntMatch = new TestCase("hardwareIsDoesntMatch") {
+ @DisableIf.Build(hardware_is = "hammerhead")
+ public void hardwareIsDoesntMatch() {}
+ };
+ String originalHardware = Build.HARDWARE;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "mako");
+ Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(hardwareIsDoesntMatch));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
+ }
+ }
+
+ @DisableIf.Build(supported_abis_includes = "foo")
+ private static class DisableIfSuperclassTestCase extends TestCase {
+ public DisableIfSuperclassTestCase(String name) {
+ super(name);
+ }
+ }
+
+ @DisableIf.Build(hardware_is = "hammerhead")
+ private static class DisableIfTestCase extends DisableIfSuperclassTestCase {
+ public DisableIfTestCase(String name) {
+ super(name);
+ }
+ public void sampleTestMethod() {}
+ }
+
+ @Test
+ public void testDisableClass() {
+ TestCase sampleTestMethod = new DisableIfTestCase("sampleTestMethod");
+ String originalHardware = Build.HARDWARE;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "hammerhead");
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sampleTestMethod));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
+ }
+ }
+
+ @Test
+ public void testDisableSuperClass() {
+ TestCase sampleTestMethod = new DisableIfTestCase("sampleTestMethod");
+ String[] originalAbis = Build.SUPPORTED_ABIS;
+ try {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", new String[] {"foo"});
+ Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sampleTestMethod));
+ } finally {
+ ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
+ }
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java
new file mode 100644
index 0000000000..2236646938
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java
@@ -0,0 +1,95 @@
+// 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.
+
+package org.chromium.base.test.util;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.isIn;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/** Unit tests for MinAndroidSdkLevelSkipCheck. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 18)
+public class MinAndroidSdkLevelSkipCheckTest {
+ public static class UnannotatedBaseClass {
+ @Test @MinAndroidSdkLevel(17) public void min17Method() {}
+ @Test @MinAndroidSdkLevel(20) public void min20Method() {}
+ }
+
+ @MinAndroidSdkLevel(17)
+ public static class Min17Class extends UnannotatedBaseClass {
+ @Test public void unannotatedMethod() {}
+ }
+
+ @MinAndroidSdkLevel(20)
+ public static class Min20Class extends UnannotatedBaseClass {
+ @Test public void unannotatedMethod() {}
+ }
+
+ public static class ExtendsMin17Class extends Min17Class {
+ @Override
+ @Test public void unannotatedMethod() {}
+ }
+
+ public static class ExtendsMin20Class extends Min20Class {
+ @Override
+ @Test public void unannotatedMethod() {}
+ }
+
+ private MinAndroidSdkLevelSkipCheck mSkipCheck = new MinAndroidSdkLevelSkipCheck();
+
+ @Rule
+ public TestRunnerTestRule mTestRunnerTestRule =
+ new TestRunnerTestRule(BaseJUnit4ClassRunner.class);
+
+ private void expectShouldSkip(Class<?> testClass, String methodName, boolean shouldSkip)
+ throws Exception {
+ Assert.assertThat(
+ mSkipCheck.shouldSkip(new FrameworkMethod(testClass.getMethod(methodName))),
+ equalTo(shouldSkip));
+ TestRunnerTestRule.TestLog runListener = mTestRunnerTestRule.runTest(testClass);
+ Assert.assertThat(Description.createTestDescription(testClass, methodName),
+ isIn(shouldSkip ? runListener.skippedTests : runListener.runTests));
+ }
+
+ @Test
+ public void testAnnotatedMethodAboveMin() throws Exception {
+ expectShouldSkip(UnannotatedBaseClass.class, "min17Method", false);
+ }
+
+ @Test
+ public void testAnnotatedMethodBelowMin() throws Exception {
+ expectShouldSkip(UnannotatedBaseClass.class, "min20Method", true);
+ }
+
+ @Test
+ public void testAnnotatedClassAboveMin() throws Exception {
+ expectShouldSkip(Min17Class.class, "unannotatedMethod", false);
+ }
+
+ @Test
+ public void testAnnotatedClassBelowMin() throws Exception {
+ expectShouldSkip(Min20Class.class, "unannotatedMethod", true);
+ }
+
+ @Test
+ public void testAnnotatedSuperclassAboveMin() throws Exception {
+ expectShouldSkip(ExtendsMin17Class.class, "unannotatedMethod", false);
+ }
+
+ @Test
+ public void testAnnotatedSuperclassBelowMin() throws Exception {
+ expectShouldSkip(ExtendsMin20Class.class, "unannotatedMethod", true);
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java
new file mode 100644
index 0000000000..86285de3f0
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java
@@ -0,0 +1,129 @@
+// 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.
+
+package org.chromium.base.test.util;
+
+import android.text.TextUtils;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/** Unit tests for RestrictionSkipCheck. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class RestrictionSkipCheckTest {
+ private static final String TEST_RESTRICTION_APPLIES =
+ "org.chromium.base.test.util.RestrictionSkipCheckTest.TEST_RESTRICTION_APPLIES";
+ private static final String TEST_RESTRICTION_DOES_NOT_APPLY =
+ "org.chromium.base.test.util.RestrictionSkipCheckTest.TEST_RESTRICTION_DOES_NOT_APPLY";
+
+ private static class TestRestrictionSkipCheck extends RestrictionSkipCheck {
+ public TestRestrictionSkipCheck() {
+ super(null);
+ }
+ @Override
+ protected boolean restrictionApplies(String restriction) {
+ return TextUtils.equals(restriction, TEST_RESTRICTION_APPLIES);
+ }
+ }
+
+ private static class UnannotatedBaseClass extends TestCase {
+ public UnannotatedBaseClass(String name) {
+ super(name);
+ }
+ @Restriction({TEST_RESTRICTION_APPLIES}) public void restrictedMethod() {}
+ @Restriction({TEST_RESTRICTION_DOES_NOT_APPLY}) public void unrestrictedMethod() {}
+ }
+
+ @Restriction({TEST_RESTRICTION_APPLIES})
+ private static class RestrictedClass extends UnannotatedBaseClass {
+ public RestrictedClass(String name) {
+ super(name);
+ }
+ public void unannotatedMethod() {}
+ }
+
+ @Restriction({TEST_RESTRICTION_DOES_NOT_APPLY})
+ private static class UnrestrictedClass extends UnannotatedBaseClass {
+ public UnrestrictedClass(String name) {
+ super(name);
+ }
+ public void unannotatedMethod() {}
+ }
+
+ @Restriction({
+ TEST_RESTRICTION_APPLIES,
+ TEST_RESTRICTION_DOES_NOT_APPLY})
+ private static class MultipleRestrictionsRestrictedClass extends UnannotatedBaseClass {
+ public MultipleRestrictionsRestrictedClass(String name) {
+ super(name);
+ }
+ public void unannotatedMethod() {}
+ }
+
+ private static class ExtendsRestrictedClass extends RestrictedClass {
+ public ExtendsRestrictedClass(String name) {
+ super(name);
+ }
+ @Override
+ public void unannotatedMethod() {}
+ }
+
+ private static class ExtendsUnrestrictedClass extends UnrestrictedClass {
+ public ExtendsUnrestrictedClass(String name) {
+ super(name);
+ }
+ @Override
+ public void unannotatedMethod() {}
+ }
+
+ @Test
+ public void testMethodRestricted() {
+ Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
+ new UnannotatedBaseClass("restrictedMethod")));
+ }
+
+ @Test
+ public void testMethodUnrestricted() {
+ Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
+ new UnannotatedBaseClass("unrestrictedMethod")));
+ }
+
+ @Test
+ public void testClassRestricted() {
+ Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
+ new RestrictedClass("unannotatedMethod")));
+ }
+
+ @Test
+ public void testClassUnrestricted() {
+ Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
+ new UnrestrictedClass("unannotatedMethod")));
+ }
+
+ @Test
+ public void testMultipleRestrictionsClassRestricted() {
+ Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
+ new MultipleRestrictionsRestrictedClass("unannotatedMethod")));
+ }
+
+ @Test
+ public void testSuperclassRestricted() {
+ Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
+ new ExtendsRestrictedClass("unannotatedMethod")));
+ }
+
+ @Test
+ public void testSuperclassUnrestricted() {
+ Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
+ new ExtendsUnrestrictedClass("unannotatedMethod")));
+ }
+}
+
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java
new file mode 100644
index 0000000000..51c7516e71
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java
@@ -0,0 +1,130 @@
+// 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.
+
+package org.chromium.base.test.util;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/** Unit tests for SkipCheck. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class SkipCheckTest {
+ private static class TestableSkipCheck extends SkipCheck {
+ public static <T extends Annotation> List<T> getAnnotationsForTesting(
+ AnnotatedElement element, Class<T> annotationClass) {
+ return AnnotationProcessingUtils.getAnnotations(element, annotationClass);
+ }
+
+ @Override
+ public boolean shouldSkip(FrameworkMethod m) {
+ return false;
+ }
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface TestAnnotation {}
+
+ @TestAnnotation
+ private class AnnotatedBaseClass {
+ public void unannotatedMethod() {}
+ @TestAnnotation public void annotatedMethod() {}
+ }
+
+ private class ExtendsAnnotatedBaseClass extends AnnotatedBaseClass {
+ public void anotherUnannotatedMethod() {}
+ }
+
+ private class ExtendsTestCaseClass extends TestCase {
+ public ExtendsTestCaseClass(String name) {
+ super(name);
+ }
+ public void testMethodA() {}
+ }
+
+ private class UnannotatedBaseClass {
+ public void unannotatedMethod() {}
+ @TestAnnotation public void annotatedMethod() {}
+ }
+
+ @Test
+ public void getAnnotationsForClassNone() {
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ UnannotatedBaseClass.class, TestAnnotation.class);
+ Assert.assertEquals(0, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForClassOnClass() {
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ AnnotatedBaseClass.class, TestAnnotation.class);
+ Assert.assertEquals(1, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForClassOnSuperclass() {
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ ExtendsAnnotatedBaseClass.class, TestAnnotation.class);
+ Assert.assertEquals(1, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForMethodNone() throws NoSuchMethodException {
+ Method testMethod = UnannotatedBaseClass.class.getMethod("unannotatedMethod",
+ (Class[]) null);
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ testMethod, TestAnnotation.class);
+ Assert.assertEquals(0, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForMethodOnMethod() throws NoSuchMethodException {
+ Method testMethod = UnannotatedBaseClass.class.getMethod("annotatedMethod",
+ (Class[]) null);
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ testMethod, TestAnnotation.class);
+ Assert.assertEquals(1, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForMethodOnClass() throws NoSuchMethodException {
+ Method testMethod = AnnotatedBaseClass.class.getMethod("unannotatedMethod",
+ (Class[]) null);
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ testMethod, TestAnnotation.class);
+ Assert.assertEquals(1, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsForMethodOnSuperclass() throws NoSuchMethodException {
+ Method testMethod = ExtendsAnnotatedBaseClass.class.getMethod("unannotatedMethod",
+ (Class[]) null);
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ testMethod, TestAnnotation.class);
+ Assert.assertEquals(1, annotations.size());
+ }
+
+ @Test
+ public void getAnnotationsOverlapping() throws NoSuchMethodException {
+ Method testMethod = AnnotatedBaseClass.class.getMethod("annotatedMethod",
+ (Class[]) null);
+ List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
+ testMethod, TestAnnotation.class);
+ Assert.assertEquals(2, annotations.size());
+ }
+}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java b/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java
new file mode 100644
index 0000000000..64805c124e
--- /dev/null
+++ b/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java
@@ -0,0 +1,132 @@
+// Copyright 2018 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.base.test.util;
+
+import static org.hamcrest.Matchers.isIn;
+import static org.junit.Assert.fail;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.rules.ExternalResource;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RuntimeEnvironment;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper rule to allow executing test runners in tests.
+ *
+ * Quis probat ipsas probas?
+ */
+class TestRunnerTestRule extends ExternalResource {
+ final Class<? extends BlockJUnit4ClassRunner> mRunnerClass;
+
+ /**
+ * @param runnerClass The runner class to run the test
+ */
+ TestRunnerTestRule(Class<? extends BlockJUnit4ClassRunner> runnerClass) {
+ mRunnerClass = runnerClass;
+ }
+
+ @Override
+ protected void before() throws Throwable {
+ // Register a fake Instrumentation so that class runners for instrumentation tests
+ // can be run even in Robolectric tests.
+ Instrumentation instrumentation = new Instrumentation() {
+ @Override
+ public Context getTargetContext() {
+ return RuntimeEnvironment.application;
+ }
+ };
+ InstrumentationRegistry.registerInstance(instrumentation, new Bundle());
+ }
+
+ @Override
+ protected void after() {
+ InstrumentationRegistry.registerInstance(null, new Bundle());
+ }
+
+ /**
+ * A struct-like class containing lists of run and skipped tests.
+ */
+ public static class TestLog {
+ public final List<Description> runTests = new ArrayList<>();
+ public final List<Description> skippedTests = new ArrayList<>();
+ }
+
+ /**
+ * Creates a new test runner and executes the test in the given {@code testClass} on it,
+ * returning lists of tests that were run and tests that were skipped.
+ * @param testClass The test class
+ * @return A {@link TestLog} that contains lists of run and skipped tests.
+ */
+ public TestLog runTest(Class<?> testClass) throws InvocationTargetException,
+ NoSuchMethodException, InstantiationException,
+ IllegalAccessException {
+ TestLog testLog = new TestLog();
+
+ // TODO(bauerb): Using Mockito mock() or spy() throws a ClassCastException.
+ RunListener runListener = new RunListener() {
+ @Override
+ public void testStarted(Description description) throws Exception {
+ testLog.runTests.add(description);
+ }
+
+ @Override
+ public void testFinished(Description description) throws Exception {
+ Assert.assertThat(description, isIn(testLog.runTests));
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ fail(failure.toString());
+ }
+
+ @Override
+ public void testAssumptionFailure(Failure failure) {
+ fail(failure.toString());
+ }
+
+ @Override
+ public void testIgnored(Description description) throws Exception {
+ testLog.skippedTests.add(description);
+ }
+ };
+ RunNotifier runNotifier = new RunNotifier();
+ runNotifier.addListener(runListener);
+ Runner runner;
+ try {
+ runner = mRunnerClass.getConstructor(Class.class).newInstance(testClass);
+ } catch (InvocationTargetException e) {
+ // If constructing the runner caused initialization errors, unwrap them from the
+ // InvocationTargetException.
+ Throwable cause = e.getCause();
+ if (!(cause instanceof InitializationError)) throw e;
+ List<Throwable> causes = ((InitializationError) cause).getCauses();
+
+ // If there was exactly one initialization error, rewrap that one.
+ if (causes.size() == 1) {
+ throw new InvocationTargetException(causes.get(0), "Initialization error");
+ }
+
+ // Otherwise, serialize all initialization errors to a string and throw that.
+ throw new AssertionError(causes.toString());
+ }
+ runner.run(runNotifier);
+ return testLog;
+ }
+}