Home | History | Annotate | Download | only in internal
      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 }