aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Nyman <jnyman@google.com>2024-01-16 09:55:10 +0000
committerJens Nyman <jnyman@google.com>2024-01-16 09:55:10 +0000
commitf82c1ff0f4c7999493401bbfedebf8ab1d1eceb3 (patch)
treeea74caa6ba48322202728726d79bab2529635ecc
parent9dd42b625d73ebcc7dd751349fe70c44902f6f0f (diff)
downloadTestParameterInjector-f82c1ff0f4c7999493401bbfedebf8ab1d1eceb3.tar.gz
TestParameterValueProvider: Add internal-only context-aware version of provideValues().
This will be used by a context-aware value provider for @TestParameter in a follow-up change. https://github.com/google/TestParameterInjector/issues/44
-rw-r--r--junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java113
-rw-r--r--junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterValueProvider.java48
-rw-r--r--junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterAnnotationMethodProcessor.java113
-rw-r--r--junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterValueProvider.java48
4 files changed, 272 insertions, 50 deletions
diff --git a/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java b/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java
index 79ba92b..d186e84 100644
--- a/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java
+++ b/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterAnnotationMethodProcessor.java
@@ -190,7 +190,11 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
valueProvider
.getConstructor()
.newInstance()
- .provideValues(annotation, annotationWithMetadata.paramClass()))
+ .provideValues(
+ annotation,
+ annotationWithMetadata.otherAnnotations(),
+ annotationWithMetadata.paramClass(),
+ annotationWithMetadata.testClass()))
.transform(
value ->
(value instanceof TestParameterValue)
@@ -248,6 +252,15 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
abstract Annotation annotation();
/**
+ * A list of all other annotations on the field or parameter that was annotated with {@code
+ * annotation}.
+ *
+ * <p>In case the annotation is annotating a method, constructor or class, {@code
+ * parameterClass} is an empty list.
+ */
+ abstract ImmutableList<Annotation> otherAnnotations();
+
+ /**
* The class of the parameter or field that is being annotated. In case the annotation is
* annotating a method, constructor or class, {@code paramClass} is an absent optional.
*/
@@ -259,20 +272,48 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
*/
abstract Optional<String> paramName();
+ /** The class that contains the test that is currently being run. */
+ abstract Class<?> testClass();
+
public static AnnotationWithMetadata withMetadata(
- Annotation annotation, Class<?> paramClass, String paramName) {
+ Annotation annotation,
+ Annotation[] allAnnotations,
+ Class<?> paramClass,
+ String paramName,
+ Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.of(paramClass), Optional.of(paramName));
+ annotation,
+ /* otherAnnotations= */ FluentIterable.from(allAnnotations)
+ .filter(a -> !a.equals(annotation))
+ .toList(),
+ Optional.of(paramClass),
+ Optional.of(paramName),
+ testClass);
}
- public static AnnotationWithMetadata withMetadata(Annotation annotation, Class<?> paramClass) {
+ public static AnnotationWithMetadata withMetadata(
+ Annotation annotation,
+ Annotation[] allAnnotations,
+ Class<?> paramClass,
+ Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.of(paramClass), Optional.absent());
+ annotation,
+ /* otherAnnotations= */ FluentIterable.from(allAnnotations)
+ .filter(a -> !a.equals(annotation))
+ .toList(),
+ Optional.of(paramClass),
+ Optional.absent(),
+ testClass);
}
- public static AnnotationWithMetadata withoutMetadata(Annotation annotation) {
+ public static AnnotationWithMetadata withoutMetadata(
+ Annotation annotation, Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.absent(), Optional.absent());
+ annotation,
+ /* otherAnnotations= */ ImmutableList.of(),
+ /* paramClass= */ Optional.absent(),
+ /* paramName= */ Optional.absent(),
+ testClass);
}
// Prevent anyone relying on equals() and hashCode() so that it remains possible to add fields
@@ -907,7 +948,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (origin == Origin.CONSTRUCTOR_PARAMETER) {
Constructor<?> constructor = TestParameterInjectorUtils.getOnlyConstructor(testClass);
List<AnnotationWithMetadata> annotations =
- getAnnotationWithMetadataListWithType(constructor, annotationType);
+ getAnnotationWithMetadataListWithType(constructor, annotationType, testClass);
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
@@ -918,12 +959,12 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (annotation != null) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(annotation), origin));
+ AnnotationWithMetadata.withoutMetadata(annotation, testClass), origin));
}
} else if (origin == Origin.METHOD_PARAMETER) {
List<AnnotationWithMetadata> annotations =
- getAnnotationWithMetadataListWithType(method, annotationType);
+ getAnnotationWithMetadataListWithType(method, annotationType, testClass);
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
}
@@ -931,7 +972,8 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (method.isAnnotationPresent(annotationType)) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(method.getAnnotation(annotationType)),
+ AnnotationWithMetadata.withoutMetadata(
+ method.getAnnotation(annotationType), testClass),
origin));
}
} else if (origin == Origin.FIELD) {
@@ -946,7 +988,11 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
.transform(
annotation ->
AnnotationWithMetadata.withMetadata(
- annotation, field.getType(), field.getName())))
+ annotation,
+ field.getAnnotations(),
+ field.getType(),
+ field.getName(),
+ testClass)))
.toList());
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
@@ -956,7 +1002,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (annotation != null) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(annotation), origin));
+ AnnotationWithMetadata.withoutMetadata(annotation, testClass), origin));
}
}
return ImmutableList.of();
@@ -974,22 +1020,30 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
}
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Method callable, Class<? extends Annotation> annotationType) {
+ Method callable, Class<? extends Annotation> annotationType, Class<?> testClass) {
try {
- return getAnnotationWithMetadataListWithType(callable.getParameters(), annotationType);
+ return getAnnotationWithMetadataListWithType(
+ callable.getParameters(), annotationType, testClass);
} catch (NoSuchMethodError ignored) {
return getAnnotationWithMetadataListWithType(
- callable.getParameterTypes(), callable.getParameterAnnotations(), annotationType);
+ callable.getParameterTypes(),
+ callable.getParameterAnnotations(),
+ annotationType,
+ testClass);
}
}
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Constructor<?> callable, Class<? extends Annotation> annotationType) {
+ Constructor<?> callable, Class<? extends Annotation> annotationType, Class<?> testClass) {
try {
- return getAnnotationWithMetadataListWithType(callable.getParameters(), annotationType);
+ return getAnnotationWithMetadataListWithType(
+ callable.getParameters(), annotationType, testClass);
} catch (NoSuchMethodError ignored) {
return getAnnotationWithMetadataListWithType(
- callable.getParameterTypes(), callable.getParameterAnnotations(), annotationType);
+ callable.getParameterTypes(),
+ callable.getParameterAnnotations(),
+ annotationType,
+ testClass);
}
}
@@ -998,7 +1052,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
// which are optional anyway).
@SuppressWarnings("AndroidJdkLibsChecker")
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Parameter[] parameters, Class<? extends Annotation> annotationType) {
+ Parameter[] parameters, Class<? extends Annotation> annotationType, Class<?> testClass) {
return FluentIterable.from(parameters)
.transform(
parameter -> {
@@ -1007,8 +1061,16 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
? null
: parameter.isNamePresent()
? AnnotationWithMetadata.withMetadata(
- annotation, parameter.getType(), parameter.getName())
- : AnnotationWithMetadata.withMetadata(annotation, parameter.getType());
+ annotation,
+ /* allAnnotations= */ parameter.getAnnotations(),
+ parameter.getType(),
+ parameter.getName(),
+ testClass)
+ : AnnotationWithMetadata.withMetadata(
+ annotation,
+ /* allAnnotations= */ parameter.getAnnotations(),
+ parameter.getType(),
+ testClass);
})
.filter(Objects::nonNull)
.toList();
@@ -1017,14 +1079,17 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
Class<?>[] parameterTypes,
Annotation[][] annotations,
- Class<? extends Annotation> annotationType) {
+ Class<? extends Annotation> annotationType,
+ Class<?> testClass) {
checkArgument(parameterTypes.length == annotations.length);
ImmutableList.Builder<AnnotationWithMetadata> resultBuilder = ImmutableList.builder();
for (int i = 0; i < annotations.length; i++) {
for (Annotation annotation : annotations[i]) {
if (annotation.annotationType().equals(annotationType)) {
- resultBuilder.add(AnnotationWithMetadata.withMetadata(annotation, parameterTypes[i]));
+ resultBuilder.add(
+ AnnotationWithMetadata.withMetadata(
+ annotation, /* allAnnotations= */ annotations[i], parameterTypes[i], testClass));
}
}
}
diff --git a/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterValueProvider.java b/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterValueProvider.java
index dbb334c..08cc173 100644
--- a/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterValueProvider.java
+++ b/junit4/src/main/java/com/google/testing/junit/testparameterinjector/TestParameterValueProvider.java
@@ -15,6 +15,7 @@
package com.google.testing.junit.testparameterinjector;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -34,7 +35,52 @@ interface TestParameterValueProvider {
* annotation is annotating a method, constructor or class, {@code parameterClass} is an empty
* optional.
*/
- List<Object> provideValues(Annotation annotation, Optional<Class<?>> parameterClass);
+ default List<Object> provideValues(Annotation annotation, Optional<Class<?>> parameterClass) {
+ throw new UnsupportedOperationException(
+ "If this is called by TestParameterInjector, it means that neither of the"
+ + " provideValues()-type methods have been implemented");
+ }
+
+ /**
+ * Extension of {@link #provideValues(Annotation, Optional<Class<?>>)} with extra context.
+ *
+ * @param annotation The annotation instance that was encountered in the test class. The
+ * definition of this annotation is itself annotated with the {@link TestParameterAnnotation}
+ * annotation.
+ * @param otherAnnotations A list of all other annotations on the field or parameter that was
+ * annotated with {@code annotation}.
+ * <p>For example, if the test code is as follows:
+ * <pre>
+ * @Test
+ * public void myTest_success(
+ * @CustomAnnotation(123) @TestParameter(valuesProvider=MyProvider.class) Foo foo) {
+ * ...
+ * }
+ * </pre>
+ * then this list will contain a single element: @CustomAnnotation(123).
+ * <p>In case the annotation is annotating a method, constructor or class, {@code
+ * parameterClass} is an empty list.
+ * @param parameterClass The class of the parameter or field that is being annotated. In case the
+ * annotation is annotating a method, constructor or class, {@code parameterClass} is an empty
+ * optional.
+ * @param testClass The class that contains the test that is currently being run.
+ * <p>Having this can be useful when sharing providers between tests that have the same base
+ * class. In those cases, an abstract method can be called as follows:
+ * <pre>
+ * ((MyBaseClass) context.testClass().newInstance()).myAbstractMethod()
+ * </pre>
+ *
+ * @deprecated Don't use this method outside of the testparameterinjector codebase, as it is prone
+ * to being changed.
+ */
+ @Deprecated
+ default List<Object> provideValues(
+ Annotation annotation,
+ ImmutableList<Annotation> otherAnnotations,
+ Optional<Class<?>> parameterClass,
+ Class<?> testClass) {
+ return provideValues(annotation, parameterClass);
+ }
/**
* Returns the class of the list elements returned by {@link #provideValues(Annotation,
diff --git a/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterAnnotationMethodProcessor.java b/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterAnnotationMethodProcessor.java
index 23462ac..41d9a7b 100644
--- a/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterAnnotationMethodProcessor.java
+++ b/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterAnnotationMethodProcessor.java
@@ -190,7 +190,11 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
valueProvider
.getConstructor()
.newInstance()
- .provideValues(annotation, annotationWithMetadata.paramClass()))
+ .provideValues(
+ annotation,
+ annotationWithMetadata.otherAnnotations(),
+ annotationWithMetadata.paramClass(),
+ annotationWithMetadata.testClass()))
.transform(
value ->
(value instanceof TestParameterValue)
@@ -248,6 +252,15 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
abstract Annotation annotation();
/**
+ * A list of all other annotations on the field or parameter that was annotated with {@code
+ * annotation}.
+ *
+ * <p>In case the annotation is annotating a method, constructor or class, {@code
+ * parameterClass} is an empty list.
+ */
+ abstract ImmutableList<Annotation> otherAnnotations();
+
+ /**
* The class of the parameter or field that is being annotated. In case the annotation is
* annotating a method, constructor or class, {@code paramClass} is an absent optional.
*/
@@ -259,20 +272,48 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
*/
abstract Optional<String> paramName();
+ /** The class that contains the test that is currently being run. */
+ abstract Class<?> testClass();
+
public static AnnotationWithMetadata withMetadata(
- Annotation annotation, Class<?> paramClass, String paramName) {
+ Annotation annotation,
+ Annotation[] allAnnotations,
+ Class<?> paramClass,
+ String paramName,
+ Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.of(paramClass), Optional.of(paramName));
+ annotation,
+ /* otherAnnotations= */ FluentIterable.from(allAnnotations)
+ .filter(a -> !a.equals(annotation))
+ .toList(),
+ Optional.of(paramClass),
+ Optional.of(paramName),
+ testClass);
}
- public static AnnotationWithMetadata withMetadata(Annotation annotation, Class<?> paramClass) {
+ public static AnnotationWithMetadata withMetadata(
+ Annotation annotation,
+ Annotation[] allAnnotations,
+ Class<?> paramClass,
+ Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.of(paramClass), Optional.absent());
+ annotation,
+ /* otherAnnotations= */ FluentIterable.from(allAnnotations)
+ .filter(a -> !a.equals(annotation))
+ .toList(),
+ Optional.of(paramClass),
+ Optional.absent(),
+ testClass);
}
- public static AnnotationWithMetadata withoutMetadata(Annotation annotation) {
+ public static AnnotationWithMetadata withoutMetadata(
+ Annotation annotation, Class<?> testClass) {
return new AutoValue_TestParameterAnnotationMethodProcessor_AnnotationWithMetadata(
- annotation, Optional.absent(), Optional.absent());
+ annotation,
+ /* otherAnnotations= */ ImmutableList.of(),
+ /* paramClass= */ Optional.absent(),
+ /* paramName= */ Optional.absent(),
+ testClass);
}
// Prevent anyone relying on equals() and hashCode() so that it remains possible to add fields
@@ -907,7 +948,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (origin == Origin.CONSTRUCTOR_PARAMETER) {
Constructor<?> constructor = TestParameterInjectorUtils.getOnlyConstructor(testClass);
List<AnnotationWithMetadata> annotations =
- getAnnotationWithMetadataListWithType(constructor, annotationType);
+ getAnnotationWithMetadataListWithType(constructor, annotationType, testClass);
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
@@ -918,12 +959,12 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (annotation != null) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(annotation), origin));
+ AnnotationWithMetadata.withoutMetadata(annotation, testClass), origin));
}
} else if (origin == Origin.METHOD_PARAMETER) {
List<AnnotationWithMetadata> annotations =
- getAnnotationWithMetadataListWithType(method, annotationType);
+ getAnnotationWithMetadataListWithType(method, annotationType, testClass);
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
}
@@ -931,7 +972,8 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (method.isAnnotationPresent(annotationType)) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(method.getAnnotation(annotationType)),
+ AnnotationWithMetadata.withoutMetadata(
+ method.getAnnotation(annotationType), testClass),
origin));
}
} else if (origin == Origin.FIELD) {
@@ -946,7 +988,11 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
.transform(
annotation ->
AnnotationWithMetadata.withMetadata(
- annotation, field.getType(), field.getName())))
+ annotation,
+ field.getAnnotations(),
+ field.getType(),
+ field.getName(),
+ testClass)))
.toList());
if (!annotations.isEmpty()) {
return toTestParameterValueList(annotations, origin);
@@ -956,7 +1002,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
if (annotation != null) {
return ImmutableList.of(
TestParameterValueHolder.create(
- AnnotationWithMetadata.withoutMetadata(annotation), origin));
+ AnnotationWithMetadata.withoutMetadata(annotation, testClass), origin));
}
}
return ImmutableList.of();
@@ -974,22 +1020,30 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
}
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Method callable, Class<? extends Annotation> annotationType) {
+ Method callable, Class<? extends Annotation> annotationType, Class<?> testClass) {
try {
- return getAnnotationWithMetadataListWithType(callable.getParameters(), annotationType);
+ return getAnnotationWithMetadataListWithType(
+ callable.getParameters(), annotationType, testClass);
} catch (NoSuchMethodError ignored) {
return getAnnotationWithMetadataListWithType(
- callable.getParameterTypes(), callable.getParameterAnnotations(), annotationType);
+ callable.getParameterTypes(),
+ callable.getParameterAnnotations(),
+ annotationType,
+ testClass);
}
}
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Constructor<?> callable, Class<? extends Annotation> annotationType) {
+ Constructor<?> callable, Class<? extends Annotation> annotationType, Class<?> testClass) {
try {
- return getAnnotationWithMetadataListWithType(callable.getParameters(), annotationType);
+ return getAnnotationWithMetadataListWithType(
+ callable.getParameters(), annotationType, testClass);
} catch (NoSuchMethodError ignored) {
return getAnnotationWithMetadataListWithType(
- callable.getParameterTypes(), callable.getParameterAnnotations(), annotationType);
+ callable.getParameterTypes(),
+ callable.getParameterAnnotations(),
+ annotationType,
+ testClass);
}
}
@@ -998,7 +1052,7 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
// which are optional anyway).
@SuppressWarnings("AndroidJdkLibsChecker")
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
- Parameter[] parameters, Class<? extends Annotation> annotationType) {
+ Parameter[] parameters, Class<? extends Annotation> annotationType, Class<?> testClass) {
return FluentIterable.from(parameters)
.transform(
parameter -> {
@@ -1007,8 +1061,16 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
? null
: parameter.isNamePresent()
? AnnotationWithMetadata.withMetadata(
- annotation, parameter.getType(), parameter.getName())
- : AnnotationWithMetadata.withMetadata(annotation, parameter.getType());
+ annotation,
+ /* allAnnotations= */ parameter.getAnnotations(),
+ parameter.getType(),
+ parameter.getName(),
+ testClass)
+ : AnnotationWithMetadata.withMetadata(
+ annotation,
+ /* allAnnotations= */ parameter.getAnnotations(),
+ parameter.getType(),
+ testClass);
})
.filter(Objects::nonNull)
.toList();
@@ -1017,14 +1079,17 @@ final class TestParameterAnnotationMethodProcessor implements TestMethodProcesso
private static ImmutableList<AnnotationWithMetadata> getAnnotationWithMetadataListWithType(
Class<?>[] parameterTypes,
Annotation[][] annotations,
- Class<? extends Annotation> annotationType) {
+ Class<? extends Annotation> annotationType,
+ Class<?> testClass) {
checkArgument(parameterTypes.length == annotations.length);
ImmutableList.Builder<AnnotationWithMetadata> resultBuilder = ImmutableList.builder();
for (int i = 0; i < annotations.length; i++) {
for (Annotation annotation : annotations[i]) {
if (annotation.annotationType().equals(annotationType)) {
- resultBuilder.add(AnnotationWithMetadata.withMetadata(annotation, parameterTypes[i]));
+ resultBuilder.add(
+ AnnotationWithMetadata.withMetadata(
+ annotation, /* allAnnotations= */ annotations[i], parameterTypes[i], testClass));
}
}
}
diff --git a/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterValueProvider.java b/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterValueProvider.java
index 3c42eec..a3ad576 100644
--- a/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterValueProvider.java
+++ b/junit5/src/main/java/com/google/testing/junit/testparameterinjector/junit5/TestParameterValueProvider.java
@@ -15,6 +15,7 @@
package com.google.testing.junit.testparameterinjector.junit5;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -34,7 +35,52 @@ interface TestParameterValueProvider {
* annotation is annotating a method, constructor or class, {@code parameterClass} is an empty
* optional.
*/
- List<Object> provideValues(Annotation annotation, Optional<Class<?>> parameterClass);
+ default List<Object> provideValues(Annotation annotation, Optional<Class<?>> parameterClass) {
+ throw new UnsupportedOperationException(
+ "If this is called by TestParameterInjector, it means that neither of the"
+ + " provideValues()-type methods have been implemented");
+ }
+
+ /**
+ * Extension of {@link #provideValues(Annotation, Optional<Class<?>>)} with extra context.
+ *
+ * @param annotation The annotation instance that was encountered in the test class. The
+ * definition of this annotation is itself annotated with the {@link TestParameterAnnotation}
+ * annotation.
+ * @param otherAnnotations A list of all other annotations on the field or parameter that was
+ * annotated with {@code annotation}.
+ * <p>For example, if the test code is as follows:
+ * <pre>
+ * @Test
+ * public void myTest_success(
+ * @CustomAnnotation(123) @TestParameter(valuesProvider=MyProvider.class) Foo foo) {
+ * ...
+ * }
+ * </pre>
+ * then this list will contain a single element: @CustomAnnotation(123).
+ * <p>In case the annotation is annotating a method, constructor or class, {@code
+ * parameterClass} is an empty list.
+ * @param parameterClass The class of the parameter or field that is being annotated. In case the
+ * annotation is annotating a method, constructor or class, {@code parameterClass} is an empty
+ * optional.
+ * @param testClass The class that contains the test that is currently being run.
+ * <p>Having this can be useful when sharing providers between tests that have the same base
+ * class. In those cases, an abstract method can be called as follows:
+ * <pre>
+ * ((MyBaseClass) context.testClass().newInstance()).myAbstractMethod()
+ * </pre>
+ *
+ * @deprecated Don't use this method outside of the testparameterinjector codebase, as it is prone
+ * to being changed.
+ */
+ @Deprecated
+ default List<Object> provideValues(
+ Annotation annotation,
+ ImmutableList<Annotation> otherAnnotations,
+ Optional<Class<?>> parameterClass,
+ Class<?> testClass) {
+ return provideValues(annotation, parameterClass);
+ }
/**
* Returns the class of the list elements returned by {@link #provideValues(Annotation,