diff options
Diffstat (limited to 'src/main/java/au/id/zancanaro/javacheck/Generator.java')
| -rw-r--r-- | src/main/java/au/id/zancanaro/javacheck/Generator.java | 32 | 
1 files changed, 29 insertions, 3 deletions
| diff --git a/src/main/java/au/id/zancanaro/javacheck/Generator.java b/src/main/java/au/id/zancanaro/javacheck/Generator.java index 9d88020..103bc69 100644 --- a/src/main/java/au/id/zancanaro/javacheck/Generator.java +++ b/src/main/java/au/id/zancanaro/javacheck/Generator.java @@ -4,6 +4,7 @@ import java.util.Iterator;  import java.util.List;  import java.util.Random;  import java.util.function.Function; +import java.util.function.Predicate;  /**   * Generators are a way of producing random objects and their associated shrink @@ -63,13 +64,13 @@ public interface Generator<T> {       * @return A {@link Generator} returning a {@link List}       */      @SafeVarargs -    static <T> Generator<List<T>> tuple(Generator<T>... generators) { +    static <T> Generator<List<T>> tuple(Generator<? extends T>... generators) {          return (random, size) -> {              @SuppressWarnings("unchecked")              ShrinkTree<T>[] result = (ShrinkTree<T>[]) new ShrinkTree[generators.length];              int index = 0; -            for (Generator<T> generator : generators) { -                result[index++] = generator.generate(random, size); +            for (Generator<? extends T> generator : generators) { +                result[index++] = generator.generate(random, size).map(x -> (T) x);              }              return ShrinkTree.zip(Function.identity(), result);          }; @@ -130,6 +131,31 @@ public interface Generator<T> {          return (random, size) -> ShrinkTree.join(this.generate(random, size).map(action).map(g -> g.generate(random, size)));      } +    /** +     * Filter the results of this generator to only those matching a given +     * predicate. +     * +     * suchThat will keep trying the generator until either it provides a valid +     * value, or a stack overflow error occurs. +     * +     * <b>Only use this method with predicates which are very likely to +     * match.</b> +     * +     * @param predicate The predicate to match +     * @return A new generator resulting from filtering this generator to only +     * terms which match the given predicate +     */ +    default Generator<T> suchThat(Predicate<T> predicate) { +        return (random, size) -> { +            ShrinkTree<T> result = this.generate(random, size); +            if (predicate.test(result.getValue())) { +                return result.filter(predicate); +            } else { +                return this.suchThat(predicate).generate(random, size); +            } +        }; +    } +      default Iterator<T> sample(Random random, int maxSize) {          return new GeneratorSampleIterator<>(this, random, maxSize);      } | 
