summaryrefslogtreecommitdiff
path: root/pbt/ts/src
diff options
context:
space:
mode:
Diffstat (limited to 'pbt/ts/src')
-rw-r--r--pbt/ts/src/bank.test.ts18
-rw-r--r--pbt/ts/src/index.test.ts6
-rw-r--r--pbt/ts/src/index.ts14
-rw-r--r--pbt/ts/src/property.test.ts12
-rw-r--r--pbt/ts/src/property.ts24
5 files changed, 41 insertions, 33 deletions
diff --git a/pbt/ts/src/bank.test.ts b/pbt/ts/src/bank.test.ts
index d503faf..f6aa7b0 100644
--- a/pbt/ts/src/bank.test.ts
+++ b/pbt/ts/src/bank.test.ts
@@ -61,7 +61,7 @@ const genOperations = (accounts: Map<Account, number>) =>
const correctBalance =
(initialAccounts: Map<Account, number>) =>
- (ops: Operation[]): boolean => {
+ (ops: Operation[]): Promise<boolean> => {
const expectedBalances = new Map(initialAccounts);
const api = new SimpleBank(initialAccounts);
@@ -74,7 +74,7 @@ const correctBalance =
console.log(
`Balance mismatch for account ${op.account}: expected ${expected}, got ${retrieved}`,
);
- return false;
+ return Promise.resolve(false);
}
break;
}
@@ -100,34 +100,34 @@ const correctBalance =
console.log(
`Final balance mismatch for account ${account}: expected ${expectedBal}, got ${retrieved}`,
);
- return false;
+ return Promise.resolve(false);
}
}
- return true;
+ return Promise.resolve(true);
};
describe('Bank Simulator', () => {
- test('can retrieve balance given account exists', () => {
+ test('can retrieve balance given account exists', async () => {
const prop = forall(genAccounts, accounts => {
const api = new SimpleBank(accounts);
return property(keyValueOf(accounts), ([accountNr, bal]) => {
const retrieved = toNullable(api.balance(accountNr));
- return retrieved === bal;
+ return Promise.resolve(retrieved === bal);
});
});
- const result = Property.run(prop);
+ const result = await Property.run(prop);
expect(result.result).toBe('OK');
});
- test('correctly update balance given a sequence of deposits and withdrawals', () => {
+ test('correctly update balance given a sequence of deposits and withdrawals', async () => {
const prop = forall(genAccounts, accounts => {
return property(genOperations(accounts), correctBalance(accounts));
});
- const result = Property.run(prop);
+ const result = await Property.run(prop);
expect(result.result).toBe('OK');
});
diff --git a/pbt/ts/src/index.test.ts b/pbt/ts/src/index.test.ts
index b0d5cdc..b102fe3 100644
--- a/pbt/ts/src/index.test.ts
+++ b/pbt/ts/src/index.test.ts
@@ -2,8 +2,10 @@ import {prop_reverse_with_two_lists} from './index';
import {Property} from './property';
describe('testing lists reversal', () => {
- test('reverse of two appended lists is append of each list reversed', () => {
- const reverse_append_result = Property.run(prop_reverse_with_two_lists);
+ test('reverse of two appended lists is append of each list reversed', async () => {
+ const reverse_append_result = await Property.run(
+ prop_reverse_with_two_lists,
+ );
expect(reverse_append_result.result).toBe('OK');
});
});
diff --git a/pbt/ts/src/index.ts b/pbt/ts/src/index.ts
index 38049b2..2f59f0e 100644
--- a/pbt/ts/src/index.ts
+++ b/pbt/ts/src/index.ts
@@ -19,8 +19,8 @@ function reverse<A>(arr: A[]): A[] {
return result;
}
-function reverse_is_self_inverse(arr: number[]): boolean {
- return arrayEquals(reverse(reverse(arr)), arr);
+function reverse_is_self_inverse(arr: number[]): Promise<boolean> {
+ return Promise.resolve(arrayEquals(reverse(reverse(arr)), arr));
}
function gen2lists<A>(gen: Gen<A>): Gen<[A[], A[]]> {
@@ -32,10 +32,12 @@ function gen2lists<A>(gen: Gen<A>): Gen<[A[], A[]]> {
};
}
-function reverse_with_two_lists<A>(arrs: [A[], A[]]): boolean {
- return arrayEquals(
- reverse(arrs[0].concat(arrs[1])),
- reverse(arrs[1]).concat(reverse(arrs[0])),
+function reverse_with_two_lists<A>(arrs: [A[], A[]]): Promise<boolean> {
+ return Promise.resolve(
+ arrayEquals(
+ reverse(arrs[0].concat(arrs[1])),
+ reverse(arrs[1]).concat(reverse(arrs[0])),
+ ),
);
}
diff --git a/pbt/ts/src/property.test.ts b/pbt/ts/src/property.test.ts
index 920457a..addff34 100644
--- a/pbt/ts/src/property.test.ts
+++ b/pbt/ts/src/property.test.ts
@@ -7,18 +7,18 @@ import {
} from './property';
// from https://github.com/jlink/shrinking-challenge/blob/main/challenges/difference.md
-const predicate1: (pair: [number, number]) => boolean = ([x, y]) =>
- x < 10 || x !== y;
+const predicate1: (pair: [number, number]) => Promise<boolean> = ([x, y]) =>
+ Promise.resolve(x < 10 || x !== y);
describe('Find minimal counterexample', () => {
- test('do not shrink example if no shrinker given', () => {
- const result = property(pairOf(positiveInt), predicate1)(42, 1);
+ test('do not shrink example if no shrinker given', async () => {
+ const result = await property(pairOf(positiveInt), predicate1)(42, 1);
expect(result.result).toBe('Falsified');
expect(result.counterexample).toBeNull;
});
- test('shrink example if shrinker given', () => {
- const result = property(
+ test('shrink example if shrinker given', async () => {
+ const result = await property(
pairOf(positiveInt),
predicate1,
shrinkPair(shrinkPositive, shrinkPositive),
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index 2b69109..56683c1 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -12,28 +12,28 @@ type TestResult<A> = {
counterexample: ShrinkResult<A> | null;
};
-type Predicate<A> = (a: A) => boolean;
+type Predicate<A> = (a: A) => Promise<boolean>;
export type Gen<A> = (rng: Prando) => (size: number) => A;
type Shrinker<A> = (a: A) => A[];
-type Property<A> = (seed: number, size: number) => TestResult<A>;
+type Property<A> = (seed: number, size: number) => Promise<TestResult<A>>;
const MAX_SUCCESS = 100;
-export function findMinimalCounterExample<A>(
+export async function findMinimalCounterExample<A>(
x: A,
predicate: Predicate<A>,
shrinker: Shrinker<A>,
depth = 0,
-): ShrinkResult<A> {
+): Promise<ShrinkResult<A>> {
const xs = shrinker(x);
let counterexample = x;
let shrinks = depth;
for (const y of xs) {
- if (!predicate(y)) {
- const shrink = findMinimalCounterExample(
+ if (!(await predicate(y))) {
+ const shrink = await findMinimalCounterExample(
y,
predicate,
shrinker,
@@ -58,16 +58,20 @@ export function property<A>(
predicate: Predicate<A>,
shrinker?: Shrinker<A>,
): Property<A> {
- return (seed: number, size: number) => {
+ return async (seed: number, size: number) => {
const rng = new Prando(seed);
const gen = generator(rng);
let i = 0;
for (; i < MAX_SUCCESS; i++) {
const x = gen(size);
- if (!predicate(x)) {
+ if (!(await predicate(x))) {
let counterexample = {counterexample: x, shrinks: 0};
if (shrinker !== undefined) {
- counterexample = findMinimalCounterExample(x, predicate, shrinker);
+ counterexample = await findMinimalCounterExample(
+ x,
+ predicate,
+ shrinker,
+ );
}
return {seed, result: 'Falsified', tests: i + 1, counterexample};
}
@@ -239,7 +243,7 @@ export function shrinkPair<A, B>(
}
export const Property = {
- run<A>(prop: Property<A>): TestResult<A> {
+ run<A>(prop: Property<A>): Promise<TestResult<A>> {
const seed = Math.floor(Math.random() * 1000000);
return prop(seed, 0);
},