001package org.junit.experimental.theories.internal; 002 003import static java.util.Collections.emptyList; 004 005import java.lang.reflect.Constructor; 006import java.lang.reflect.Method; 007import java.util.ArrayList; 008import java.util.List; 009 010import org.junit.experimental.theories.ParameterSignature; 011import org.junit.experimental.theories.ParameterSupplier; 012import org.junit.experimental.theories.ParametersSuppliedBy; 013import org.junit.experimental.theories.PotentialAssignment; 014import org.junit.experimental.theories.PotentialAssignment.CouldNotGenerateValueException; 015import org.junit.runners.model.TestClass; 016 017/** 018 * A potentially incomplete list of value assignments for a method's formal 019 * parameters 020 */ 021public class Assignments { 022 private final List<PotentialAssignment> assigned; 023 024 private final List<ParameterSignature> unassigned; 025 026 private final TestClass clazz; 027 028 private Assignments(List<PotentialAssignment> assigned, 029 List<ParameterSignature> unassigned, TestClass clazz) { 030 this.unassigned = unassigned; 031 this.assigned = assigned; 032 this.clazz = clazz; 033 } 034 035 /** 036 * Returns a new assignment list for {@code testMethod}, with no params 037 * assigned. 038 */ 039 public static Assignments allUnassigned(Method testMethod, 040 TestClass testClass) { 041 List<ParameterSignature> signatures; 042 signatures = ParameterSignature.signatures(testClass 043 .getOnlyConstructor()); 044 signatures.addAll(ParameterSignature.signatures(testMethod)); 045 return new Assignments(new ArrayList<PotentialAssignment>(), 046 signatures, testClass); 047 } 048 049 public boolean isComplete() { 050 return unassigned.isEmpty(); 051 } 052 053 public ParameterSignature nextUnassigned() { 054 return unassigned.get(0); 055 } 056 057 public Assignments assignNext(PotentialAssignment source) { 058 List<PotentialAssignment> potentialAssignments = new ArrayList<PotentialAssignment>(assigned); 059 potentialAssignments.add(source); 060 061 return new Assignments(potentialAssignments, unassigned.subList(1, 062 unassigned.size()), clazz); 063 } 064 065 public Object[] getActualValues(int start, int stop) 066 throws CouldNotGenerateValueException { 067 Object[] values = new Object[stop - start]; 068 for (int i = start; i < stop; i++) { 069 values[i - start] = assigned.get(i).getValue(); 070 } 071 return values; 072 } 073 074 public List<PotentialAssignment> potentialsForNextUnassigned() 075 throws Throwable { 076 ParameterSignature unassigned = nextUnassigned(); 077 List<PotentialAssignment> assignments = getSupplier(unassigned).getValueSources(unassigned); 078 079 if (assignments.isEmpty()) { 080 assignments = generateAssignmentsFromTypeAlone(unassigned); 081 } 082 083 return assignments; 084 } 085 086 private List<PotentialAssignment> generateAssignmentsFromTypeAlone(ParameterSignature unassigned) { 087 Class<?> paramType = unassigned.getType(); 088 089 if (paramType.isEnum()) { 090 return new EnumSupplier(paramType).getValueSources(unassigned); 091 } else if (paramType.equals(Boolean.class) || paramType.equals(boolean.class)) { 092 return new BooleanSupplier().getValueSources(unassigned); 093 } else { 094 return emptyList(); 095 } 096 } 097 098 private ParameterSupplier getSupplier(ParameterSignature unassigned) 099 throws Exception { 100 ParametersSuppliedBy annotation = unassigned 101 .findDeepAnnotation(ParametersSuppliedBy.class); 102 103 if (annotation != null) { 104 return buildParameterSupplierFromClass(annotation.value()); 105 } else { 106 return new AllMembersSupplier(clazz); 107 } 108 } 109 110 private ParameterSupplier buildParameterSupplierFromClass( 111 Class<? extends ParameterSupplier> cls) throws Exception { 112 Constructor<?>[] supplierConstructors = cls.getConstructors(); 113 114 for (Constructor<?> constructor : supplierConstructors) { 115 Class<?>[] parameterTypes = constructor.getParameterTypes(); 116 if (parameterTypes.length == 1 117 && parameterTypes[0].equals(TestClass.class)) { 118 return (ParameterSupplier) constructor.newInstance(clazz); 119 } 120 } 121 122 return cls.newInstance(); 123 } 124 125 public Object[] getConstructorArguments() 126 throws CouldNotGenerateValueException { 127 return getActualValues(0, getConstructorParameterCount()); 128 } 129 130 public Object[] getMethodArguments() throws CouldNotGenerateValueException { 131 return getActualValues(getConstructorParameterCount(), assigned.size()); 132 } 133 134 public Object[] getAllArguments() throws CouldNotGenerateValueException { 135 return getActualValues(0, assigned.size()); 136 } 137 138 private int getConstructorParameterCount() { 139 List<ParameterSignature> signatures = ParameterSignature 140 .signatures(clazz.getOnlyConstructor()); 141 int constructorParameterCount = signatures.size(); 142 return constructorParameterCount; 143 } 144 145 public Object[] getArgumentStrings(boolean nullsOk) 146 throws CouldNotGenerateValueException { 147 Object[] values = new Object[assigned.size()]; 148 for (int i = 0; i < values.length; i++) { 149 values[i] = assigned.get(i).getDescription(); 150 } 151 return values; 152 } 153}