diff options
Diffstat (limited to 'src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java')
-rw-r--r-- | src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java | 291 |
1 files changed, 184 insertions, 107 deletions
diff --git a/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java b/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java index 615cc3e..f15fb28 100644 --- a/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java +++ b/src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java @@ -1,19 +1,19 @@ -/** - * - */ package org.junit.experimental.theories.internal; import java.lang.reflect.Array; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; 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; import org.junit.experimental.theories.ParameterSupplier; import org.junit.experimental.theories.PotentialAssignment; +import org.junit.runners.model.FrameworkField; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.TestClass; @@ -21,107 +21,184 @@ import org.junit.runners.model.TestClass; * Supplies Theory parameters based on all public members of the target class. */ public class AllMembersSupplier extends ParameterSupplier { - static class MethodParameterValue extends PotentialAssignment { - private final FrameworkMethod fMethod; - - private MethodParameterValue(FrameworkMethod dataPointMethod) { - fMethod= dataPointMethod; - } - - @Override - public Object getValue() throws CouldNotGenerateValueException { - try { - return fMethod.invokeExplosively(null); - } catch (IllegalArgumentException e) { - throw new RuntimeException( - "unexpected: argument length is checked"); - } 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 - } - } - - @Override - public String getDescription() throws CouldNotGenerateValueException { - return fMethod.getName(); - } - } - - private final TestClass fClass; - - /** - * Constructs a new supplier for {@code type} - */ - public AllMembersSupplier(TestClass type) { - fClass= type; - } - - @Override - public List<PotentialAssignment> getValueSources(ParameterSignature sig) { - List<PotentialAssignment> list= new ArrayList<PotentialAssignment>(); - - addFields(sig, list); - addSinglePointMethods(sig, list); - addMultiPointMethods(list); - - return list; - } - - private void addMultiPointMethods(List<PotentialAssignment> list) { - for (FrameworkMethod dataPointsMethod : fClass - .getAnnotatedMethods(DataPoints.class)) - try { - addArrayValues(dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null)); - } catch (Throwable e) { - // ignore and move on - } - } - - @SuppressWarnings("deprecation") - private void addSinglePointMethods(ParameterSignature sig, - List<PotentialAssignment> list) { - for (FrameworkMethod dataPointMethod : fClass - .getAnnotatedMethods(DataPoint.class)) { - Class<?> type= sig.getType(); - if ((dataPointMethod.producesType(type))) - list.add(new MethodParameterValue(dataPointMethod)); - } - } - - private void addFields(ParameterSignature sig, - List<PotentialAssignment> list) { - for (final Field field : fClass.getJavaClass().getFields()) { - if (Modifier.isStatic(field.getModifiers())) { - Class<?> type= field.getType(); - if (sig.canAcceptArrayType(type) - && field.getAnnotation(DataPoints.class) != null) { - addArrayValues(field.getName(), list, getStaticFieldValue(field)); - } else if (sig.canAcceptType(type) - && field.getAnnotation(DataPoint.class) != null) { - list.add(PotentialAssignment - .forValue(field.getName(), getStaticFieldValue(field))); - } - } - } - } - - private void addArrayValues(String name, List<PotentialAssignment> list, Object array) { - for (int i= 0; i < Array.getLength(array); i++) - list.add(PotentialAssignment.forValue(name + "[" + i + "]", Array.get(array, i))); - } - - private Object getStaticFieldValue(final Field field) { - try { - return field.get(null); - } catch (IllegalArgumentException e) { - throw new RuntimeException( - "unexpected: field from getClass doesn't exist on object"); - } catch (IllegalAccessException e) { - throw new RuntimeException( - "unexpected: getFields returned an inaccessible field"); - } - } + static class MethodParameterValue extends PotentialAssignment { + private final FrameworkMethod method; + + private MethodParameterValue(FrameworkMethod dataPointMethod) { + method = dataPointMethod; + } + + @Override + public Object getValue() throws CouldNotGenerateValueException { + try { + return method.invokeExplosively(null); + } catch (IllegalArgumentException e) { + throw new RuntimeException( + "unexpected: argument length is checked"); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "unexpected: getMethods returned an inaccessible method"); + } catch (Throwable throwable) { + DataPoint annotation = method.getAnnotation(DataPoint.class); + Assume.assumeTrue(annotation == null || !isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)); + + throw new CouldNotGenerateValueException(throwable); + } + } + + @Override + public String getDescription() throws CouldNotGenerateValueException { + return method.getName(); + } + } + + private final TestClass clazz; + + /** + * Constructs a new supplier for {@code type} + */ + public AllMembersSupplier(TestClass type) { + clazz = type; + } + + @Override + public List<PotentialAssignment> getValueSources(ParameterSignature sig) throws Throwable { + List<PotentialAssignment> list = new ArrayList<PotentialAssignment>(); + + addSinglePointFields(sig, list); + addMultiPointFields(sig, list); + addSinglePointMethods(sig, list); + addMultiPointMethods(sig, list); + + return 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())) || + Iterable.class.isAssignableFrom(returnType)) { + try { + addDataPointsValues(returnType, sig, dataPointsMethod.getName(), list, + dataPointsMethod.invokeExplosively(null)); + } catch (Throwable throwable) { + DataPoints annotation = dataPointsMethod.getAnnotation(DataPoints.class); + if (annotation != null && isAssignableToAnyOf(annotation.ignoredExceptions(), throwable)) { + return; + } else { + throw throwable; + } + } + } + } + } + + private void addSinglePointMethods(ParameterSignature sig, List<PotentialAssignment> list) { + for (FrameworkMethod dataPointMethod : getSingleDataPointMethods(sig)) { + if (sig.canAcceptType(dataPointMethod.getType())) { + list.add(new MethodParameterValue(dataPointMethod)); + } + } + } + + private void addMultiPointFields(ParameterSignature sig, List<PotentialAssignment> list) { + for (final Field field : getDataPointsFields(sig)) { + Class<?> type = field.getType(); + addDataPointsValues(type, sig, field.getName(), list, getStaticFieldValue(field)); + } + } + + private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignment> list) { + for (final Field field : getSingleDataPointFields(sig)) { + Object value = getStaticFieldValue(field); + + if (sig.canAcceptValue(value)) { + list.add(PotentialAssignment.forValue(field.getName(), value)); + } + } + } + + private void addDataPointsValues(Class<?> type, ParameterSignature sig, String name, + List<PotentialAssignment> list, Object value) { + if (type.isArray()) { + addArrayValues(sig, name, list, value); + } + else if (Iterable.class.isAssignableFrom(type)) { + addIterableValues(sig, name, list, (Iterable<?>) value); + } + } + + private void addArrayValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Object array) { + for (int i = 0; i < Array.getLength(array); i++) { + Object value = Array.get(array, i); + if (sig.canAcceptValue(value)) { + list.add(PotentialAssignment.forValue(name + "[" + i + "]", value)); + } + } + } + + private void addIterableValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Iterable<?> iterable) { + Iterator<?> iterator = iterable.iterator(); + int i = 0; + while (iterator.hasNext()) { + Object value = iterator.next(); + if (sig.canAcceptValue(value)) { + list.add(PotentialAssignment.forValue(name + "[" + i + "]", value)); + } + i += 1; + } + } + + private Object getStaticFieldValue(final Field field) { + try { + return field.get(null); + } catch (IllegalArgumentException e) { + throw new RuntimeException( + "unexpected: field from getClass doesn't exist on object"); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "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 clazz.getAnnotatedMethods(DataPoints.class); + } + + protected Collection<Field> getSingleDataPointFields(ParameterSignature sig) { + List<FrameworkField> fields = clazz.getAnnotatedFields(DataPoint.class); + Collection<Field> validFields = new ArrayList<Field>(); + + for (FrameworkField frameworkField : fields) { + validFields.add(frameworkField.getField()); + } + + return validFields; + } + + protected Collection<Field> getDataPointsFields(ParameterSignature sig) { + List<FrameworkField> fields = clazz.getAnnotatedFields(DataPoints.class); + Collection<Field> validFields = new ArrayList<Field>(); + + for (FrameworkField frameworkField : fields) { + validFields.add(frameworkField.getField()); + } + + return validFields; + } + + protected Collection<FrameworkMethod> getSingleDataPointMethods(ParameterSignature sig) { + return clazz.getAnnotatedMethods(DataPoint.class); + } + }
\ No newline at end of file |