Skip to content

Commit

Permalink
Merge c8654f8 into 6ca5c65
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz committed Oct 12, 2018
2 parents 6ca5c65 + c8654f8 commit f2c9f13
Show file tree
Hide file tree
Showing 15 changed files with 50 additions and 43 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -39,7 +39,7 @@
},
"dependencies": {
"lorem-ipsum": "~1.0.6",
"pure-rand": "^1.4.2"
"pure-rand": "^1.5.0"
},
"devDependencies": {
"@types/lorem-ipsum": "^1.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/check/runner/configuration/Parameters.ts
Expand Up @@ -12,10 +12,10 @@ export interface Parameters<T = void> {
*/
seed?: number;
/**
* Random number generator: `mersenne` by default
* Random number generator: `xorshift128plus` by default
*
* Random generator is the core element behind the generation of random values - changing it might directly impact the quality and performances of the generation of random values.
* It can be one of: 'mersenne', 'congruential', 'congruential32'
* It can be one of: 'mersenne', 'congruential', 'congruential32', 'xorshift128plus'
* Or any function able to build a `RandomGenerator` based on a seed
*/
randomType?: RandomType | ((seed: number) => RandomGenerator);
Expand Down
4 changes: 3 additions & 1 deletion src/check/runner/configuration/QualifiedParameters.ts
Expand Up @@ -22,7 +22,7 @@ export class QualifiedParameters<T> {

private static readSeed = <T>(p?: Parameters<T>): number => (p != null && p.seed != null ? p.seed : Date.now());
private static readRandomType = <T>(p?: Parameters<T>): ((seed: number) => RandomGenerator) => {
if (p == null || p.randomType == null) return prand.mersenne;
if (p == null || p.randomType == null) return prand.xorshift128plus;
if (typeof p.randomType === 'string') {
switch (p.randomType) {
case 'mersenne':
Expand All @@ -31,6 +31,8 @@ export class QualifiedParameters<T> {
return prand.congruential;
case 'congruential32':
return prand.congruential32;
case 'xorshift128plus':
return prand.xorshift128plus;
default:
throw new Error(`Invalid random specified: '${p.randomType}'`);
}
Expand Down
2 changes: 1 addition & 1 deletion src/check/runner/configuration/RandomType.ts
@@ -1,4 +1,4 @@
/**
* Random generator type
*/
export type RandomType = 'mersenne' | 'congruential' | 'congruential32';
export type RandomType = 'mersenne' | 'congruential' | 'congruential32' | 'xorshift128plus';
2 changes: 1 addition & 1 deletion test/e2e/GenerateAllValues.spec.ts
Expand Up @@ -9,7 +9,7 @@ describe(`Generate all values (seed: ${seed})`, () => {
* of their type / range
*/
const lookForMissing = <T>(arb: fc.Arbitrary<T>, missing: number): void => {
const mrng = new fc.Random(prand.mersenne(seed));
const mrng = new fc.Random(prand.xorshift128plus(seed));
const alreadySeen: any = {};
while (missing > 0) {
const g = arb.generate(mrng).value.toString();
Expand Down
8 changes: 4 additions & 4 deletions test/unit/check/arbitrary/LoremArbitrary.spec.ts
Expand Up @@ -10,8 +10,8 @@ describe('LoremArbitrary', () => {
it('Should generate the same text with the same random', () =>
fc.assert(
fc.property(fc.integer(), seed => {
const mrng1 = new Random(prand.mersenne(seed));
const mrng2 = new Random(prand.mersenne(seed));
const mrng1 = new Random(prand.xorshift128plus(seed));
const mrng2 = new Random(prand.xorshift128plus(seed));
const g1 = lorem().generate(mrng1).value;
const g2 = lorem().generate(mrng2).value;
assert.equal(g1, g2);
Expand All @@ -21,15 +21,15 @@ describe('LoremArbitrary', () => {
it('Should generate words by default', () =>
fc.assert(
fc.property(fc.integer(), fc.integer(0, 100), (seed, num) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const g = lorem(num).generate(mrng).value;
return g.indexOf('.') === -1;
})
));
it('Should generate sentences when asked too', () =>
fc.assert(
fc.property(fc.integer(), seed => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const g = lorem(5, true).generate(mrng).value;
return g.indexOf('.') !== -1;
})
Expand Down
2 changes: 1 addition & 1 deletion test/unit/check/arbitrary/OptionArbitrary.spec.ts
Expand Up @@ -13,7 +13,7 @@ describe('OptionArbitrary', () => {
fc.assert(
fc.property(fc.integer(), seed => {
const MAX_GUESSES = 1000;
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const arb = option(stubArb.forward());
for (let idx = 0; idx != MAX_GUESSES; ++idx) {
if (arb.generate(mrng).value == null) {
Expand Down
4 changes: 2 additions & 2 deletions test/unit/check/arbitrary/RecordArbitrary.spec.ts
Expand Up @@ -15,7 +15,7 @@ describe('RecordArbitrary', () => {
it('Should produce a record with missing keys', () =>
fc.assert(
fc.property(fc.set(fc.string(), 1, 10), fc.nat(), fc.integer(), (keys, missingIdx, seed) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const recordModel: { [key: string]: Arbitrary<string> } = {};
for (const k of keys) recordModel[k] = constant(`_${k}_`);

Expand All @@ -30,7 +30,7 @@ describe('RecordArbitrary', () => {
it('Should produce a record with present keys', () =>
fc.assert(
fc.property(fc.set(fc.string(), 1, 10), fc.nat(), fc.integer(), (keys, missingIdx, seed) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const recordModel: { [key: string]: Arbitrary<string> } = {};
for (const k of keys) recordModel[k] = constant(`_${k}_`);

Expand Down
Expand Up @@ -66,7 +66,7 @@ describe('ArbitraryWithShrink', () => {
it('Should produce the same shrunk values as the generated shrinkable', () => {
fc.assert(
fc.property(fc.integer().noShrink(), fc.nat(), (seed, mod) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const generated = smallIntWithShrink.generate(mrng);
const fromValue = smallIntWithShrink.shrinkableFor(generated.value);

Expand Down
14 changes: 7 additions & 7 deletions test/unit/check/arbitrary/generic/GenericArbitraryHelper.ts
Expand Up @@ -15,8 +15,8 @@ const testSameSeedSameValues = function<U, T>(
fc.assert(
fc.property(argsForArbGenerator, fc.integer().noShrink(), (params, seed) => {
const arb = arbGenerator(params);
const v1 = arb.generate(new Random(prand.mersenne(seed))).value;
const v2 = arb.generate(new Random(prand.mersenne(seed))).value;
const v1 = arb.generate(new Random(prand.xorshift128plus(seed))).value;
const v2 = arb.generate(new Random(prand.xorshift128plus(seed))).value;
assertEquality(v1, v2);
})
));
Expand All @@ -35,8 +35,8 @@ const testSameSeedSameShrinks = function<U, T>(
fc.set(fc.nat(100), 1, 10),
(params, seed, shrinkPath) => {
const arb = arbGenerator(params);
let s1: Shrinkable<T> | null = arb.generate(new Random(prand.mersenne(seed)));
let s2: Shrinkable<T> | null = arb.generate(new Random(prand.mersenne(seed)));
let s1: Shrinkable<T> | null = arb.generate(new Random(prand.xorshift128plus(seed)));
let s2: Shrinkable<T> | null = arb.generate(new Random(prand.xorshift128plus(seed)));
let id = 0;
while (s1 !== null && s2 !== null) {
assertEquality(s1.value, s2.value);
Expand All @@ -63,7 +63,7 @@ const testShrinkPathStrictlyDecreasing = function<U, T>(
fc.set(fc.nat(100), 1, 10),
(params, seed, shrinkPath) => {
const arb = arbGenerator(params);
let shrinkable: Shrinkable<T> | null = arb.generate(new Random(prand.mersenne(seed)));
let shrinkable: Shrinkable<T> | null = arb.generate(new Random(prand.xorshift128plus(seed)));
let prevValue = shrinkable!.value;
let id = 0;
while (shrinkable !== null) {
Expand Down Expand Up @@ -91,7 +91,7 @@ const testAlwaysGenerateCorrectValues = function<U, T>(
fc.assert(
fc.property(argsForArbGenerator, fc.integer().noShrink(), (params, seed) => {
const arb = arbGenerator(params);
const shrinkable = arb.generate(new Random(prand.mersenne(seed)));
const shrinkable = arb.generate(new Random(prand.xorshift128plus(seed)));
assert.ok(
isValidValue(shrinkable.value, params),
`Expect ${JSON.stringify(shrinkable.value)} to be a correct value (built with parameters: ${JSON.stringify(
Expand All @@ -115,7 +115,7 @@ const testAlwaysShrinkToCorrectValues = function<U, T>(
fc.set(fc.nat(100), 1, 10),
(params, seed, shrinkPath) => {
const arb = arbGenerator(params);
let shrinkable: Shrinkable<T> | null = arb.generate(new Random(prand.mersenne(seed)));
let shrinkable: Shrinkable<T> | null = arb.generate(new Random(prand.xorshift128plus(seed)));
let id = 0;
while (shrinkable !== null) {
assert.ok(
Expand Down
6 changes: 3 additions & 3 deletions test/unit/check/model/commands/CommandsArbitrary.spec.ts
Expand Up @@ -60,7 +60,7 @@ describe('CommandWrapper', () => {
it('Should skip skipped commands on shrink', () =>
fc.assert(
fc.property(fc.integer(), (seed: number) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
let logOnCheck: { data: string[] } = { data: [] };

const baseCommands = commands([
Expand All @@ -82,7 +82,7 @@ describe('CommandWrapper', () => {
/*it('Should shrink with failure at the end', () =>
fc.assert(
fc.property(fc.integer(), (seed: number) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
let logOnCheck: { data: string[] } = { data: [] };
const baseCommands = commands([
Expand Down Expand Up @@ -110,7 +110,7 @@ describe('CommandWrapper', () => {
it('Should shrink with at most one failure and all successes', () =>
fc.assert(
fc.property(fc.integer(), (seed: number) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
let logOnCheck: { data: string[] } = { data: [] };

const baseCommands = commands([
Expand Down
14 changes: 7 additions & 7 deletions test/unit/check/runner/Tosser.spec.ts
Expand Up @@ -23,7 +23,7 @@ describe('Tosser', () => {
it('Should offset the random number generator between calls', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(100), (seed, start) => {
const s = stream(toss(wrap(stubArb.forwardArray(4)), seed, prand.mersenne, []));
const s = stream(toss(wrap(stubArb.forwardArray(4)), seed, prand.xorshift128plus, []));
const [g1, g2] = [
...s
.drop(start)
Expand All @@ -39,12 +39,12 @@ describe('Tosser', () => {
fc.property(fc.integer(), fc.nat(20), (seed, num) => {
assert.deepStrictEqual(
[
...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, []))
...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, []))
.take(num)
.map(f => f().value)
],
[
...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, []))
...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, []))
.take(num)
.map(f => f().value)
]
Expand All @@ -54,8 +54,8 @@ describe('Tosser', () => {
it('Should not depend on the order of iteration', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(20), (seed, num) => {
const onGoingItems1 = [...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, [])).take(num)];
const onGoingItems2 = [...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, [])).take(num)];
const onGoingItems1 = [...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, [])).take(num)];
const onGoingItems2 = [...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, [])).take(num)];
assert.deepStrictEqual(
onGoingItems2
.reverse()
Expand All @@ -69,10 +69,10 @@ describe('Tosser', () => {
fc.assert(
fc.property(fc.integer(), fc.nat(20), fc.array(fc.integer()), (seed, num, examples) => {
const noExamplesProvided = [
...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, [])).take(num - examples.length)
...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, [])).take(num - examples.length)
].map(f => f().value);
const examplesProvided = [
...stream(toss(wrap(stubArb.forward()), seed, prand.mersenne, examples)).take(num)
...stream(toss(wrap(stubArb.forward()), seed, prand.xorshift128plus, examples)).take(num)
].map(f => f().value);
assert.deepStrictEqual([...examples, ...noExamplesProvided].slice(0, num), examplesProvided);
})
Expand Down
Expand Up @@ -17,7 +17,7 @@ const extractExceptSeed = <T>(conf: QualifiedParameters<T>) => {
const parametersArbitrary = fc.record(
{
seed: fc.integer(),
randomType: fc.constantFrom(prand.mersenne, prand.congruential, prand.congruential32),
randomType: fc.constantFrom(prand.mersenne, prand.congruential, prand.congruential32, prand.xorshift128plus),
numRuns: fc.nat(),
timeout: fc.nat(),
path: fc.array(fc.nat()).map(arr => arr.join(':')),
Expand All @@ -28,7 +28,12 @@ const parametersArbitrary = fc.record(
{ withDeletedKeys: true }
);

const hardCodedRandomType = fc.constantFrom('mersenne', 'congruential', 'congruential32') as fc.Arbitrary<RandomType>;
const hardCodedRandomType = fc.constantFrom(
'mersenne',
'congruential',
'congruential32',
'xorshift128plus'
) as fc.Arbitrary<RandomType>;

describe('QualifiedParameters', () => {
describe('read', () => {
Expand Down
12 changes: 6 additions & 6 deletions test/unit/random/generator/Random.spec.ts
Expand Up @@ -10,7 +10,7 @@ describe('Random', () => {
it('Should produce values within 0 and 2 ** n - 1', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(31), fc.nat(MAX_SIZE), (seed, n, num) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
for (let idx = 0; idx != num; ++idx) {
const v = mrng.next(n);
if (v < 0 || v > (((1 << n) - 1) | 0)) return false;
Expand All @@ -23,7 +23,7 @@ describe('Random', () => {
it('Should produce values within the range', () =>
fc.assert(
fc.property(fc.integer(), fc.integer(), fc.integer(), fc.nat(MAX_SIZE), (seed, a, b, num) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
const min = a < b ? a : b;
const max = a < b ? b : a;
for (let idx = 0; idx != num; ++idx) {
Expand All @@ -36,8 +36,8 @@ describe('Random', () => {
it('Should produce the same sequences given same seeds', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(MAX_SIZE), (seed, num) => {
const mrng1 = new Random(prand.mersenne(seed));
const mrng2 = new Random(prand.mersenne(seed));
const mrng1 = new Random(prand.xorshift128plus(seed));
const mrng2 = new Random(prand.xorshift128plus(seed));
for (let idx = 0; idx != num; ++idx) if (mrng1.nextInt() != mrng2.nextInt()) return false;
return true;
})
Expand All @@ -47,7 +47,7 @@ describe('Random', () => {
it('Should produce values within 0 and 1', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(MAX_SIZE), (seed, num) => {
const mrng = new Random(prand.mersenne(seed));
const mrng = new Random(prand.xorshift128plus(seed));
for (let idx = 0; idx != num; ++idx) {
const v = mrng.nextDouble();
if (v < 0 || v >= 1) return false;
Expand All @@ -60,7 +60,7 @@ describe('Random', () => {
it('Should produce the same sequences', () =>
fc.assert(
fc.property(fc.integer(), fc.nat(MAX_SIZE), (seed, num) => {
const mrng1 = new Random(prand.mersenne(seed));
const mrng1 = new Random(prand.xorshift128plus(seed));
const mrng2 = mrng1.clone();
for (let idx = 0; idx != num; ++idx) if (mrng1.nextInt() != mrng2.nextInt()) return false;
return true;
Expand Down

0 comments on commit f2c9f13

Please sign in to comment.