package org.junit.experimental.theories.internal; import static java.util.Collections.emptyList; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.junit.experimental.theories.ParameterSignature; import org.junit.experimental.theories.ParameterSupplier; import org.junit.experimental.theories.ParametersSuppliedBy; import org.junit.experimental.theories.PotentialAssignment; import org.junit.experimental.theories.PotentialAssignment.CouldNotGenerateValueException; import org.junit.runners.model.TestClass; /** * A potentially incomplete list of value assignments for a method's formal * parameters */ public class Assignments { private final List assigned; private final List unassigned; private final TestClass clazz; private Assignments(List assigned, List unassigned, TestClass clazz) { this.unassigned = unassigned; this.assigned = assigned; this.clazz = clazz; } /** * Returns a new assignment list for {@code testMethod}, with no params * assigned. */ public static Assignments allUnassigned(Method testMethod, TestClass testClass) { List signatures; signatures = ParameterSignature.signatures(testClass .getOnlyConstructor()); signatures.addAll(ParameterSignature.signatures(testMethod)); return new Assignments(new ArrayList(), signatures, testClass); } public boolean isComplete() { return unassigned.size() == 0; } public ParameterSignature nextUnassigned() { return unassigned.get(0); } public Assignments assignNext(PotentialAssignment source) { List assigned = new ArrayList( this.assigned); assigned.add(source); return new Assignments(assigned, unassigned.subList(1, unassigned.size()), clazz); } public Object[] getActualValues(int start, int stop) throws CouldNotGenerateValueException { Object[] values = new Object[stop - start]; for (int i = start; i < stop; i++) { values[i - start] = assigned.get(i).getValue(); } return values; } public List potentialsForNextUnassigned() throws Throwable { ParameterSignature unassigned = nextUnassigned(); List assignments = getSupplier(unassigned).getValueSources(unassigned); if (assignments.size() == 0) { assignments = generateAssignmentsFromTypeAlone(unassigned); } return assignments; } private List generateAssignmentsFromTypeAlone(ParameterSignature unassigned) { Class paramType = unassigned.getType(); if (paramType.isEnum()) { return new EnumSupplier(paramType).getValueSources(unassigned); } else if (paramType.equals(Boolean.class) || paramType.equals(boolean.class)) { return new BooleanSupplier().getValueSources(unassigned); } else { return emptyList(); } } private ParameterSupplier getSupplier(ParameterSignature unassigned) throws Exception { ParametersSuppliedBy annotation = unassigned .findDeepAnnotation(ParametersSuppliedBy.class); if (annotation != null) { return buildParameterSupplierFromClass(annotation.value()); } else { return new AllMembersSupplier(clazz); } } private ParameterSupplier buildParameterSupplierFromClass( Class cls) throws Exception { Constructor[] supplierConstructors = cls.getConstructors(); for (Constructor constructor : supplierConstructors) { Class[] parameterTypes = constructor.getParameterTypes(); if (parameterTypes.length == 1 && parameterTypes[0].equals(TestClass.class)) { return (ParameterSupplier) constructor.newInstance(clazz); } } return cls.newInstance(); } public Object[] getConstructorArguments() throws CouldNotGenerateValueException { return getActualValues(0, getConstructorParameterCount()); } public Object[] getMethodArguments() throws CouldNotGenerateValueException { return getActualValues(getConstructorParameterCount(), assigned.size()); } public Object[] getAllArguments() throws CouldNotGenerateValueException { return getActualValues(0, assigned.size()); } private int getConstructorParameterCount() { List signatures = ParameterSignature .signatures(clazz.getOnlyConstructor()); int constructorParameterCount = signatures.size(); return constructorParameterCount; } public Object[] getArgumentStrings(boolean nullsOk) throws CouldNotGenerateValueException { Object[] values = new Object[assigned.size()]; for (int i = 0; i < values.length; i++) { values[i] = assigned.get(i).getDescription(); } return values; } }