summaryrefslogtreecommitdiff
path: root/pbt/ts/src/property.ts
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2025-01-25 18:31:41 +0100
committerArnaud Bailly <arnaud.bailly@iohk.io>2025-01-25 18:31:41 +0100
commit8bcaac40ee1afb8c36f98beabe0348ae3713d44d (patch)
tree0b4b6f1f399fcf21462dec3ae2bbf95a1b6f69c3 /pbt/ts/src/property.ts
parenta98aaf0232a159d403a7e2bc946c51c1fa490481 (diff)
downloadlambda-nantes-8bcaac40ee1afb8c36f98beabe0348ae3713d44d.tar.gz
Generate a random list
Diffstat (limited to 'pbt/ts/src/property.ts')
-rw-r--r--pbt/ts/src/property.ts53
1 files changed, 53 insertions, 0 deletions
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
new file mode 100644
index 0000000..e8d3a21
--- /dev/null
+++ b/pbt/ts/src/property.ts
@@ -0,0 +1,53 @@
+import Prando from "prando";
+
+type Result = 'OK' | 'Falsified' | 'Exception';
+
+type ShrinkResult<A> = { counterexample: A, shrinks: number };
+
+type TestResult<A> = {
+ result: Result,
+ counterexample: ShrinkResult<A> | null
+};
+
+type Predicate<A> = (a: A) => boolean;
+
+export type Gen<A> = (rng: Prando) => ((size: number) => A);
+
+type Shrinker<A> = (a: A) => [A];
+
+const MAX_SUCCESS = 100;
+
+function findMinimalCounterExample<A>(x: A,
+ predicate: Predicate<A>,
+ shrinker: Shrinker<A>,
+ depth: number = 0): ShrinkResult<A> {
+ let xs = shrinker(x);
+ let counterexample = x;
+ let shrinks = depth;
+ for (let y of xs) {
+ if (!predicate(y)) {
+ let shrink = findMinimalCounterExample(y, predicate, shrinker, depth + 1);
+ if (shrink.shrinks > depth) {
+ counterexample = shrink.counterexample;
+ shrinks = shrink.shrinks;
+ }
+ }
+ }
+ return { counterexample, shrinks };
+}
+
+export function property<A>(rng: Prando,
+ size: number,
+ predicate: Predicate<A>,
+ generator: Gen<A>,
+ shrinker: Shrinker<A>): TestResult<A> {
+ let gen = generator(rng);
+ for (let i = 0; i < MAX_SUCCESS; i++) {
+ let x = gen(size);
+ if (!predicate(x)) {
+ let counterexample = findMinimalCounterExample(x, predicate, shrinker);
+ return { result: 'Falsified', counterexample };
+ }
+ }
+ return { result: 'OK', counterexample: null };
+}