Skip to content

Commit

Permalink
Merge pull request #639 from pimterry/datapoints-exceptions-#449
Browse files Browse the repository at this point in the history
Fixes #449, stopping AllMembersSupplier & Theories hiding DataPoints method exceptions
  • Loading branch information
David Saff committed Mar 26, 2013
2 parents 8d7f5cc + dbe7711 commit 34e6674
Show file tree
Hide file tree
Showing 18 changed files with 294 additions and 105 deletions.
3 changes: 2 additions & 1 deletion src/main/java/org/junit/experimental/theories/DataPoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@
@Target({FIELD, METHOD})
public @interface DataPoint {
String[] value() default {};
}
Class<? extends Throwable>[] ignoredExceptions() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@
@Target({FIELD, METHOD})
public @interface DataPoints {
String[] value() default {};
Class<? extends Throwable>[] ignoredExceptions() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import java.util.List;

public abstract class ParameterSupplier {
public abstract List<PotentialAssignment> getValueSources(ParameterSignature sig);
public abstract List<PotentialAssignment> getValueSources(ParameterSignature sig) throws Throwable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
public abstract class PotentialAssignment {
public static class CouldNotGenerateValueException extends Exception {
private static final long serialVersionUID = 1L;

public CouldNotGenerateValueException() {
}

public CouldNotGenerateValueException(Throwable t) {
super(t);
}
}

public static PotentialAssignment forValue(final String name, final Object value) {
Expand Down
23 changes: 14 additions & 9 deletions src/main/java/org/junit/experimental/theories/Theories.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.List;

import org.junit.Assert;
import org.junit.experimental.theories.PotentialAssignment.CouldNotGenerateValueException;
import org.junit.Assume;
import org.junit.experimental.theories.internal.Assignments;
import org.junit.experimental.theories.internal.ParameterizedAssertionError;
import org.junit.internal.AssumptionViolatedException;
Expand Down Expand Up @@ -202,8 +202,13 @@ protected Statement methodInvoker(FrameworkMethod method, Object test) {

@Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(
complete.getConstructorArguments(nullsOk()));
Object[] params = complete.getConstructorArguments();

if (!nullsOk()) {
Assume.assumeNotNull(params);
}

return getTestClass().getOnlyConstructor().newInstance(params);
}
}.methodBlock(fTestMethod).evaluate();
}
Expand All @@ -213,13 +218,13 @@ private Statement methodCompletesWithParameters(
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
final Object[] values = complete.getMethodArguments(
nullsOk());
method.invokeExplosively(freshInstance, values);
} catch (CouldNotGenerateValueException e) {
// ignore
final Object[] values = complete.getMethodArguments();

if (!nullsOk()) {
Assume.assumeNotNull(values);
}

method.invokeExplosively(freshInstance, values);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Collection;
import java.util.List;

import org.junit.Assume;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.ParameterSignature;
Expand Down Expand Up @@ -36,17 +37,20 @@ public Object getValue() throws CouldNotGenerateValueException {
} catch (IllegalAccessException e) {
throw new RuntimeException(
"unexpected: getMethods returned an inaccessible method");
} catch (Throwable e) {
throw new CouldNotGenerateValueException();
// do nothing, just look for more values
} catch (Throwable throwable) {
DataPoint annotation = fMethod.getAnnotation(DataPoint.class);
Assume.assumeTrue(annotation == null || !isAssignableToAnyOf(annotation.ignoredExceptions(), throwable));

throw new CouldNotGenerateValueException(throwable);
}
}
}

@Override
public String getDescription() throws CouldNotGenerateValueException {
return fMethod.getName();
}
}
}

private final TestClass fClass;

