summaryrefslogtreecommitdiff
path: root/pbt/ts/src/gen.ts
diff options
context:
space:
mode:
Diffstat (limited to 'pbt/ts/src/gen.ts')
-rw-r--r--pbt/ts/src/gen.ts114
1 files changed, 95 insertions, 19 deletions
diff --git a/pbt/ts/src/gen.ts b/pbt/ts/src/gen.ts
index 7d8c6f1..587bca6 100644
--- a/pbt/ts/src/gen.ts
+++ b/pbt/ts/src/gen.ts
@@ -5,7 +5,20 @@ import Prando from 'prando';
// namely the sequence of generated values in order to be
// able to backtrack and shrink.
-type GenMode = 'gen' | 'shrink';
+export interface Generators {
+
+ genInt(): Gen<number>;
+
+ genIntWithin(min: number, max: number): Gen<number>;
+
+ genBytes(): GenBytes;
+
+ genString(): Gen<string>;
+
+ genList<A>(generator: Gen<A>): Gen<A[]>;
+
+ replay(): void;
+}
export interface Gen<A> {
generate(): A;
@@ -13,11 +26,12 @@ export interface Gen<A> {
generateN(n: number): A[];
}
-export interface GenBytes {
+interface GenBytes {
+ reject(): void;
generate(n: number): number[];
}
-export class BytesGen implements GenBytes {
+class BytesGen implements GenBytes {
prng: Prando;
bytes: number[][]; // the internal sequence of generated values
@@ -54,7 +68,7 @@ export class BytesGen implements GenBytes {
}
}
-export class ReplayBytes implements GenBytes {
+class ReplayBytes implements GenBytes {
bytes: number[][]; // the internal sequence of generated values
index: number = 0; // the current index in the sequence of generated values
@@ -77,13 +91,18 @@ export class ReplayBytes implements GenBytes {
return chunk;
}
+
+ reject() {
+ if (this.index >= this.bytes.length) {
+ throw new Error('No more bytes to shrink');
+ }
+ this.index++;
+ }
}
class GenInt implements Gen<number> {
- private bytes: BytesGen;
-
- constructor(seed: number | undefined = undefined) {
- this.bytes = new BytesGen(new Prando(seed ? seed : Math.random() * 1000));
+ constructor(private bytes: GenBytes) {
+ this.bytes = bytes;
}
generate(): number {
@@ -102,10 +121,8 @@ class GenInt implements Gen<number> {
}
class GenIntWithin implements Gen<number> {
- private bytes: BytesGen;
-
- constructor(private min: number, private max: number, seed: number | undefined = undefined) {
- this.bytes = new BytesGen(new Prando(seed ? seed : Math.random() * 1000000000));
+ constructor(private bytes: GenBytes, private min: number, private max: number) {
+ this.bytes = bytes;
this.min = min;
this.max = max;
}
@@ -148,10 +165,8 @@ class GenIntWithin implements Gen<number> {
}
class GenASCIIString implements Gen<string> {
- private bytes: BytesGen;
-
- constructor(seed: number | undefined = undefined) {
- this.bytes = new BytesGen(new Prando(seed ? seed : Math.random() * 1000));
+ constructor(private bytes: GenBytes) {
+ this.bytes = bytes
}
generate(): string {
@@ -169,8 +184,69 @@ class GenASCIIString implements Gen<string> {
}
}
-export const genInt = (seed: number | undefined = undefined) => new GenInt(seed);
+class Seeded implements Generators {
+
+ constructor(private bytes: BytesGen) {
+ this.bytes = bytes;
+ }
+
+ replay(): Generators {
+ return new Replayed(this.bytes);
+ }
+
+ genInt(): Gen<number> {
+ return new GenInt(this.bytes);
+ }
+ genIntWithin(min: number, max: number): Gen<number> {
+ return new GenIntWithin(this.bytes, min, max);
+ }
+ genBytes(): GenBytes {
+ return this.bytes;
+ }
+ genString(): Gen<string> {
+ return new GenASCIIString(this.bytes);
+ }
+ genList<A>(generator: Gen<A>): Gen<A[]> {
+ throw new Error('Method not implemented.');
+ }
+
+}
+
+class Replayed implements Generators {
+ bytes : GenBytes;
+
+ constructor (bytes: BytesGen) {
+ this.bytes = bytes.replay();
+ }
+
+ replay(): Generators {
+ throw new Error('Cannot replay a replayed generator');
+ }
+
+ genInt(): Gen<number> {
+ return new GenInt(this.bytes);
+ }
+ genIntWithin(min: number, max: number): Gen<number> {
+ return new GenIntWithin(this.bytes, min, max);
+ }
+ genBytes(): GenBytes {
+ return this.bytes;
+ }
+ genString(): Gen<string> {
+ return new GenASCIIString(this.bytes);
+ }
+ genList<A>(generator: Gen<A>): Gen<A[]> {
+ throw new Error('Method not implemented.');
+ }
+
+}
+
+
+const generators = (seed: number | undefined = undefined) => {
+ const prng = new Prando(seed ? seed : Math.random() * 10000000);
+ const bytes = new BytesGen(prng);
-export const genIntWithin = (min: number, max: number, seed: number | undefined = undefined) => new GenIntWithin(min, max, seed);
+ return new Seeded(bytes);
+};
-export const genASCIIString = (seed: number | undefined = undefined) => new GenASCIIString(seed);
+export default generators;