Skip to content

Commit

Permalink
WIP: use L128X1024Mix for random generator
Browse files Browse the repository at this point in the history
fixes #363
  • Loading branch information
Vladimir Sitnikov committed Dec 11, 2022
1 parent 7a37d8d commit c6a1f54
Show file tree
Hide file tree
Showing 154 changed files with 1,198 additions and 883 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ Use _jqwik_ itself for all tests and properties.

Use _AssertJ_ for non trivial assertions.

Use `@ForAll Random random` parameter if you need a random value.
Use `@ForAll JqwikRandom random` parameter if you need a random value.
2 changes: 2 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ signing {
dependencies {
api("org.opentest4j:opentest4j:${opentest4jVersion}")
api("org.junit.platform:junit-platform-commons:${junitPlatformVersion}")
api(platform("org.apache.commons:commons-rng-bom:1.5"))
api("org.apache.commons:commons-rng-client-api")
}
7 changes: 3 additions & 4 deletions api/src/main/java/net/jqwik/api/Arbitraries.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import javax.annotation.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import org.apiguardian.api.*;

Expand Down Expand Up @@ -112,7 +111,7 @@ public static <T> Arbitrary<T> fromGenerator(RandomGenerator<T> generator) {
* @param <T> The type of values to generate
* @return a new arbitrary instance
*/
public static <T> Arbitrary<T> randomValue(Function<Random, T> generator) {
public static <T> Arbitrary<T> randomValue(Function<JqwikRandom, T> generator) {
return fromGenerator(random -> Shrinkable.unshrinkable(generator.apply(random)));
}

Expand All @@ -121,8 +120,8 @@ public static <T> Arbitrary<T> randomValue(Function<Random, T> generator) {
*
* @return a new arbitrary instance
*/
public static Arbitrary<Random> randoms() {
return randomValue(random -> new Random(random.nextLong()));
public static Arbitrary<JqwikRandom> randoms() {
return randomValue(JqwikRandom::split);
}

/**
Expand Down
37 changes: 37 additions & 0 deletions api/src/main/java/net/jqwik/api/JqwikRandom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.jqwik.api;

import net.jqwik.api.random.*;

import org.apache.commons.rng.*;

import java.util.*;

public interface JqwikRandom extends UniformRandomProvider {
JqwikRandom jump();

default JqwikRandom split() {
return split(this);
}

JqwikRandom split(UniformRandomProvider source);

JqwikRandomState saveState();

void restoreState(JqwikRandomState state);

default Random asJdkRandom() {
return new Random() {
@Override
protected int next(int bits) {
int next = JqwikRandom.this.nextInt();
next &= ((1L << bits) - 1);
return next;
}

@Override
public long nextLong() {
return JqwikRandom.this.nextLong();
}
};
}
}
3 changes: 1 addition & 2 deletions api/src/main/java/net/jqwik/api/RandomDistribution.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.jqwik.api;

import java.math.*;
import java.util.*;

import org.apiguardian.api.*;

Expand Down Expand Up @@ -61,7 +60,7 @@ interface RandomNumericGenerator {
*
* @return an instance of BigInteger. Never {@code null}.
*/
BigInteger next(Random random);
BigInteger next(JqwikRandom random);
}

/**
Expand Down
14 changes: 8 additions & 6 deletions api/src/main/java/net/jqwik/api/RandomGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.function.*;
import java.util.stream.*;

import net.jqwik.api.random.*;

import org.apiguardian.api.*;

import static org.apiguardian.api.API.Status.*;
Expand All @@ -19,13 +21,13 @@ abstract class RandomGeneratorFacade {
implementation = FacadeLoader.load(RandomGeneratorFacade.class);
}

public abstract <T, U> Shrinkable<U> flatMap(Shrinkable<T> self, Function<T, RandomGenerator<U>> mapper, long nextLong);
public abstract <T, U> Shrinkable<U> flatMap(Shrinkable<T> self, Function<T, RandomGenerator<U>> mapper, JqwikRandomState nextLong);

public abstract <T, U> Shrinkable<U> flatMap(
Shrinkable<T> wrappedShrinkable,
Function<T, Arbitrary<U>> mapper,
int genSize,
long nextLong,
JqwikRandomState nextLong,
boolean withEmbeddedEdgeCases
);

Expand All @@ -44,7 +46,7 @@ public abstract <T, U> Shrinkable<U> flatMap(
* @param random the source of randomness. Injected by jqwik itself.
* @return the next generated value wrapped within the Shrinkable interface. The method must ALWAYS return a next value.
*/
Shrinkable<T> next(Random random);
Shrinkable<T> next(JqwikRandom random);

@API(status = INTERNAL)
default <U> RandomGenerator<U> map(Function<T, U> mapper) {
Expand All @@ -63,7 +65,7 @@ default <U> RandomGenerator<U> mapShrinkable(Function<Shrinkable<T>, Shrinkable<
default <U> RandomGenerator<U> flatMap(Function<T, RandomGenerator<U>> mapper) {
return random -> {
Shrinkable<T> wrappedShrinkable = RandomGenerator.this.next(random);
return RandomGeneratorFacade.implementation.flatMap(wrappedShrinkable, mapper, random.nextLong());
return RandomGeneratorFacade.implementation.flatMap(wrappedShrinkable, mapper, random.split().saveState());
};
}

Expand All @@ -72,7 +74,7 @@ default <U> RandomGenerator<U> flatMap(Function<T, Arbitrary<U>> mapper, int gen
return random -> {
Shrinkable<T> wrappedShrinkable = RandomGenerator.this.next(random);
return RandomGeneratorFacade.implementation
.flatMap(wrappedShrinkable, mapper, genSize, random.nextLong(), withEmbeddedEdgeCases);
.flatMap(wrappedShrinkable, mapper, genSize, random.split().saveState(), withEmbeddedEdgeCases);
};
}

Expand All @@ -87,7 +89,7 @@ default RandomGenerator<T> withEdgeCases(int genSize, EdgeCases<T> edgeCases) {
}

@API(status = INTERNAL)
default Stream<Shrinkable<T>> stream(Random random) {
default Stream<Shrinkable<T>> stream(JqwikRandom random) {
return Stream.generate(() -> this.next(random));
}

Expand Down
6 changes: 4 additions & 2 deletions api/src/main/java/net/jqwik/api/Shrinkable.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.function.*;
import java.util.stream.*;

import net.jqwik.api.random.*;

import org.apiguardian.api.*;

import static org.apiguardian.api.API.Status.*;
Expand All @@ -26,7 +28,7 @@ abstract class ShrinkableFacade {

public abstract <T> Shrinkable<T> filter(Shrinkable<T> self, Predicate<T> filter);

public abstract <T, U> Shrinkable<U> flatMap(Shrinkable<T> self, Function<T, Arbitrary<U>> flatMapper, int tries, long randomSeed);
public abstract <T, U> Shrinkable<U> flatMap(Shrinkable<T> self, Function<T, Arbitrary<U>> flatMapper, int tries, JqwikRandomState randomSeed);
}

static <T> Shrinkable<T> unshrinkable(@Nullable T value) {
Expand Down Expand Up @@ -106,7 +108,7 @@ default Shrinkable<T> filter(Predicate<T> filter) {
return ShrinkableFacade.implementation.filter(this, filter);
}

default <U> Shrinkable<U> flatMap(Function<T, Arbitrary<U>> flatMapper, int tries, long randomSeed) {
default <U> Shrinkable<U> flatMap(Function<T, Arbitrary<U>> flatMapper, int tries, JqwikRandomState randomSeed) {
return ShrinkableFacade.implementation.flatMap(this, flatMapper, tries, randomSeed);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package net.jqwik.api.facades;

import java.util.*;

import org.apiguardian.api.*;

import net.jqwik.api.*;
Expand All @@ -17,9 +15,9 @@ public abstract class ShrinkingSupportFacade {
implementation = FacadeLoader.load(ShrinkingSupportFacade.class);
}

public abstract <T> T falsifyThenShrink(Arbitrary<? extends T> arbitrary, Random random, Falsifier<T> falsifier);
public abstract <T> T falsifyThenShrink(Arbitrary<? extends T> arbitrary, JqwikRandom random, Falsifier<T> falsifier);

public abstract <T> T falsifyThenShrink(RandomGenerator<? extends T> arbitrary, Random random, Falsifier<T> falsifier);
public abstract <T> T falsifyThenShrink(RandomGenerator<? extends T> arbitrary, JqwikRandom random, Falsifier<T> falsifier);

public abstract <T> T shrink(
Shrinkable<T> falsifiedShrinkable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public abstract class TestingSupportFacade {
implementation = FacadeLoader.load(TestingSupportFacade.class);
}

public abstract <T> Shrinkable<T> generateUntil(RandomGenerator<T> generator, Random random, Function<T, Boolean> condition);
public abstract <T> Shrinkable<T> generateUntil(RandomGenerator<T> generator, JqwikRandom random, Function<T, Boolean> condition);

public abstract String singleLineReport(Object any);

Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/net/jqwik/api/random/JqwikRandomSeed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package net.jqwik.api.random;

public interface JqwikRandomSeed {
}
5 changes: 5 additions & 0 deletions api/src/main/java/net/jqwik/api/random/JqwikRandomState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.jqwik.api.random;

public interface JqwikRandomState {
Object getAlgorithm();
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ The starting point for generation usually is a static method call on class
return Arbitraries.randomValue(random -> generatePrime(random));
}

private Integer generatePrime(Random random) {
private Integer generatePrime(JqwikRandom random) {
int candidate;
do {
candidate = random.nextInt(10000) + 2;
Expand Down Expand Up @@ -309,7 +309,7 @@ Arbitraries.strings().ofMinLength(5).ofMaxLength(25)

#### java.util.Random

- [`Arbitrary<Random> randoms()`](/docs/${docsVersion}/javadoc/net/jqwik/api/Arbitraries.html#randoms()):
- [`Arbitrary<JqwikRandom> randoms()`](/docs/${docsVersion}/javadoc/net/jqwik/api/Arbitraries.html#randoms()):
Random instances will never be shrunk

#### Shuffling Permutations
Expand Down
4 changes: 2 additions & 2 deletions documentation/src/docs/include/lifecycle-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ and publish the result using a [`Reporter`](/docs/${docsVersion}/javadoc/net/jqw
```java
@Property(tries = 100)
@AddLifecycleHook(MeasureTime.class)
void measureTimeSpent(@ForAll Random random) throws InterruptedException {
void measureTimeSpent(@ForAll JqwikRandom random) throws InterruptedException {
Thread.sleep(random.nextInt(50));
}

Expand Down Expand Up @@ -228,7 +228,7 @@ The following example shows how to fail if a single try will take longer than 10
```java
@Property(tries = 10)
@AddLifecycleHook(FailIfTooSlow.class)
void sleepingProperty(@ForAll Random random) throws InterruptedException {
void sleepingProperty(@ForAll JqwikRandom random) throws InterruptedException {
Thread.sleep(random.nextInt(101));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void countingTries(@ForAll String aString) {

@Property(tries = 100)
@AddLifecycleHook(MeasureTime.class)
void measureTimeSpent(@ForAll Random random) throws InterruptedException {
void measureTimeSpent(@ForAll JqwikRandom random) throws InterruptedException {
Thread.sleep(random.nextInt(50));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class AroundTryHookExamples {

@Property(tries = 10)
@AddLifecycleHook(FailIfTooSlow.class)
void sleepingProperty(@ForAll Random random) throws InterruptedException {
void sleepingProperty(@ForAll JqwikRandom random) throws InterruptedException {
Thread.sleep(random.nextInt(101));
}

Expand Down
2 changes: 2 additions & 0 deletions engine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ dependencies {
api("org.opentest4j:opentest4j:${opentest4jVersion}")
api("org.junit.platform:junit-platform-commons:${junitPlatformVersion}")
implementation("org.junit.platform:junit-platform-engine:${junitPlatformVersion}")
implementation("org.apache.commons:commons-rng-core")
implementation("org.apache.commons:commons-rng-simple")

testImplementation(project(":testing"))

Expand Down

0 comments on commit c6a1f54

Please sign in to comment.