diff options
Diffstat (limited to 'pbt/ts/src/property.ts')
| -rw-r--r-- | pbt/ts/src/property.ts | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts index 7b3ee59..500c423 100644 --- a/pbt/ts/src/property.ts +++ b/pbt/ts/src/property.ts @@ -20,7 +20,7 @@ type Property<A> = (seed: number, size: number) => TestResult<A>; const MAX_SUCCESS = 100; -function findMinimalCounterExample<A>( +export function findMinimalCounterExample<A>( x: A, predicate: Predicate<A>, shrinker: Shrinker<A>, @@ -117,6 +117,7 @@ export function mapOf1<K, V>(genK: Gen<K>, genV: Gen<V>): Gen<Map<K, V>> { }; } +/// Select randomly one element from given list export function elements<A>(arr: A[]): Gen<A> { return (rng: Prando) => (_size: number) => { let index = rng.nextInt(0, arr.length - 1); @@ -124,6 +125,7 @@ export function elements<A>(arr: A[]): Gen<A> { }; } +/// Select one key-value pair from given map export function keyValueOf<K, V>(map: Map<K, V>): Gen<[K, V]> { let keys = Array.from(map.keys()); return (rng: Prando) => { @@ -136,12 +138,27 @@ export function keyValueOf<K, V>(map: Map<K, V>): Gen<[K, V]> { }; } +/// Choose number between some bounds. export function choose(min: number, max: number): Gen<number> { return (rng: Prando) => (size: number) => rng.nextInt(min, max); } -export let someInt: Gen<number> = (rng: Prando) => (size: number) => - rng.nextInt(-size, size); +/// Choose some random integer. +export let someInt: Gen<number> = (rng: Prando) => (size: number) => { + const bound = Math.pow(2, size); + return rng.nextInt(-bound, bound); +}; + +/// Choose some random positive integer. +export let positiveInt: Gen<number> = (rng: Prando) => (size: number) => { + const bound = Math.pow(2, Math.round(Math.sqrt(size))); + return rng.nextInt(0, bound); +}; + +/// Generate a pair of generated values +export function pairOf<A>(gen: Gen<A>): Gen<[A, A]> { + return (rng: Prando) => (size: number) => [gen(rng)(size), gen(rng)(size)]; +} // basic shrinkers export function shrinklist<A>(arr: A[]): A[][] { @@ -162,6 +179,28 @@ export function shrinklist<A>(arr: A[]): A[][] { return result; } +export function shrinkPositive(i: number): number[] { + if (i == 0) return []; + + return [i - 1, Math.round(Math.sqrt(i))]; +} + +// shrink pair +export function shrinkPair<A, B>( + shrinkA: Shrinker<A>, + shrinkB: Shrinker<B>, +): Shrinker<[A, B]> { + return ([x, y]) => { + const shrinkx = shrinkA(x); + const shrinky = shrinkB(y); + // assumes x >= y + const resulta: [A, B][] = shrinkx.map(e => [e, y]); + const resultb: [A, B][] = shrinky.map(e => [x, e]); + const resultboth: [A, B][] = shrinkx.map((e, i) => [e, shrinky[i]]); + return resulta.concat(resultb, resultboth); + }; +} + export const Property = { run<A>(prop: Property<A>): TestResult<A> { let seed = Math.floor(Math.random() * 1000000); |
