Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

more extractors; using ServiceLoader to find others.

  • Loading branch information...
commit 13d8db710c13e65edaaed4754bfad7056b82a0f1 1 parent d021dd2
@pholser pholser authored committed
Showing with 218 additions and 111 deletions.
  1. +5 −0 pom.xml
  2. +10 −0 src/META-INF/services/com.pholser.junit.parameters.extractors.RandomValueExtractor
  3. +0 −13 src/main/java/com/pholser/junit/parameters/ExtractedBy.java
  4. +19 −68 src/main/java/com/pholser/junit/parameters/GeneratingParameterSupplier.java
  5. +0 −5 src/main/java/com/pholser/junit/parameters/RandomValueExtractor.java
  6. +7 −0 src/main/java/com/pholser/junit/parameters/extractors/RandomValueExtractor.java
  7. +7 −0 src/main/java/com/pholser/junit/parameters/extractors/RandomValueExtractorSource.java
  8. +32 −0 src/main/java/com/pholser/junit/parameters/extractors/ServiceLoaderExtractorSource.java
  9. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/BooleanExtractor.java
  10. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/ByteExtractor.java
  11. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/CharacterExtractor.java
  12. +13 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/DateExtractor.java
  13. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/DoubleExtractor.java
  14. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/FloatExtractor.java
  15. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/IntegerExtractor.java
  16. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/LongExtractor.java
  17. +11 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/ShortExtractor.java
  18. +17 −0 src/main/java/com/pholser/junit/parameters/internal/extractors/StringExtractor.java
  19. +2 −2 src/main/java/com/pholser/junit/parameters/{ → random}/AbstractJDKSourceOfRandomness.java
  20. +1 −1  src/main/java/com/pholser/junit/parameters/{ → random}/JDKSourceOfRandomness.java
  21. +1 −1  src/main/java/com/pholser/junit/parameters/{ → random}/SecureJDKSourceOfRandomness.java
  22. +1 −1  src/main/java/com/pholser/junit/parameters/{ → random}/SourceOfRandomness.java
  23. +15 −20 src/test/java/com/pholser/junit/parameters/MarkingTheoryParametersAsForAllTest.java
