diff options
Diffstat (limited to 'pbt/ts')
| -rw-r--r-- | pbt/ts/src/bank.test.ts | 18 | ||||
| -rw-r--r-- | pbt/ts/src/bank.ts | 20 | ||||
| -rw-r--r-- | pbt/ts/src/property.test.ts | 6 | ||||
| -rw-r--r-- | pbt/ts/src/property.ts | 20 |
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); } |
