blob: 51a328d2b69df40ce6a56d8673124071e8095a88 [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.testing.junit.testparameterinjector;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.truth.Truth.assertThat;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList;
import com.google.testing.junit.testparameterinjector.TestParameter.TestParameterValuesProvider;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runner.notification.Failure;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.TestClass;
/**
* Test class to test the PluggableTestRunner test harness works with {@link
* TestParameterAnnotation}s.
*/
@RunWith(Parameterized.class)
public class TestParameterAnnotationMethodProcessorTest {
@Retention(RUNTIME)
@interface ClassTestResult {
Result value();
}
enum Result {
/**
* A successful test run is expected in both for
* TestParameterAnnotationMethodProcessor#forAllAnnotationPlacements and
* TestParameterAnnotationMethodProcessor#onlyForFieldsAndParameters.
*/
SUCCESS_ALWAYS,
SUCCESS_FOR_ALL_PLACEMENTS_ONLY,
FAILURE,
}
public enum TestEnum {
UNDEFINED,
ONE,
TWO,
THREE,
FOUR,
FIVE
}
@Retention(RUNTIME)
@TestParameterAnnotation
public @interface EnumParameter {
TestEnum[] value() default {};
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class SingleAnnotationClass {
private static List<TestEnum> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class MultipleAllEnumValuesAnnotationClass {
private static List<String> testedParameters;
@TestParameter TestEnum enumParameter1;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test(@TestParameter TestEnum enumParameter2) {
testedParameters.add(enumParameter1 + ":" + enumParameter2);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).hasSize(TestEnum.values().length * TestEnum.values().length);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
public static class SingleParameterAnnotationClass {
private static List<TestEnum> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public void test(TestEnum enumParameter) {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class SingleAnnotatedParameterAnnotationClass {
private static List<TestEnum> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test(
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}) TestEnum enumParameter) {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class AnnotatedSuperclassParameter {
private static List<Object> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test(
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}) Object enumParameter) {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class DuplicatedAnnotatedParameterAnnotationClass {
private static List<ImmutableList<TestEnum>> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test(
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}) TestEnum enumParameter,
@EnumParameter({TestEnum.FOUR, TestEnum.FIVE}) TestEnum enumParameter2) {
testedParameters.add(ImmutableList.of(enumParameter, enumParameter2));
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters)
.containsExactly(
ImmutableList.of(TestEnum.ONE, TestEnum.FOUR),
ImmutableList.of(TestEnum.ONE, TestEnum.FIVE),
ImmutableList.of(TestEnum.TWO, TestEnum.FOUR),
ImmutableList.of(TestEnum.TWO, TestEnum.FIVE),
ImmutableList.of(TestEnum.THREE, TestEnum.FOUR),
ImmutableList.of(TestEnum.THREE, TestEnum.FIVE));
}
}
@ClassTestResult(Result.FAILURE)
public static class SingleAnnotatedParameterAnnotationClassWithMissingValue {
private static List<TestEnum> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test(@EnumParameter TestEnum enumParameter) {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
public static class MultipleAnnotationTestClass {
private static List<TestEnum> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
@EnumParameter({TestEnum.THREE})
public void parameterized() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class TooLongTestNamesShortened {
@Rule public TestName testName = new TestName();
private static List<String> allTestNames;
@BeforeClass
public static void resetStaticState() {
allTestNames = new ArrayList<>();
}
@Test
public void test1(
@TestParameter({
"ABC",
"This is a very long string (240 characters) that would normally cause Sponge+Tin to"
+ " exceed the filename limit of 255 characters."
+ " ==========================================================================="
+ "==================================="
})
String testString) {
allTestNames.add(testName.getMethodName());
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(allTestNames)
.containsExactly(
"test1[1.ABC]",
"test1[2.This is a very long string (240 characters) that would normally cause"
+ " Sponge+Tin to exceed the...]");
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class DuplicateTestNames {
@Rule public TestName testName = new TestName();
private static List<String> allTestNames;
private static List<Object> allTestParameterValues;
@BeforeClass
public static void resetStaticState() {
allTestNames = new ArrayList<>();
allTestParameterValues = new ArrayList<>();
}
@Test
public void test1(@TestParameter({"ABC", "ABC"}) String testString) {
allTestNames.add(testName.getMethodName());
allTestParameterValues.add(testString);
}
private static final class Test2Provider implements TestParameterValuesProvider {
@Override
public List<Object> provideValues() {
return newArrayList(123, "123", "null", null);
}
}
@Test
public void test2(@TestParameter(valuesProvider = Test2Provider.class) Object testObject) {
allTestNames.add(testName.getMethodName());
allTestParameterValues.add(testObject);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(allTestNames)
.containsExactly(
"test1[1.ABC]",
"test1[2.ABC]",
"test2[123 (Integer)]",
"test2[123 (String)]",
"test2[null (String)]",
"test2[null (null reference)]");
assertThat(allTestParameterValues).containsExactly("ABC", "ABC", 123, "123", "null", null);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class DuplicateFieldAnnotationTestClass {
private static List<String> testedParameters;
@TestParameter({"foo", "bar"})
String stringParameter;
@TestParameter({"baz", "qux"})
String stringParameter2;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(stringParameter + ":" + stringParameter2);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly("foo:baz", "foo:qux", "bar:baz", "bar:qux");
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class DuplicateIdenticalFieldAnnotationTestClass {
private static List<String> testedParameters;
@TestParameter({"foo", "bar"})
String stringParameter;
@TestParameter({"foo", "bar"})
String stringParameter2;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(stringParameter + ":" + stringParameter2);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly("foo:foo", "foo:bar", "bar:foo", "bar:bar");
}
}
@ClassTestResult(Result.FAILURE)
public static class ErrorDuplicateFieldAnnotationTestClass {
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
TestEnum parameter1;
@EnumParameter({TestEnum.THREE, TestEnum.FOUR})
TestEnum parameter2;
@Test
@EnumParameter(TestEnum.FIVE)
public void test() {}
}
@ClassTestResult(Result.FAILURE)
public static class ErrorDuplicateFieldAndClassAnnotationTestClass {
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
TestEnum parameter;
@EnumParameter(TestEnum.FIVE)
public ErrorDuplicateFieldAndClassAnnotationTestClass() {}
@Test
public void test() {}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class SingleAnnotationTestClassWithAnnotation {
private static List<TestEnum> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class MultipleAnnotationTestClassWithAnnotation {
private static List<String> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void parameterized(@TestParameter({"foo", "bar"}) String stringParameter) {
testedParameters.add(stringParameter + ":" + enumParameter);
}
@Test
public void nonParameterized() {
testedParameters.add("none:" + enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters)
.containsExactly(
"none:ONE",
"none:TWO",
"none:THREE",
"foo:ONE",
"foo:TWO",
"foo:THREE",
"bar:ONE",
"bar:TWO",
"bar:THREE");
}
}
public abstract static class BaseClassWithAnnotations {
@Rule public TestName testName = new TestName();
static List<String> allTestNames;
@TestParameter boolean boolInBase;
@BeforeClass
public static void resetStaticState() {
allTestNames = new ArrayList<>();
}
@Before
public void setUp() {
assertThat(allTestNames).doesNotContain(testName.getMethodName());
}
@After
public void tearDown() {
assertThat(allTestNames).contains(testName.getMethodName());
}
@Test
public void testInBase(@TestParameter({"ONE", "TWO"}) TestEnum enumInBase) {
allTestNames.add(testName.getMethodName());
}
@Test
public abstract void abstractTestInBase();
@Test
public void overridableTestInBase() {
throw new UnsupportedOperationException("Expected the base class to override this");
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class AnnotationInheritedFromBaseClass extends BaseClassWithAnnotations {
@TestParameter boolean boolInChild;
@Test
public void testInChild(@TestParameter({"TWO", "THREE"}) TestEnum enumInChild) {
allTestNames.add(testName.getMethodName());
}
@Override
public void abstractTestInBase() {
allTestNames.add(testName.getMethodName());
}
@Override
public void overridableTestInBase() {
allTestNames.add(testName.getMethodName());
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(allTestNames)
.containsExactly(
"testInBase[boolInChild=false,boolInBase=false,ONE]",
"testInBase[boolInChild=false,boolInBase=false,TWO]",
"testInBase[boolInChild=false,boolInBase=true,ONE]",
"testInBase[boolInChild=false,boolInBase=true,TWO]",
"testInBase[boolInChild=true,boolInBase=false,ONE]",
"testInBase[boolInChild=true,boolInBase=false,TWO]",
"testInBase[boolInChild=true,boolInBase=true,ONE]",
"testInBase[boolInChild=true,boolInBase=true,TWO]",
"testInChild[boolInChild=false,boolInBase=false,TWO]",
"testInChild[boolInChild=false,boolInBase=false,THREE]",
"testInChild[boolInChild=false,boolInBase=true,TWO]",
"testInChild[boolInChild=false,boolInBase=true,THREE]",
"testInChild[boolInChild=true,boolInBase=false,TWO]",
"testInChild[boolInChild=true,boolInBase=false,THREE]",
"testInChild[boolInChild=true,boolInBase=true,TWO]",
"testInChild[boolInChild=true,boolInBase=true,THREE]",
"abstractTestInBase[boolInChild=false,boolInBase=false]",
"abstractTestInBase[boolInChild=false,boolInBase=true]",
"abstractTestInBase[boolInChild=true,boolInBase=false]",
"abstractTestInBase[boolInChild=true,boolInBase=true]",
"overridableTestInBase[boolInChild=false,boolInBase=false]",
"overridableTestInBase[boolInChild=false,boolInBase=true]",
"overridableTestInBase[boolInChild=true,boolInBase=false]",
"overridableTestInBase[boolInChild=true,boolInBase=true]");
}
}
@Retention(RUNTIME)
@TestParameterAnnotation(validator = TestEnumValidator.class, processor = TestEnumProcessor.class)
public @interface EnumEvaluatorParameter {
TestEnum[] value() default {};
}
public static class TestEnumValidator implements TestParameterValidator {
@Override
public boolean shouldSkip(Context context) {
return context.has(EnumEvaluatorParameter.class, TestEnum.THREE);
}
}
public static class TestEnumProcessor implements TestParameterProcessor {
static List<Object> beforeCalls = new ArrayList<>();
static List<Object> afterCalls = new ArrayList<>();
static void init() {
beforeCalls.clear();
afterCalls.clear();
}
static TestEnum currentValue;
@Override
public void before(Object testParameterValue) {
beforeCalls.add(testParameterValue);
currentValue = (TestEnum) testParameterValue;
}
@Override
public void after(Object testParameterValue) {
afterCalls.add(testParameterValue);
currentValue = null;
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class MethodEvaluatorClass {
private static List<TestEnum> testedParameters;
@Test
public void test(
@EnumEvaluatorParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}) TestEnum value) {
if (value == TestEnum.THREE) {
fail();
} else {
testedParameters.add(value);
}
}
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@BeforeClass
public static void init() {
TestEnumProcessor.init();
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.beforeCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.afterCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class FieldEvaluatorClass {
private static List<TestEnum> testedParameters;
@EnumEvaluatorParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
TestEnum value;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
if (value == TestEnum.THREE) {
fail();
} else {
testedParameters.add(value);
}
}
@BeforeClass
public static void init() {
TestEnumProcessor.init();
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.beforeCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.afterCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
@EnumEvaluatorParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public static class ClassEvaluatorClass {
private static List<TestEnum> testedParameters;
public ClassEvaluatorClass() {}
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
if (TestEnumProcessor.currentValue == TestEnum.THREE) {
fail();
} else {
testedParameters.add(TestEnumProcessor.currentValue);
}
}
@BeforeClass
public static void init() {
TestEnumProcessor.init();
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.beforeCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
assertThat(TestEnumProcessor.afterCalls).containsExactly(TestEnum.ONE, TestEnum.TWO);
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class ConstructorClass {
private static List<TestEnum> testedParameters;
final TestEnum enumParameter;
public ConstructorClass(
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}) TestEnum enumParameter) {
this.enumParameter = enumParameter;
}
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
public static class MethodFieldOverrideClass {
private static List<TestEnum> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public void test() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO, TestEnum.THREE);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
@EnumEvaluatorParameter({TestEnum.ONE})
public static class MethodClassOverrideClass {
private static List<TestEnum> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
@EnumEvaluatorParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public void test() {
testedParameters.add(TestEnumProcessor.currentValue);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO);
}
}
@ClassTestResult(Result.SUCCESS_FOR_ALL_PLACEMENTS_ONLY)
public static class ErrorDuplicatedConstructorMethodAnnotation {
private static List<String> testedParameters;
final TestEnum enumParameter;
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public ErrorDuplicatedConstructorMethodAnnotation(TestEnum enumParameter) {
this.enumParameter = enumParameter;
}
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
public void test(TestEnum otherParameter) {
testedParameters.add(enumParameter + ":" + otherParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters)
.containsExactly("ONE:ONE", "ONE:TWO", "TWO:ONE", "TWO:TWO", "THREE:ONE", "THREE:TWO");
}
}
@ClassTestResult(Result.FAILURE)
@EnumParameter({TestEnum.ONE, TestEnum.TWO, TestEnum.THREE})
public static class ErrorDuplicatedClassFieldAnnotation {
private static List<TestEnum> testedParameters;
@EnumParameter({TestEnum.ONE, TestEnum.TWO})
TestEnum enumParameter;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(enumParameter);
}
@AfterClass
public static void completedAllParameterizedTests() {
assertThat(testedParameters).containsExactly(TestEnum.ONE, TestEnum.TWO);
}
}
@ClassTestResult(Result.FAILURE)
public static class ErrorNonStaticProviderClass {
@Test
public void test(@TestParameter(valuesProvider = NonStaticProvider.class) int i) {}
@SuppressWarnings("ClassCanBeStatic")
class NonStaticProvider implements TestParameterValuesProvider {
@Override
public List<?> provideValues() {
return ImmutableList.of();
}
}
}
public enum EnumA {
A1,
A2
}
public enum EnumB {
B1,
B2
}
public enum EnumC {
C1,
C2,
C3
}
@Retention(RUNTIME)
@TestParameterAnnotation(validator = TestBaseValidatorValidator.class)
public @interface EnumAParameter {
EnumA[] value() default {EnumA.A1, EnumA.A2};
}
@Retention(RUNTIME)
@TestParameterAnnotation(validator = TestBaseValidatorValidator.class)
public @interface EnumBParameter {
EnumB[] value() default {EnumB.B1, EnumB.B2};
}
@Retention(RUNTIME)
@TestParameterAnnotation(validator = TestBaseValidatorValidator.class)
public @interface EnumCParameter {
EnumC[] value() default {EnumC.C1, EnumC.C2, EnumC.C3};
}
public static class TestBaseValidatorValidator extends BaseTestParameterValidator {
@Override
protected List<List<Class<? extends Annotation>>> getIndependentParameters(Context context) {
return ImmutableList.of(
ImmutableList.of(EnumAParameter.class, EnumBParameter.class, EnumCParameter.class));
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class IndependentAnnotation {
@EnumAParameter EnumA enumA;
@EnumBParameter EnumB enumB;
@EnumCParameter EnumC enumC;
private static List<List<Object>> testedParameters;
@BeforeClass
public static void resetStaticState() {
testedParameters = new ArrayList<>();
}
@Test
public void test() {
testedParameters.add(ImmutableList.of(enumA, enumB, enumC));
}
@AfterClass
public static void completedAllParameterizedTests() {
// Only 3 tests should have been sufficient to cover all cases.
assertThat(testedParameters).hasSize(3);
assertAllEnumsAreIncluded(EnumA.values());
assertAllEnumsAreIncluded(EnumB.values());
assertAllEnumsAreIncluded(EnumC.values());
}
private static <T extends Enum<T>> void assertAllEnumsAreIncluded(Enum<T>[] values) {
Set<Enum<T>> enumSet = new HashSet<>(Arrays.asList(values));
for (List<Object> enumList : testedParameters) {
enumSet.removeAll(enumList);
}
assertThat(enumSet).isEmpty();
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class TestNamesTest {
@Rule public TestName name = new TestName();
@TestParameter("8")
long fieldParam;
@Test
public void withPrimitives(
@TestParameter("true") boolean param1, @TestParameter("2") int param2) {
assertThat(name.getMethodName())
.isEqualTo("withPrimitives[fieldParam=8,param1=true,param2=2]");
}
@Test
public void withString(@TestParameter("AAA") String param1) {
assertThat(name.getMethodName()).isEqualTo("withString[fieldParam=8,AAA]");
}
@Test
public void withEnum(@EnumParameter(TestEnum.TWO) TestEnum param1) {
assertThat(name.getMethodName()).isEqualTo("withEnum[fieldParam=8,TWO]");
}
}
@ClassTestResult(Result.SUCCESS_ALWAYS)
public static class MethodNameContainsOrderedParameterNames {
@Rule public TestName name = new TestName();
@Test
public void pretest(@TestParameter({"a", "b"}) String foo) {}
@Test
public void test(
@EnumParameter({TestEnum.ONE, TestEnum.TWO}) TestEnum e, @TestParameter({"c"}) String foo) {
assertThat(name.getMethodName()).isEqualTo("test[" + e.name() + "," + foo + "]");
}
}
@Parameters(name = "{0}:{2}")
public static Collection<Object[]> parameters() {
return Arrays.stream(TestParameterAnnotationMethodProcessorTest.class.getClasses())
.filter(cls -> cls.isAnnotationPresent(ClassTestResult.class))
.map(
cls ->
new Object[] {
cls.getSimpleName(), cls, cls.getAnnotation(ClassTestResult.class).value()
})
.collect(toImmutableList());
}
private final Class<?> testClass;
private final Result result;
public TestParameterAnnotationMethodProcessorTest(
String name, Class<?> testClass, Result result) {
this.testClass = testClass;
this.result = result;
}
@Test
@Ignore("b/195657808 @TestParameters is not supported on Android")
public void test() throws Exception {
List<Failure> failures;
switch (result) {
case SUCCESS_ALWAYS:
failures =
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::forAllAnnotationPlacements));
assertThat(failures).isEmpty();
failures =
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::onlyForFieldsAndParameters));
assertThat(failures).isEmpty();
break;
case SUCCESS_FOR_ALL_PLACEMENTS_ONLY:
failures =
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::forAllAnnotationPlacements));
assertThat(failures).isEmpty();
assertThrows(
IllegalStateException.class,
() ->
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::onlyForFieldsAndParameters)));
break;
case FAILURE:
assertThrows(
IllegalStateException.class,
() ->
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::forAllAnnotationPlacements)));
assertThrows(
IllegalStateException.class,
() ->
PluggableTestRunner.run(
newTestRunnerWithParameterizedSupport(
TestParameterAnnotationMethodProcessor::onlyForFieldsAndParameters)));
break;
}
}
private PluggableTestRunner newTestRunnerWithParameterizedSupport(
Function<TestClass, TestMethodProcessor> processor) throws Exception {
return new PluggableTestRunner(testClass) {
@Override
protected List<TestMethodProcessor> createTestMethodProcessorList() {
return ImmutableList.of(processor.apply(getTestClass()));
}
};
}
}