summaryrefslogtreecommitdiff
path: root/pbt/ts
diff options
context:
space:
mode:
Diffstat (limited to 'pbt/ts')
-rw-r--r--pbt/ts/src/bank.test.ts18
-rw-r--r--pbt/ts/src/bank.ts20
-rw-r--r--pbt/ts/src/property.test.ts6
-rw-r--r--pbt/ts/src/property.ts20
4 files changed, 36 insertions, 28 deletions
diff --git a/pbt/ts/src/bank.test.ts b/pbt/ts/src/bank.test.ts
index f6aa7b0..5939034 100644
--- a/pbt/ts/src/bank.test.ts
+++ b/pbt/ts/src/bank.test.ts
@@ -61,20 +61,20 @@ const genOperations = (accounts: Map<Account, number>) =>
const correctBalance =
(initialAccounts: Map<Account, number>) =>
- (ops: Operation[]): Promise<boolean> => {
+ async (ops: Operation[]): Promise<boolean> => {
const expectedBalances = new Map(initialAccounts);
const api = new SimpleBank(initialAccounts);
for (const op of ops) {
switch (op.op) {
case 'GetBalance': {
- const retrieved = toNullable(api.balance(op.account));
+ const retrieved = toNullable(await api.balance(op.account));
const expected = expectedBalances.get(op.account);
if (retrieved !== expected) {
console.log(
`Balance mismatch for account ${op.account}: expected ${expected}, got ${retrieved}`,
);
- return Promise.resolve(false);
+ return false;
}
break;
}
@@ -95,24 +95,24 @@ const correctBalance =
// finally check all balances
for (const [account, expectedBal] of expectedBalances.entries()) {
- const retrieved = toNullable(api.balance(account));
+ const retrieved = toNullable(await api.balance(account));
if (retrieved !== expectedBal) {
console.log(
`Final balance mismatch for account ${account}: expected ${expectedBal}, got ${retrieved}`,
);
- return Promise.resolve(false);
+ return false;
}
}
- return Promise.resolve(true);
+ return true;
};
describe('Bank Simulator', () => {
test('can retrieve balance given account exists', async () => {
- const prop = forall(genAccounts, accounts => {
+ const prop = forall(genAccounts, async accounts => {
const api = new SimpleBank(accounts);
- return property(keyValueOf(accounts), ([accountNr, bal]) => {
- const retrieved = toNullable(api.balance(accountNr));
+ return property(keyValueOf(accounts), async ([accountNr, bal]) => {
+ const retrieved = toNullable(await api.balance(accountNr));
return Promise.resolve(retrieved === bal);
});
});
diff --git a/pbt/ts/src/bank.ts b/pbt/ts/src/bank.ts
index 1f47739..f5981a4 100644
--- a/pbt/ts/src/bank.ts
+++ b/pbt/ts/src/bank.ts
@@ -4,7 +4,7 @@ import {Option, fromNullable, matchW} from 'fp-ts/lib/Option';
export type Account = string;
export interface Bank {
- balance: (account: Account) => Option<number>;
+ balance: (account: Account) => Promise<Option<number>>;
/// Deposit amount into account
///
@@ -15,8 +15,8 @@ export interface Bank {
///
/// @param account The account to deposit into
/// @param amt The amount to deposit
- deposit: (account: Account, amt: number) => void;
- withdraw: (account: Account, amt: number) => void;
+ deposit: (account: Account, amt: number) => Promise<void>;
+ withdraw: (account: Account, amt: number) => Promise<void>;
}
export class SimpleBank implements Bank {
@@ -27,12 +27,12 @@ export class SimpleBank implements Bank {
this.accounts = new Map(accounts);
}
- balance(account: Account): Option<number> {
- return fromNullable(this.accounts.get(account));
+ balance(account: Account): Promise<Option<number>> {
+ return Promise.resolve(fromNullable(this.accounts.get(account)));
}
- deposit(account: Account, amt: number): void {
- const current = this.balance(account);
+ deposit(account: Account, amt: number): Promise<void> {
+ const current = fromNullable(this.accounts.get(account));
matchW(
() => {
throw new Error(`Unknown account ${account}`);
@@ -41,10 +41,11 @@ export class SimpleBank implements Bank {
this.accounts.set(account, bal + amt);
},
)(current);
+ return Promise.resolve();
}
- withdraw(account: Account, amt: number): void {
- const current = this.balance(account);
+ withdraw(account: Account, amt: number): Promise<void> {
+ const current = fromNullable(this.accounts.get(account));
matchW(
() => {
throw new Error(`Unknown account ${account}`);
@@ -53,6 +54,7 @@ export class SimpleBank implements Bank {
this.accounts.set(account, bal - amt);
},
)(current);
+ return Promise.resolve();
}
}
diff --git a/pbt/ts/src/property.test.ts b/pbt/ts/src/property.test.ts
index addff34..67ea81d 100644
--- a/pbt/ts/src/property.test.ts
+++ b/pbt/ts/src/property.test.ts
@@ -12,7 +12,9 @@ const predicate1: (pair: [number, number]) => Promise<boolean> = ([x, y]) =>
describe('Find minimal counterexample', () => {
test('do not shrink example if no shrinker given', async () => {
- const result = await property(pairOf(positiveInt), predicate1)(42, 1);
+ const result = await property(pairOf(positiveInt), predicate1).then(p =>
+ p(42, 1),
+ );
expect(result.result).toBe('Falsified');
expect(result.counterexample).toBeNull;
});
@@ -22,7 +24,7 @@ describe('Find minimal counterexample', () => {
pairOf(positiveInt),
predicate1,
shrinkPair(shrinkPositive, shrinkPositive),
- )(42, 1);
+ ).then(p => p(42, 1));
expect(result.result).toBe('Falsified');
if (result.counterexample !== null) {
expect(result.counterexample.counterexample).toStrictEqual([10, 10]);
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index 56683c1..635e731 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -53,11 +53,11 @@ export function generate<A>(gen: Gen<A>): A {
return gen(rng)(100);
}
-export function property<A>(
+export async function property<A>(
generator: Gen<A>,
predicate: Predicate<A>,
shrinker?: Shrinker<A>,
-): Property<A> {
+): Promise<Property<A>> {
return async (seed: number, size: number) => {
const rng = new Prando(seed);
const gen = generator(rng);
@@ -243,9 +243,10 @@ export function shrinkPair<A, B>(
}
export const Property = {
- run<A>(prop: Property<A>): Promise<TestResult<A>> {
+ async run<A>(prop: Promise<Property<A>>): Promise<TestResult<A>> {
const seed = Math.floor(Math.random() * 1000000);
- return prop(seed, 0);
+ const p = await prop;
+ return await p(seed, 0);
},
};
@@ -253,11 +254,14 @@ export const Property = {
export function forall<A, B>(
gen: Gen<A>,
- k: (a: A) => Property<B>,
-): Property<B> {
- return (seed: number, size: number) => {
+ k: (a: A) => Promise<Property<B>>,
+): Promise<Property<B>> {
+ const p = async (seed: number, size: number) => {
const rng = new Prando(seed);
const a = gen(rng)(size);
- return k(a)(seed, size);
+ const p = await k(a);
+ return await p(seed, size);
};
+
+ return Promise.resolve(p);
}