View
5 pom.xml
@@ -30,6 +30,11 @@
<dependencies>
<dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
View
10 src/META-INF/services/com.pholser.junit.parameters.extractors.RandomValueExtractor
@@ -0,0 +1,10 @@
+com.pholser.junit.parameters.internal.extractors.BooleanExtractor
+com.pholser.junit.parameters.internal.extractors.ByteExtractor
+com.pholser.junit.parameters.internal.extractors.CharacterExtractor
+com.pholser.junit.parameters.internal.extractors.DateExtractor
+com.pholser.junit.parameters.internal.extractors.DoubleExtractor
+com.pholser.junit.parameters.internal.extractors.FloatExtractor
+com.pholser.junit.parameters.internal.extractors.IntegerExtractor
+com.pholser.junit.parameters.internal.extractors.LongExtractor
+com.pholser.junit.parameters.internal.extractors.ShortExtractor
+com.pholser.junit.parameters.internal.extractors.StringExtractor
View
13 src/main/java/com/pholser/junit/parameters/ExtractedBy.java
@@ -1,13 +0,0 @@
-package com.pholser.junit.parameters;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Target(PARAMETER)
-@Retention(RUNTIME)
-public @interface ExtractedBy {
- Class<? extends RandomValueExtractor> value();
-}
View
87 src/main/java/com/pholser/junit/parameters/GeneratingParameterSupplier.java
@@ -1,73 +1,38 @@
package com.pholser.junit.parameters;
-import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import com.pholser.junit.parameters.extractors.RandomValueExtractorSource;
+
+import com.pholser.junit.parameters.extractors.ServiceLoaderExtractorSource;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SecureJDKSourceOfRandomness;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.PotentialAssignment;
-public class GeneratingParameterSupplier extends ParameterSupplier {
- private static final Map<Class<?>, RandomValueExtractor> extractors =
- new HashMap<Class<?>, RandomValueExtractor>();
-
- static {
- extractors.put(int.class, new RandomValueExtractor() {
- @Override
- public Object randomValue(SourceOfRandomness random) {
- return random.nextInt();
- }
- });
- extractors.put(Integer.class, extractors.get(int.class));
- extractors.put(double.class, new RandomValueExtractor() {
- @Override
- public Object randomValue(SourceOfRandomness random) {
- return random.nextDouble();
- }
- });
- extractors.put(Double.class, extractors.get(double.class));
- extractors.put(float.class, new RandomValueExtractor() {
- @Override
- public Object randomValue(SourceOfRandomness random) {
- return random.nextFloat();
- }
- });
- extractors.put(Float.class, extractors.get(float.class));
- extractors.put(boolean.class, new RandomValueExtractor() {
- @Override
- public Object randomValue(SourceOfRandomness random) {
- return random.nextBoolean();
- }
- });
- extractors.put(Boolean.class, extractors.get(boolean.class));
- extractors.put(String.class, new RandomValueExtractor() {
- @Override
- public Object randomValue(SourceOfRandomness random) {
- try {
- return new String(random.nextBytes(16), "US-ASCII");
- } catch (UnsupportedEncodingException ex) {
- throw new AssertionError(ex);
- }
- }
- });
- }
+import static org.apache.commons.lang.ClassUtils.*;
+public class GeneratingParameterSupplier extends ParameterSupplier {
private final SourceOfRandomness random;
+ private final Map<Class<?>, RandomValueExtractor<?>> extractors;
public GeneratingParameterSupplier() {
- this(new SecureJDKSourceOfRandomness());
+ this(new SecureJDKSourceOfRandomness(), new ServiceLoaderExtractorSource());
}
- public GeneratingParameterSupplier(SourceOfRandomness random) {
+ public GeneratingParameterSupplier(SourceOfRandomness random, RandomValueExtractorSource extractorSource) {
this.random = random;
+ extractors = extractorSource.extractors();
}
@Override
public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
- RandomValueExtractor extractor = extractor(sig);
+ RandomValueExtractor<?> extractor = extractor(sig);
int sampleSize = sampleSizeFor(sig);
List<PotentialAssignment> potentials = new ArrayList<PotentialAssignment>();
@@ -79,27 +44,13 @@ public GeneratingParameterSupplier(SourceOfRandomness random) {
}
private static int sampleSizeFor(ParameterSignature sig) {
- Class<?> type = sig.getType();
- if (boolean.class.equals(type) || Boolean.class.equals(type))
- return 2;
return sig.getAnnotation(ForAll.class).sampleSize();
}
- private RandomValueExtractor extractor(ParameterSignature sig) {
- ExtractedBy extractedBy = sig.getAnnotation(ExtractedBy.class);
-
- if (extractedBy != null)
- return instantiate(extractedBy.value());
- return extractors.get(sig.getType());
- }
-
- private RandomValueExtractor instantiate(Class<? extends RandomValueExtractor> type) {
- try {
- return type.newInstance();
- } catch (InstantiationException ex) {
- throw new IllegalStateException(ex);
- } catch (IllegalAccessException ex) {
- throw new IllegalStateException(ex);
- }
+ private RandomValueExtractor<?> extractor(ParameterSignature sig) {
+ Class<?> key = primitiveToWrapper(sig.getType());
+ if (!extractors.containsKey(key))
+ throw new IllegalStateException("Don't know how to generate values of " + sig.getType());
+ return extractors.get(key);
}
}
View
5 src/main/java/com/pholser/junit/parameters/RandomValueExtractor.java
@@ -1,5 +0,0 @@
-package com.pholser.junit.parameters;
-
-interface RandomValueExtractor {
- Object randomValue(SourceOfRandomness random);
-}
View
7 src/main/java/com/pholser/junit/parameters/extractors/RandomValueExtractor.java
@@ -0,0 +1,7 @@
+package com.pholser.junit.parameters.extractors;
+
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public interface RandomValueExtractor<T> {
+ T randomValue(SourceOfRandomness random);
+}
View
7 src/main/java/com/pholser/junit/parameters/extractors/RandomValueExtractorSource.java
@@ -0,0 +1,7 @@
+package com.pholser.junit.parameters.extractors;
+
+import java.util.Map;
+
+public interface RandomValueExtractorSource {
+ Map<Class<?>, RandomValueExtractor<?>> extractors();
+}
View
32 src/main/java/com/pholser/junit/parameters/extractors/ServiceLoaderExtractorSource.java
@@ -0,0 +1,32 @@
+package com.pholser.junit.parameters.extractors;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+public class ServiceLoaderExtractorSource implements RandomValueExtractorSource {
+ @Override
+ public Map<Class<?>, RandomValueExtractor<?>> extractors() {
+ Map<Class<?>, RandomValueExtractor<?>> extractors = new HashMap<Class<?>, RandomValueExtractor<?>>();
+ for (RandomValueExtractor<?> each : ServiceLoader.load(RandomValueExtractor.class))
+ addExtractor(extractors, each);
+ return extractors;
+ }
+
+ private void addExtractor(Map<Class<?>, RandomValueExtractor<?>> extractors,
+ RandomValueExtractor<?> newExtractor) {
+
+ for (Type each : newExtractor.getClass().getGenericInterfaces()) {
+ if (each instanceof ParameterizedType) {
+ ParameterizedType parameterized = (ParameterizedType) each;
+ if (RandomValueExtractor.class.equals(parameterized.getRawType())) {
+ Type typeArgument = parameterized.getActualTypeArguments()[0];
+ if (typeArgument instanceof Class<?>)
+ extractors.put((Class<?>) typeArgument, newExtractor);
+ }
+ }
+ }
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/BooleanExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class BooleanExtractor implements RandomValueExtractor<Boolean> {
+ @Override
+ public Boolean randomValue(SourceOfRandomness random) {
+ return random.nextBoolean();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/ByteExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class ByteExtractor implements RandomValueExtractor<Byte> {
+ @Override
+ public Byte randomValue(SourceOfRandomness random) {
+ return (byte) random.nextInt();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/CharacterExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class CharacterExtractor implements RandomValueExtractor<Character> {
+ @Override
+ public Character randomValue(SourceOfRandomness random) {
+ return (char) random.nextInt();
+ }
+}
View
13 src/main/java/com/pholser/junit/parameters/internal/extractors/DateExtractor.java
@@ -0,0 +1,13 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import java.util.Date;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class DateExtractor implements RandomValueExtractor<Date> {
+ @Override
+ public Date randomValue(SourceOfRandomness random) {
+ return new Date(random.nextLong());
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/DoubleExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class DoubleExtractor implements RandomValueExtractor<Double> {
+ @Override
+ public Double randomValue(SourceOfRandomness random) {
+ return random.nextDouble();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/FloatExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class FloatExtractor implements RandomValueExtractor<Float> {
+ @Override
+ public Float randomValue(SourceOfRandomness random) {
+ return random.nextFloat();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/IntegerExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class IntegerExtractor implements RandomValueExtractor<Integer> {
+ @Override
+ public Integer randomValue(SourceOfRandomness random) {
+ return random.nextInt();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/LongExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class LongExtractor implements RandomValueExtractor<Long> {
+ @Override
+ public Long randomValue(SourceOfRandomness random) {
+ return random.nextLong();
+ }
+}
View
11 src/main/java/com/pholser/junit/parameters/internal/extractors/ShortExtractor.java
@@ -0,0 +1,11 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class ShortExtractor implements RandomValueExtractor<Short> {
+ @Override
+ public Short randomValue(SourceOfRandomness random) {
+ return (short) random.nextInt();
+ }
+}
View
17 src/main/java/com/pholser/junit/parameters/internal/extractors/StringExtractor.java
@@ -0,0 +1,17 @@
+package com.pholser.junit.parameters.internal.extractors;
+
+import java.io.UnsupportedEncodingException;
+
+import com.pholser.junit.parameters.extractors.RandomValueExtractor;
+import com.pholser.junit.parameters.random.SourceOfRandomness;
+
+public class StringExtractor implements RandomValueExtractor<String> {
+ @Override
+ public String randomValue(SourceOfRandomness random) {
+ try {
+ return new String(random.nextBytes(16), "US-ASCII");
+ } catch (UnsupportedEncodingException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+}
View
4 ...nit/parameters/AbstractJDKSourceOfRandomness.java → ...ameters/random/AbstractJDKSourceOfRandomness.java
@@ -1,8 +1,8 @@
-package com.pholser.junit.parameters;
+package com.pholser.junit.parameters.random;
import java.util.Random;
-public abstract class AbstractJDKSourceOfRandomness implements SourceOfRandomness {
+abstract class AbstractJDKSourceOfRandomness implements SourceOfRandomness {
private final Random random;
protected AbstractJDKSourceOfRandomness(Random random) {
View
2  ...olser/junit/parameters/JDKSourceOfRandomness.java → ...unit/parameters/random/JDKSourceOfRandomness.java
@@ -1,4 +1,4 @@
-package com.pholser.junit.parameters;
+package com.pholser.junit.parameters.random;
import java.util.Random;
View
2  ...junit/parameters/SecureJDKSourceOfRandomness.java → ...arameters/random/SecureJDKSourceOfRandomness.java
@@ -1,4 +1,4 @@
-package com.pholser.junit.parameters;
+package com.pholser.junit.parameters.random;
import java.security.SecureRandom;
View
2  .../pholser/junit/parameters/SourceOfRandomness.java → ...r/junit/parameters/random/SourceOfRandomness.java
@@ -1,4 +1,4 @@
-package com.pholser.junit.parameters;
+package com.pholser.junit.parameters.random;
public interface SourceOfRandomness {
boolean nextBoolean();
View
35 src/test/java/com/pholser/junit/parameters/MarkingTheoryParametersAsForAllTest.java
@@ -65,10 +65,11 @@ public void shouldHold(@ForAll float f) {
}
@Test
- public void shouldFeedExactlyTwoBooleansToAMarkedBooleanParameter() throws Exception {
+ public void shouldFeedDefaultNumberOfBooleansToAMarkedBooleanParameter() throws Exception {
JUnitCore.runClasses(ForDefaultNumberOfBooleans.class);
- assertEquals(2, ForDefaultNumberOfBooleans.iterations);
+ assertEquals(ForAll.class.getMethod("sampleSize").getDefaultValue(),
+ ForDefaultNumberOfBooleans.iterations);
}
@RunWith(Theories.class)
@@ -82,10 +83,11 @@ public void shouldHold(@ForAll boolean b) {
}
@Test
- public void shouldFeedExactlyTwoBooleansWrappersToAMarkedBooleanWrapperParameter() throws Exception {
+ public void shouldFeedDefaultNumberOfBooleansWrappersToAMarkedBooleanWrapperParameter() throws Exception {
JUnitCore.runClasses(ForDefaultNumberOfBooleanWrappers.class);
- assertEquals(2, ForDefaultNumberOfBooleans.iterations);
+ assertEquals(ForAll.class.getMethod("sampleSize").getDefaultValue(),
+ ForDefaultNumberOfBooleans.iterations);
}
@RunWith(Theories.class)
@@ -150,27 +152,20 @@ public void shouldHold(@ForAll(sampleSize = 3) int i, @ForAll(sampleSize = 5) in
}
@Test
- public void shouldAllowNonPrimitiveTypesToBeRandomlyGenerated() {
- JUnitCore.runClasses(NonPrimitiveParameter.class);
+ public void shouldFeedRandomDatesToAMarkedDateParameter() throws Exception {
+ JUnitCore.runClasses(ForDefaultNumberOfDates.class);
- assertEquals(100, RandomDateExtractor.numberOfCalls);
+ assertEquals(ForAll.class.getMethod("sampleSize").getDefaultValue(),
+ ForDefaultNumberOfDates.iterations);
}
@RunWith(Theories.class)
- public static class NonPrimitiveParameter {
- @Theory
- public void shouldHold(@ForAll @ExtractedBy(RandomDateExtractor.class) Date d) {
- assertNotNull(d);
- }
- }
-
- static class RandomDateExtractor implements RandomValueExtractor {
- static int numberOfCalls;
+ public static class ForDefaultNumberOfDates {
+ static int iterations;
- @Override
- public Object randomValue(SourceOfRandomness random) {
- ++numberOfCalls;
- return new Date(random.nextLong());
+ @Theory
+ public void shouldHold(@ForAll Date d) {
+ ++iterations;
}
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.