/**
Expand All @@ -57,7 +61,7 @@ public AllMembersSupplier(TestClass type) {
}

@Override
public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
public List<PotentialAssignment> getValueSources(ParameterSignature sig) throws Throwable {
List<PotentialAssignment> list = new ArrayList<PotentialAssignment>();

addSinglePointFields(sig, list);
Expand All @@ -68,15 +72,20 @@ public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
return list;
}

private void addMultiPointMethods(ParameterSignature sig, List<PotentialAssignment> list) {
private void addMultiPointMethods(ParameterSignature sig, List<PotentialAssignment> list) throws Throwable {
for (FrameworkMethod dataPointsMethod : getDataPointsMethods(sig)) {
Class<?> returnType = dataPointsMethod.getReturnType();

if (returnType.isArray() && sig.canPotentiallyAcceptType(returnType.getComponentType())) {
try {
addArrayValues(sig, dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
} catch (Throwable e) {
// ignore and move on
} catch (Throwable throwable) {
DataPoints annotation = dataPointsMethod.getAnnotation(DataPoints.class);
if (annotation != null && isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)) {
return;
} else {
throw throwable;
}
}
}
}
Expand All @@ -94,7 +103,7 @@ private void addMultiPointFields(ParameterSignature sig, List<PotentialAssignmen
for (final Field field : getDataPointsFields(sig)) {
addArrayValues(sig, field.getName(), list, getStaticFieldValue(field));
}
}
}

private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignment> list) {
for (final Field field : getSingleDataPointFields(sig)) {
Expand Down Expand Up @@ -126,6 +135,15 @@ private Object getStaticFieldValue(final Field field) {
"unexpected: getFields returned an inaccessible field");
}
}

private static boolean isAssignableToAnyOf(Class<?>[] typeArray, Object target) {
for (Class<?> type : typeArray) {
if (type.isAssignableFrom(target.getClass())) {
return true;
}
}
return false;
}

protected Collection<FrameworkMethod> getDataPointsMethods(ParameterSignature sig) {
return fClass.getAnnotatedMethods(DataPoints.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,17 @@ public Assignments assignNext(PotentialAssignment source) {
fUnassigned.size()), fClass);
}

public Object[] getActualValues(int start, int stop, boolean nullsOk)
public Object[] getActualValues(int start, int stop)
throws CouldNotGenerateValueException {
Object[] values = new Object[stop - start];
for (int i = start; i < stop; i++) {
Object value = fAssigned.get(i).getValue();
if (value == null && !nullsOk) {
throw new CouldNotGenerateValueException();
}
values[i - start] = value;
values[i - start] = fAssigned.get(i).getValue();
}
return values;
}

public List<PotentialAssignment> potentialsForNextUnassigned()
throws Exception {
throws Throwable {
ParameterSignature unassigned = nextUnassigned();
List<PotentialAssignment> assignments = getSupplier(unassigned).getValueSources(unassigned);

Expand Down Expand Up @@ -127,20 +123,17 @@ private ParameterSupplier buildParameterSupplierFromClass(
return cls.newInstance();
}

public Object[] getConstructorArguments(boolean nullsOk)
public Object[] getConstructorArguments()
throws CouldNotGenerateValueException {
return getActualValues(0, getConstructorParameterCount(), nullsOk);
return getActualValues(0, getConstructorParameterCount());
}

public Object[] getMethodArguments(boolean nullsOk)
throws CouldNotGenerateValueException {
return getActualValues(getConstructorParameterCount(),
fAssigned.size(), nullsOk);
public Object[] getMethodArguments() throws CouldNotGenerateValueException {
return getActualValues(getConstructorParameterCount(), fAssigned.size());
}

public Object[] getAllArguments(boolean nullsOk)
throws CouldNotGenerateValueException {
return getActualValues(0, fAssigned.size(), nullsOk);
public Object[] getAllArguments() throws CouldNotGenerateValueException {
return getActualValues(0, fAssigned.size());
}

private int getConstructorParameterCount() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected Collection<Field> getSingleDataPointFields(ParameterSignature sig) {
}
}

return fieldsWithMatchingNames;
return fieldsWithMatchingNames;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public final class TheoryTestUtils {
private TheoryTestUtils() { }

public static List<PotentialAssignment> potentialAssignments(Method method)
throws Exception {
throws Throwable {
return Assignments.allUnassigned(method,
new TestClass(method.getDeclaringClass()))
.potentialsForNextUnassigned();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected void runWithIncompleteAssignment(Assignments incomplete)
}

private GuesserQueue createGuesserQueue(Assignments incomplete)
throws Exception {
throws Throwable {
ParameterSignature nextUnassigned = incomplete.nextUnassigned();

if (nextUnassigned.hasAnnotation(Stub.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@

import java.util.List;

import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.PotentialAssignment;
import org.junit.experimental.theories.Theory;
import org.junit.experimental.theories.internal.AllMembersSupplier;
import org.junit.rules.ExpectedException;
import org.junit.runners.model.TestClass;

public class AllMembersSupplierTest {
@Rule
public ExpectedException expected = ExpectedException.none();


public static class HasDataPointsArrayField {
@DataPoints
Expand All @@ -29,7 +34,7 @@ public void theory(String param) {
}

@Test
public void dataPointsArrayShouldBeRecognized() throws Exception {
public void dataPointsArrayShouldBeRecognized() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsArrayField.class.getMethod("theory", String.class));

Expand All @@ -46,7 +51,7 @@ public void theory(Integer param) {
}

@Test
public void dataPointsArrayShouldBeRecognizedOnValueTypeNotFieldType() throws Exception {
public void dataPointsArrayShouldBeRecognizedOnValueTypeNotFieldType() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsArrayWithMatchingButInaccurateTypes.class.getMethod("theory", Integer.class));

Expand All @@ -65,7 +70,7 @@ public void theory(Object param) {
}

@Test
public void dataPointMethodShouldBeRecognizedForOverlyGeneralParameters() throws Exception {
public void dataPointMethodShouldBeRecognizedForOverlyGeneralParameters() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointMethodWithOverlyGeneralTypes.class.getMethod("theory", Object.class));

Expand All @@ -82,7 +87,7 @@ public void theory(Object obj) {
}

@Test
public void dataPointsAnnotationMeansTreatAsArrayOnly() throws Exception {
public void dataPointsAnnotationMeansTreatAsArrayOnly() throws Throwable {
List<PotentialAssignment> assignments = potentialAssignments(
HasDataPointsWithObjectParameter.class.getMethod("theory", Object.class));

Expand All @@ -101,13 +106,9 @@ public HasDataPointsFieldWithNullValue(Object obj) {
}

@Test
public void dataPointsArrayFieldMayContainNullValue()
throws SecurityException, NoSuchMethodException {
List<PotentialAssignment> valueSources = new AllMembersSupplier(
new TestClass(HasDataPointsFieldWithNullValue.class))
.getValueSources(ParameterSignature.signatures(
HasDataPointsFieldWithNullValue.class.getConstructor(Object.class))
.get(0));
public void dataPointsArrayFieldMayContainNullValue() throws Throwable {
List<PotentialAssignment> valueSources = allMemberValuesFor(
HasDataPointsFieldWithNullValue.class, Object.class);
assertThat(valueSources.size(), is(2));
}

Expand All @@ -122,13 +123,34 @@ public HasDataPointsMethodWithNullValue(Integer i) {
}

@Test
public void dataPointsArrayMethodMayContainNullValue()
throws SecurityException, NoSuchMethodException {
List<PotentialAssignment> valueSources = new AllMembersSupplier(
new TestClass(HasDataPointsMethodWithNullValue.class))
public void dataPointsArrayMethodMayContainNullValue() throws Throwable {
List<PotentialAssignment> valueSources = allMemberValuesFor(
HasDataPointsMethodWithNullValue.class, Integer.class);
assertThat(valueSources.size(), is(2));
}

public static class HasFailingDataPointsArrayMethod {
@DataPoints
public static Object[] objects() {
throw new RuntimeException("failing method");
}

public HasFailingDataPointsArrayMethod(Object obj) {
}
}

@Test
public void allMembersFailsOnFailingDataPointsArrayMethod() throws Throwable {
expected.expect(RuntimeException.class);
expected.expectMessage("failing method");
allMemberValuesFor(HasFailingDataPointsArrayMethod.class, Object.class);
}

private List<PotentialAssignment> allMemberValuesFor(Class<?> testClass,
Class<?>... constructorParameterTypes) throws Throwable {
return new AllMembersSupplier(new TestClass(testClass))
.getValueSources(ParameterSignature.signatures(
HasDataPointsMethodWithNullValue.class.getConstructor(Integer.class))
testClass.getConstructor(constructorParameterTypes))
.get(0));
assertThat(valueSources.size(), is(2));
}
}
Loading

0 comments on commit 34e6674

Please sign in to comment.