Skip to content

Commit cc8497f

Browse files
committed
Parameters are now matched on value, not defined type, for array and single-valued methods and fields.
1 parent 2ade5fd commit cc8497f

File tree

4 files changed

+165
-56
lines changed

4 files changed

+165
-56
lines changed

src/main/java/org/junit/experimental/theories/ParameterSignature.java

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,29 @@
22

33
import java.lang.annotation.Annotation;
44
import java.lang.reflect.Constructor;
5+
import java.lang.reflect.Field;
56
import java.lang.reflect.Method;
7+
import java.lang.reflect.Modifier;
68
import java.util.ArrayList;
79
import java.util.Arrays;
10+
import java.util.HashMap;
811
import java.util.List;
12+
import java.util.Map;
913

1014
public class ParameterSignature {
15+
16+
@SuppressWarnings("serial")
17+
private static final Map<Class<?>, Class<?>> primitivesBoxingMap = new HashMap<Class<?>, Class<?>>() {{
18+
put(boolean.class, Boolean.class);
19+
put(byte.class, Byte.class);
20+
put(short.class, Short.class);
21+
put(char.class, Character.class);
22+
put(int.class, Integer.class);
23+
put(long.class, Long.class);
24+
put(float.class, Float.class);
25+
put(double.class, Double.class);
26+
}};
27+
1128
public static ArrayList<ParameterSignature> signatures(Method method) {
1229
return signatures(method.getParameterTypes(), method
1330
.getParameterAnnotations());
@@ -42,21 +59,48 @@ public boolean canAcceptValue(Object candidate) {
4259
}
4360

4461
public boolean canAcceptType(Class<?> candidate) {
45-
return type.isAssignableFrom(candidate);
62+
return type.isAssignableFrom(candidate) ||
63+
canAcceptBoxed(candidate) ||
64+
canAcceptUnboxed(candidate);
4665
}
4766

48-
public Class<?> getType() {
67+
private boolean canAcceptBoxed(Class<?> candidate) {
68+
if (primitivesBoxingMap.containsKey(candidate)) {
69+
Class<?> wrapperClass = primitivesBoxingMap.get(candidate);
70+
return type.isAssignableFrom(wrapperClass);
71+
} else {
72+
return false;
73+
}
74+
}
75+
76+
private boolean canAcceptUnboxed(Class<?> candidate) {
77+
Field primitiveClassField = null;
78+
try {
79+
primitiveClassField = candidate.getDeclaredField("TYPE");
80+
} catch (NoSuchFieldException e) {
81+
return false;
82+
}
83+
84+
try {
85+
if (Modifier.isStatic(primitiveClassField.getModifiers())) {
86+
Class<?> primitiveClass = (Class<?>) primitiveClassField.get(null);
87+
return type.isAssignableFrom(primitiveClass);
88+
} else {
89+
return false;
90+
}
91+
} catch (Exception e) {
92+
throw new RuntimeException(e);
93+
}
94+
}
95+
96+
public Class<?> getType() {
4997
return type;
5098
}
5199

52100
public List<Annotation> getAnnotations() {
53101
return Arrays.asList(annotations);
54102
}
55103

56-
public boolean canAcceptArrayType(Class<?> type) {
57-
return type.isArray() && canAcceptType(type.getComponentType());
58-
}
59-
60104
public boolean hasAnnotation(Class<? extends Annotation> type) {
61105
return getAnnotation(type) != null;
62106
}

src/main/java/org/junit/experimental/theories/internal/AllMembersSupplier.java

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,63 +44,52 @@ public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
4444
private void addMultiPointMethods(ParameterSignature sig, List<PotentialAssignment> list) {
4545
for (FrameworkMethod dataPointsMethod : getDataPointsMethods(sig)) {
4646
try {
47-
addMultiPointArrayValues(sig, dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
47+
addArrayValues(sig, dataPointsMethod.getName(), list, dataPointsMethod.invokeExplosively(null));
4848
} catch (Throwable e) {
4949
// ignore and move on
5050
}
5151
}
5252
}
5353

54-
private void addSinglePointMethods(ParameterSignature sig,
55-
List<PotentialAssignment> list) {
54+
private void addSinglePointMethods(ParameterSignature sig, List<PotentialAssignment> list) {
5655
for (FrameworkMethod dataPointMethod : getSingleDataPointMethods(sig)) {
57-
if (sig.canAcceptType(dataPointMethod.getType())) {
58-
try {
59-
list.add(PotentialAssignment.forValue(dataPointMethod.getName(), dataPointMethod.invokeExplosively(null)));
60-
} catch (Throwable e) {
61-
// ignore and move on
62-
}
56+
Object value;
57+
58+
try {
59+
value = dataPointMethod.invokeExplosively(null);
60+
} catch (Throwable e) {
61+
// ignore and move on
62+
continue;
63+
}
64+
65+
if (sig.canAcceptValue(value)) {
66+
list.add(PotentialAssignment.forValue(dataPointMethod.getName(), value));
6367
}
6468
}
6569
}
6670

67-
private void addMultiPointFields(ParameterSignature sig,
68-
List<PotentialAssignment> list) {
71+
private void addMultiPointFields(ParameterSignature sig, List<PotentialAssignment> list) {
6972
for (final Field field : getDataPointsFields(sig)) {
70-
Class<?> type = field.getType();
71-
if (sig.canAcceptArrayType(type)) {
72-
try {
73-
addArrayValues(field.getName(), list, getStaticFieldValue(field));
74-
} catch (Throwable e) {
75-
// ignore and move on
76-
}
77-
}
73+
addArrayValues(sig, field.getName(), list, getStaticFieldValue(field));
7874
}
79-
}
75+
}
8076

81-
private void addSinglePointFields(ParameterSignature sig,
82-
List<PotentialAssignment> list) {
77+
private void addSinglePointFields(ParameterSignature sig, List<PotentialAssignment> list) {
8378
for (final Field field : getSingleDataPointFields(sig)) {
84-
Class<?> type = field.getType();
85-
if (sig.canAcceptType(type)) {
86-
list.add(PotentialAssignment.forValue(field.getName(), getStaticFieldValue(field)));
79+
Object value = getStaticFieldValue(field);
80+
81+
if (sig.canAcceptValue(value)) {
82+
list.add(PotentialAssignment.forValue(field.getName(), value));
8783
}
8884
}
8985
}
9086

91-
private void addArrayValues(String name, List<PotentialAssignment> list, Object array) {
92-
for (int i = 0; i < Array.getLength(array); i++) {
93-
list.add(PotentialAssignment.forValue(name + "[" + i + "]", Array.get(array, i)));
94-
}
95-
}
96-
97-
private void addMultiPointArrayValues(ParameterSignature sig, String name, List<PotentialAssignment> list,
98-
Object array) throws Throwable {
87+
private void addArrayValues(ParameterSignature sig, String name, List<PotentialAssignment> list, Object array) {
9988
for (int i = 0; i < Array.getLength(array); i++) {
100-
if (!sig.canAcceptValue(Array.get(array, i))) {
101-
return;
89+
Object value = Array.get(array, i);
90+
if (sig.canAcceptValue(value)) {
91+
list.add(PotentialAssignment.forValue(name + "[" + i + "]", value));
10292
}
103-
list.add(PotentialAssignment.forValue(name + "[" + i + "]", Array.get(array, i)));
10493
}
10594
}
10695

src/test/java/org/junit/tests/experimental/theories/ParameterSignatureTest.java

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.hamcrest.CoreMatchers.isA;
44
import static org.junit.Assert.assertEquals;
55
import static org.junit.Assert.assertThat;
6+
import static org.junit.Assert.assertTrue;
67
import static org.junit.Assume.assumeTrue;
78

89
import java.lang.annotation.Annotation;
@@ -40,17 +41,52 @@ public void getType(Method method, int index) {
4041
.signatures(method).get(index).getType());
4142
}
4243

43-
public void foo(@TestedOn(ints = {1, 2, 3})
44-
int x) {
44+
public void foo(@TestedOn(ints = {1, 2, 3}) int x) {
4545
}
4646

4747
@Test
4848
public void getAnnotations() throws SecurityException,
4949
NoSuchMethodException {
50-
Method method = ParameterSignatureTest.class.getMethod("foo", int.class);
50+
Method method = getClass().getMethod("foo", int.class);
5151
List<Annotation> annotations = ParameterSignature.signatures(method)
5252
.get(0).getAnnotations();
5353
assertThat(annotations,
5454
CoreMatchers.<TestedOn>hasItem(isA(TestedOn.class)));
5555
}
56+
57+
public void intMethod(int param) {
58+
}
59+
60+
public void integerMethod(Integer param) {
61+
}
62+
63+
public void numberMethod(Number param) {
64+
}
65+
66+
@Test
67+
public void primitiveTypesShouldBeAcceptedAsWrapperTypes() throws Exception {
68+
List<ParameterSignature> signatures = ParameterSignature
69+
.signatures(getClass().getMethod("integerMethod", Integer.class));
70+
ParameterSignature integerSignature = signatures.get(0);
71+
72+
assertTrue(integerSignature.canAcceptType(int.class));
73+
}
74+
75+
@Test
76+
public void primitiveTypesShouldBeAcceptedAsWrapperTypeAssignables() throws Exception {
77+
List<ParameterSignature> signatures = ParameterSignature
78+
.signatures(getClass().getMethod("numberMethod", Number.class));
79+
ParameterSignature numberSignature = signatures.get(0);
80+
81+
assertTrue(numberSignature.canAcceptType(int.class));
82+
}
83+
84+
@Test
85+
public void wrapperTypesShouldBeAcceptedAsPrimitiveTypes() throws Exception {
86+
List<ParameterSignature> signatures = ParameterSignature
87+
.signatures(getClass().getMethod("intMethod", int.class));
88+
ParameterSignature intSignature = signatures.get(0);
89+
90+
assertTrue(intSignature.canAcceptType(Integer.class));
91+
}
5692
}

src/test/java/org/junit/tests/experimental/theories/internal/AllMembersSupplierTest.java

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,75 @@
11
package org.junit.tests.experimental.theories.internal;
22

33
import static org.hamcrest.CoreMatchers.is;
4+
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertNotEquals;
46
import static org.junit.Assert.assertThat;
7+
import static org.junit.tests.experimental.theories.TheoryTestUtils.potentialAssignments;
58

69
import java.util.List;
710

811
import org.junit.Test;
912
import org.junit.experimental.theories.DataPoints;
1013
import org.junit.experimental.theories.ParameterSignature;
1114
import org.junit.experimental.theories.PotentialAssignment;
15+
import org.junit.experimental.theories.Theory;
1216
import org.junit.experimental.theories.internal.AllMembersSupplier;
1317
import org.junit.runners.model.TestClass;
1418

1519
public class AllMembersSupplierTest {
16-
public static class HasDataPoints {
20+
21+
public static class HasDataPointsArrayField {
1722
@DataPoints
18-
public static Object[] objects = {1, 2};
23+
public static String[] list = new String[] { "qwe", "asd" };
1924

20-
public HasDataPoints(Object obj) {
25+
@Theory
26+
public void theory(String param) {
27+
}
28+
}
29+
30+
@Test
31+
public void dataPointsArrayShouldBeRecognized() throws Exception {
32+
List<PotentialAssignment> assignments = potentialAssignments(
33+
HasDataPointsArrayField.class.getMethod("theory", String.class));
34+
35+
assertEquals(2, assignments.size());
36+
}
37+
38+
public static class HasDataPointsArrayWithMatchingButInaccurateTypes {
39+
@DataPoints
40+
public static Object[] objects = {1, "string!", 2};
41+
42+
@Theory
43+
public void theory(Integer param) {
2144
}
2245
}
2346

2447
@Test
25-
public void dataPointsAnnotationMeansTreatAsArrayOnly()
26-
throws SecurityException, NoSuchMethodException {
27-
List<PotentialAssignment> valueSources = new AllMembersSupplier(
28-
new TestClass(HasDataPoints.class))
29-
.getValueSources(ParameterSignature.signatures(
30-
HasDataPoints.class.getConstructor(Object.class))
31-
.get(0));
32-
assertThat(valueSources.size(), is(2));
48+
public void dataPointsArrayShouldBeRecognizedOnValueTypeNotFieldType() throws Exception {
49+
List<PotentialAssignment> assignments = potentialAssignments(
50+
HasDataPointsArrayWithMatchingButInaccurateTypes.class.getMethod("theory", Integer.class));
51+
52+
assertEquals(2, assignments.size());
53+
}
54+
55+
public static class HasDataPointsWithObjectParameter {
56+
@DataPoints
57+
public static Object[] objectField = {1, 2};
58+
59+
@Theory
60+
public void theory(Object obj) {
61+
}
62+
}
63+
64+
@Test
65+
public void dataPointsAnnotationMeansTreatAsArrayOnly() throws Exception {
66+
List<PotentialAssignment> assignments = potentialAssignments(
67+
HasDataPointsWithObjectParameter.class.getMethod("theory", Object.class));
68+
69+
assertEquals(2, assignments.size());
70+
for (PotentialAssignment assignment : assignments) {
71+
assertNotEquals(HasDataPointsWithObjectParameter.objectField, assignment.getValue());
72+
}
3373
}
3474

3575
public static class HasDataPointsFieldWithNullValue {

0 commit comments

Comments
 (0)