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.size() == 0; 051 } 052 053 public ParameterSignature nextUnassigned() { 054 return unassigned.get(0); 055 } 056 057 public Assignments assignNext(PotentialAssignment source) { 058 List<PotentialAssignment> assigned = new ArrayList<PotentialAssignment>( 059 this.assigned); 060 assigned.add(source); 061 062 return new Assignments(assigned, unassigned.subList(1, 063 unassigned.size()), clazz); 064 } 065 066 public Object[] getActualValues(int start, int stop) 067 throws CouldNotGenerateValueException { 068 Object[] values = new Object[stop - start]; 069 for (int i = start; i < stop; i++) { 070 values[i - start] = assigned.get(i).getValue(); 071 } 072 return values; 073 } 074 075 public List<PotentialAssignment> potentialsForNextUnassigned() 076 throws Throwable { 077 ParameterSignature unassigned = nextUnassigned(); 078 List<PotentialAssignment> assignments = getSupplier(unassigned).getValueSources(unassigned); 079 080 if (assignments.size() == 0) { 081 assignments = generateAssignmentsFromTypeAlone(unassigned); 082 } 083 084 return assignments; 085 } 086 087 private List<PotentialAssignment> generateAssignmentsFromTypeAlone(ParameterSignature unassigned) { 088 Class<?> paramType = unassigned.getType(); 089 090 if (paramType.isEnum()) { 091 return new EnumSupplier(paramType).getValueSources(unassigned); 092 } else if (paramType.equals(Boolean.class) || paramType.equals(boolean.class)) { 093 return new BooleanSupplier().getValueSources(unassigned); 094 } else { 095 return emptyList(); 096 } 097 } 098 099 private ParameterSupplier getSupplier(ParameterSignature unassigned) 100 throws Exception { 101 ParametersSuppliedBy annotation = unassigned 102 .findDeepAnnotation(ParametersSuppliedBy.class); 103 104 if (annotation != null) { 105 return buildParameterSupplierFromClass(annotation.value()); 106 } else { 107 return new AllMembersSupplier(clazz); 108 } 109 } 110 111 private ParameterSupplier buildParameterSupplierFromClass( 112 Class<? extends ParameterSupplier> cls) throws Exception { 113 Constructor<?>[] supplierConstructors = cls.getConstructors(); 114 115 for (Constructor<?> constructor : supplierConstructors) { 116 Class<?>[] parameterTypes = constructor.getParameterTypes(); 117 if (parameterTypes.length == 1 118 && parameterTypes[0].equals(TestClass.class)) { 119 return (ParameterSupplier) constructor.newInstance(clazz); 120 } 121 } 122 123 return cls.newInstance(); 124 } 125 126 public Object[] getConstructorArguments() 127 throws CouldNotGenerateValueException { 128 return getActualValues(0, getConstructorParameterCount()); 129 } 130 131 public Object[] getMethodArguments() throws CouldNotGenerateValueException { 132 return getActualValues(getConstructorParameterCount(), assigned.size()); 133 } 134 135 public Object[] getAllArguments() throws CouldNotGenerateValueException { 136 return getActualValues(0, assigned.size()); 137 } 138 139 private int getConstructorParameterCount() { 140 List<ParameterSignature> signatures = ParameterSignature 141 .signatures(clazz.getOnlyConstructor()); 142 int constructorParameterCount = signatures.size(); 143 return constructorParameterCount; 144 } 145 146 public Object[] getArgumentStrings(boolean nullsOk) 147 throws CouldNotGenerateValueException { 148 Object[] values = new Object[assigned.size()]; 149 for (int i = 0; i < values.length; i++) { 150 values[i] = assigned.get(i).getDescription(); 151 } 152 return values; 153 } 154}