1 /** 2 * 3 */ 4 package org.junit.experimental.theories.internal; 5 6 import java.lang.reflect.Array; 7 import java.lang.reflect.Field; 8 import java.lang.reflect.Modifier; 9 import java.util.ArrayList; 10 import java.util.List; 11 12 import org.junit.experimental.theories.DataPoint; 13 import org.junit.experimental.theories.DataPoints; 14 import org.junit.experimental.theories.ParameterSignature; 15 import org.junit.experimental.theories.ParameterSupplier; 16 import org.junit.experimental.theories.PotentialAssignment; 17 import org.junit.runners.model.FrameworkMethod; 18 import org.junit.runners.model.TestClass; 19 20 /** 21 * Supplies Theory parameters based on all public members of the target class. 22 */ 23 public class AllMembersSupplier extends ParameterSupplier { 24 static class MethodParameterValue extends PotentialAssignment { 25 private final FrameworkMethod fMethod; 26 27 private MethodParameterValue(FrameworkMethod dataPointMethod) { 28 fMethod= dataPointMethod; 29 } 30 31 @Override 32 public Object getValue() throws CouldNotGenerateValueException { 33 try { 34 return fMethod.invokeExplosively(null); 35 } catch (IllegalArgumentException e) { 36 throw new RuntimeException( 37 "unexpected: argument length is checked"); 38 } catch (IllegalAccessException e) { 39 throw new RuntimeException( 40 "unexpected: getMethods returned an inaccessible method"); 41 } catch (Throwable e) { 42 throw new CouldNotGenerateValueException(); 43 // do nothing, just look for more values 44 } 45 } 46 47 @Override 48 public String getDescription() throws CouldNotGenerateValueException { 49 return fMethod.getName(); 50 } 51 } 52 53 private final TestClass fClass; 54 55 /** 56 * Constructs a new supplier for {@code type} 57 */ 58 public AllMembersSupplier(TestClass type) { 59 fClass= type; 60 } 61 62 @Override 63 public List<PotentialAssignment> getValueSources(ParameterSignature sig) { 64 List<PotentialAssignment> list= new ArrayList<PotentialAssignment>(); 65 66 addFields(sig, list); 67 addSinglePointMethods(sig, list); 68 addMultiPointMethods(list); 69 70 return list; 71 } 72 73 private void addMultiPointMethods(List<PotentialAssignment> list) { 74 for (FrameworkMethod dataPointsMethod : fClass 75 .getAnnotatedMethods(DataPoints.class)) 76 try { 77 addArrayValues(dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null)); 78 } catch (Throwable e) { 79 // ignore and move on 80 } 81 } 82 83 @SuppressWarnings("deprecation") 84 private void addSinglePointMethods(ParameterSignature sig, 85 List<PotentialAssignment> list) { 86 for (FrameworkMethod dataPointMethod : fClass 87 .getAnnotatedMethods(DataPoint.class)) { 88 Class<?> type= sig.getType(); 89 if ((dataPointMethod.producesType(type))) 90 list.add(new MethodParameterValue(dataPointMethod)); 91 } 92 } 93 94 private void addFields(ParameterSignature sig, 95 List<PotentialAssignment> list) { 96 for (final Field field : fClass.getJavaClass().getFields()) { 97 if (Modifier.isStatic(field.getModifiers())) { 98 Class<?> type= field.getType(); 99 if (sig.canAcceptArrayType(type) 100 && field.getAnnotation(DataPoints.class) != null) { 101 addArrayValues(field.getName(), list, getStaticFieldValue(field)); 102 } else if (sig.canAcceptType(type) 103 && field.getAnnotation(DataPoint.class) != null) { 104 list.add(PotentialAssignment 105 .forValue(field.getName(), getStaticFieldValue(field))); 106 } 107 } 108 } 109 } 110 111 private void addArrayValues(String name, List<PotentialAssignment> list, Object array) { 112 for (int i= 0; i < Array.getLength(array); i++) 113 list.add(PotentialAssignment.forValue(name + "[" + i + "]", Array.get(array, i))); 114 } 115 116 private Object getStaticFieldValue(final Field field) { 117 try { 118 return field.get(null); 119 } catch (IllegalArgumentException e) { 120 throw new RuntimeException( 121 "unexpected: field from getClass doesn't exist on object"); 122 } catch (IllegalAccessException e) { 123 throw new RuntimeException( 124 "unexpected: getFields returned an inaccessible field"); 125 } 126 } 127 }