diff --git a/src/check/property/AsyncProperty.generic.ts b/src/check/property/AsyncProperty.generic.ts index a491d6e8a14..fab326748ee 100644 --- a/src/check/property/AsyncProperty.generic.ts +++ b/src/check/property/AsyncProperty.generic.ts @@ -2,21 +2,26 @@ import { Random } from '../../random/generator/Random'; import { Arbitrary } from '../arbitrary/definition/Arbitrary'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; import { PreconditionFailure } from '../precondition/PreconditionFailure'; -import { IProperty, runIdToFrequency } from './IProperty'; +import { IRawProperty, runIdToFrequency } from './IRawProperty'; /** - * Asynchronous property, see {@link IProperty} + * Interface for asynchronous property, see {@link IRawProperty} + */ +export interface IAsyncProperty extends IRawProperty {} + +/** + * Asynchronous property, see {@link IAsyncProperty} * * Prefer using {@link asyncProperty} instead */ -export class AsyncProperty implements IProperty { +export class AsyncProperty implements IAsyncProperty { static dummyHook: () => Promise = async () => { return; }; private beforeEachHook: () => Promise = AsyncProperty.dummyHook; private afterEachHook: () => Promise = AsyncProperty.dummyHook; constructor(readonly arb: Arbitrary, readonly predicate: (t: Ts) => Promise) {} - isAsync = () => true; + isAsync = () => true as const; generate(mrng: Random, runId?: number): Shrinkable { return runId != null ? this.arb.withBias(runIdToFrequency(runId)).generate(mrng) : this.arb.generate(mrng); } diff --git a/src/check/property/AsyncProperty.ts b/src/check/property/AsyncProperty.ts index 542c5b09655..5cc876933b5 100644 --- a/src/check/property/AsyncProperty.ts +++ b/src/check/property/AsyncProperty.ts @@ -1,4 +1,4 @@ import { asyncProperty } from './AsyncProperty.generated'; -import { AsyncProperty } from './AsyncProperty.generic'; +import { IAsyncProperty } from './AsyncProperty.generic'; -export { asyncProperty, AsyncProperty }; +export { asyncProperty, IAsyncProperty }; diff --git a/src/check/property/IProperty.ts b/src/check/property/IRawProperty.ts similarity index 77% rename from src/check/property/IProperty.ts rename to src/check/property/IRawProperty.ts index 5c10ce73a42..de094a17577 100644 --- a/src/check/property/IProperty.ts +++ b/src/check/property/IRawProperty.ts @@ -9,13 +9,13 @@ import { PreconditionFailure } from '../precondition/PreconditionFailure'; * - Arbitraries: how to generate the inputs for the algorithm * - Predicate: how to confirm the algorithm succeeded? */ -export interface IProperty { +export interface IRawProperty { /** * Is the property asynchronous? * * true in case of asynchronous property, false otherwise */ - isAsync(): boolean; + isAsync(): IsAsync; /** * Generate values of type Ts * @@ -27,7 +27,11 @@ export interface IProperty { * Check the predicate for v * @param v Value of which we want to check the predicate */ - run(v: Ts): Promise | (PreconditionFailure | string | null); + run( + v: Ts + ): + | (IsAsync extends true ? Promise : never) + | (IsAsync extends false ? (PreconditionFailure | string | null) : never); } /** diff --git a/src/check/property/Property.generic.ts b/src/check/property/Property.generic.ts index bd23eb0cf4f..99b6cde6abc 100644 --- a/src/check/property/Property.generic.ts +++ b/src/check/property/Property.generic.ts @@ -2,7 +2,12 @@ import { Random } from '../../random/generator/Random'; import { Arbitrary } from '../arbitrary/definition/Arbitrary'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; import { PreconditionFailure } from '../precondition/PreconditionFailure'; -import { IProperty, runIdToFrequency } from './IProperty'; +import { IRawProperty, runIdToFrequency } from './IRawProperty'; + +/** + * Interface for synchronous property, see {@link IRawProperty} + */ +export interface IProperty extends IRawProperty {} /** * Property, see {@link IProperty} @@ -16,7 +21,7 @@ export class Property implements IProperty { private beforeEachHook: () => void = Property.dummyHook; private afterEachHook: () => void = Property.dummyHook; constructor(readonly arb: Arbitrary, readonly predicate: (t: Ts) => boolean | void) {} - isAsync = () => false; + isAsync = () => false as const; generate(mrng: Random, runId?: number): Shrinkable { return runId != null ? this.arb.withBias(runIdToFrequency(runId)).generate(mrng) : this.arb.generate(mrng); } diff --git a/src/check/property/Property.ts b/src/check/property/Property.ts index 0a6ae2987d2..959e4e5d659 100644 --- a/src/check/property/Property.ts +++ b/src/check/property/Property.ts @@ -1,4 +1,4 @@ import { property } from './Property.generated'; -import { Property } from './Property.generic'; +import { IProperty } from './Property.generic'; -export { property, Property }; +export { property, IProperty }; diff --git a/src/check/property/SkipAfterProperty.ts b/src/check/property/SkipAfterProperty.ts index bf794953abe..5adc8bb59a6 100644 --- a/src/check/property/SkipAfterProperty.ts +++ b/src/check/property/SkipAfterProperty.ts @@ -1,12 +1,12 @@ import { Random } from '../../random/generator/Random'; import { PreconditionFailure } from '../precondition/PreconditionFailure'; -import { IProperty } from './IProperty'; +import { IRawProperty } from './IRawProperty'; /** @hidden */ -export class SkipAfterProperty implements IProperty { +export class SkipAfterProperty implements IRawProperty { private skipAfterTime: number; constructor( - readonly property: IProperty, + readonly property: IRawProperty, readonly getTime: () => number, timeLimit: number, readonly interruptExecution: boolean @@ -17,7 +17,12 @@ export class SkipAfterProperty implements IProperty { generate = (mrng: Random, runId?: number) => this.property.generate(mrng, runId); run = (v: Ts) => { if (this.getTime() >= this.skipAfterTime) { - return new PreconditionFailure(this.interruptExecution); + const preconditionFailure = new PreconditionFailure(this.interruptExecution); + if (this.isAsync()) { + return Promise.resolve(preconditionFailure) as any; // IsAsync => Promise + } else { + return preconditionFailure as any; // !IsAsync => PreconditionFailure | string | null + } } return this.property.run(v); }; diff --git a/src/check/property/TimeoutProperty.ts b/src/check/property/TimeoutProperty.ts index cf6193c64b5..e8ab8e40d57 100644 --- a/src/check/property/TimeoutProperty.ts +++ b/src/check/property/TimeoutProperty.ts @@ -1,6 +1,6 @@ import { Random } from '../../random/generator/Random'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; -import { IProperty } from './IProperty'; +import { IRawProperty } from './IRawProperty'; /** @hidden */ const timeoutAfter = (timeMs: number) => { @@ -17,9 +17,9 @@ const timeoutAfter = (timeMs: number) => { }; /** @hidden */ -export class TimeoutProperty implements IProperty { - constructor(readonly property: IProperty, readonly timeMs: number) {} - isAsync = () => true; +export class TimeoutProperty implements IRawProperty { + constructor(readonly property: IRawProperty, readonly timeMs: number) {} + isAsync = () => true as const; generate(mrng: Random, runId?: number): Shrinkable { return this.property.generate(mrng, runId); } diff --git a/src/check/property/UnbiasedProperty.ts b/src/check/property/UnbiasedProperty.ts index 0c70cdeebff..8840f1ca5b9 100644 --- a/src/check/property/UnbiasedProperty.ts +++ b/src/check/property/UnbiasedProperty.ts @@ -1,9 +1,9 @@ import { Random } from '../../random/generator/Random'; -import { IProperty } from './IProperty'; +import { IRawProperty } from './IRawProperty'; /** @hidden */ -export class UnbiasedProperty implements IProperty { - constructor(readonly property: IProperty) {} +export class UnbiasedProperty implements IRawProperty { + constructor(readonly property: IRawProperty) {} isAsync = () => this.property.isAsync(); generate = (mrng: Random, runId?: number) => this.property.generate(mrng); run = (v: Ts) => this.property.run(v); diff --git a/src/check/runner/DecorateProperty.ts b/src/check/runner/DecorateProperty.ts index 9e6194ca3d6..07a92b16289 100644 --- a/src/check/runner/DecorateProperty.ts +++ b/src/check/runner/DecorateProperty.ts @@ -1,4 +1,4 @@ -import { IProperty } from '../property/IProperty'; +import { IRawProperty } from '../property/IRawProperty'; import { SkipAfterProperty } from '../property/SkipAfterProperty'; import { TimeoutProperty } from '../property/TimeoutProperty'; import { UnbiasedProperty } from '../property/UnbiasedProperty'; @@ -11,7 +11,7 @@ type MinimalQualifiedParameters = Pick< >; /** @hidden */ -export function decorateProperty(rawProperty: IProperty, qParams: MinimalQualifiedParameters) { +export function decorateProperty(rawProperty: IRawProperty, qParams: MinimalQualifiedParameters) { let prop = rawProperty; if (rawProperty.isAsync() && qParams.timeout != null) prop = new TimeoutProperty(prop, qParams.timeout); if (qParams.unbiased === true) prop = new UnbiasedProperty(prop); diff --git a/src/check/runner/Runner.ts b/src/check/runner/Runner.ts index fca2f118e2b..bae2b6f277f 100644 --- a/src/check/runner/Runner.ts +++ b/src/check/runner/Runner.ts @@ -1,9 +1,7 @@ import { stream } from '../../stream/Stream'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; import { PreconditionFailure } from '../precondition/PreconditionFailure'; -import { AsyncProperty } from '../property/AsyncProperty'; -import { IProperty } from '../property/IProperty'; -import { Property } from '../property/Property'; +import { IRawProperty } from '../property/IRawProperty'; import { readConfigureGlobal } from './configuration/GlobalParameters'; import { Parameters } from './configuration/Parameters'; import { QualifiedParameters } from './configuration/QualifiedParameters'; @@ -16,10 +14,12 @@ import { SourceValuesIterator } from './SourceValuesIterator'; import { toss } from './Tosser'; import { pathWalk } from './utils/PathWalker'; import { throwIfFailed } from './utils/RunDetailsFormatter'; +import { IAsyncProperty } from '../property/AsyncProperty'; +import { IProperty } from '../property/Property'; /** @hidden */ function runIt( - property: IProperty, + property: IRawProperty, sourceValues: SourceValuesIterator>, verbose: VerbosityLevel, interruptedAsFailure: boolean @@ -34,7 +34,7 @@ function runIt( /** @hidden */ async function asyncRunIt( - property: IProperty, + property: IRawProperty, sourceValues: SourceValuesIterator>, verbose: VerbosityLevel, interruptedAsFailure: boolean @@ -83,7 +83,7 @@ function buildInitialValues( * * @returns Test status and other useful details */ -function check(property: AsyncProperty, params?: Parameters): Promise>; +function check(property: IAsyncProperty, params?: Parameters): Promise>; /** * Run the property, do not throw contrary to {@link assert} * @@ -92,9 +92,9 @@ function check(property: AsyncProperty, params?: Parameters): Promis * * @returns Test status and other useful details */ -function check(property: Property, params?: Parameters): RunDetails; -function check(property: IProperty, params?: Parameters): Promise> | RunDetails; -function check(rawProperty: IProperty, params?: Parameters) { +function check(property: IProperty, params?: Parameters): RunDetails; +function check(property: IRawProperty, params?: Parameters): Promise> | RunDetails; +function check(rawProperty: IRawProperty, params?: Parameters) { if (rawProperty == null || rawProperty.generate == null) throw new Error('Invalid property encountered, please use a valid property'); if (rawProperty.run == null) @@ -130,7 +130,7 @@ function check(rawProperty: IProperty, params?: Parameters) { * @param property Asynchronous property to be checked * @param params Optional parameters to customize the execution */ -function assert(property: AsyncProperty, params?: Parameters): Promise; +function assert(property: IAsyncProperty, params?: Parameters): Promise; /** * Run the property, throw in case of failure * @@ -140,9 +140,9 @@ function assert(property: AsyncProperty, params?: Parameters): Promi * @param property Synchronous property to be checked * @param params Optional parameters to customize the execution */ -function assert(property: Property, params?: Parameters): void; -function assert(property: IProperty, params?: Parameters): Promise | void; -function assert(property: IProperty, params?: Parameters) { +function assert(property: IProperty, params?: Parameters): void; +function assert(property: IRawProperty, params?: Parameters): Promise | void; +function assert(property: IRawProperty, params?: Parameters) { const out = check(property, params); if (property.isAsync()) return (out as Promise>).then(throwIfFailed); else throwIfFailed(out as RunDetails); diff --git a/src/check/runner/Sampler.ts b/src/check/runner/Sampler.ts index b34583e7a4f..cddff42ef59 100644 --- a/src/check/runner/Sampler.ts +++ b/src/check/runner/Sampler.ts @@ -2,8 +2,8 @@ import { Stream, stream } from '../../stream/Stream'; import { ObjectEntries, StringPadEnd, StringPadStart } from '../../utils/polyfills'; import { Arbitrary } from '../arbitrary/definition/Arbitrary'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; -import { IProperty } from '../property/IProperty'; -import { Property } from '../property/Property'; +import { IRawProperty } from '../property/IRawProperty'; +import { Property } from '../property/Property.generic'; import { UnbiasedProperty } from '../property/UnbiasedProperty'; import { readConfigureGlobal } from './configuration/GlobalParameters'; import { Parameters } from './configuration/Parameters'; @@ -12,16 +12,19 @@ import { toss } from './Tosser'; import { pathWalk } from './utils/PathWalker'; /** @hidden */ -function toProperty(generator: IProperty | Arbitrary, qParams: QualifiedParameters): IProperty { +function toProperty( + generator: IRawProperty | Arbitrary, + qParams: QualifiedParameters +): IRawProperty { const prop = !Object.prototype.hasOwnProperty.call(generator, 'isAsync') ? new Property(generator as Arbitrary, () => true) - : (generator as IProperty); + : (generator as IRawProperty); return qParams.unbiased === true ? new UnbiasedProperty(prop) : prop; } /** @hidden */ function streamSample( - generator: IProperty | Arbitrary, + generator: IRawProperty | Arbitrary, params?: Parameters | number ): IterableIterator { const extendedParams = @@ -52,7 +55,7 @@ function streamSample( * @param generator {@link IProperty} or {@link Arbitrary} to extract the values from * @param params Integer representing the number of values to generate or {@link Parameters} as in {@link assert} */ -function sample(generator: IProperty | Arbitrary, params?: Parameters | number): Ts[] { +function sample(generator: IRawProperty | Arbitrary, params?: Parameters | number): Ts[] { return [...streamSample(generator, params)]; } @@ -78,7 +81,7 @@ function sample(generator: IProperty | Arbitrary, params?: Parameter * @param params Integer representing the number of values to generate or {@link Parameters} as in {@link assert} */ function statistics( - generator: IProperty | Arbitrary, + generator: IRawProperty | Arbitrary, classify: (v: Ts) => string | string[], params?: Parameters | number ): void { diff --git a/src/check/runner/Tosser.ts b/src/check/runner/Tosser.ts index a43ffc78334..c36c11a020e 100644 --- a/src/check/runner/Tosser.ts +++ b/src/check/runner/Tosser.ts @@ -2,16 +2,16 @@ import * as prand from 'pure-rand'; import { Random } from '../../random/generator/Random'; import { Shrinkable } from '../arbitrary/definition/Shrinkable'; -import { IProperty } from '../property/IProperty'; +import { IRawProperty } from '../property/IRawProperty'; /** @hidden */ -function lazyGenerate(generator: IProperty, rng: prand.RandomGenerator, idx: number): () => Shrinkable { +function lazyGenerate(generator: IRawProperty, rng: prand.RandomGenerator, idx: number): () => Shrinkable { return () => generator.generate(new Random(rng), idx); } /** @hidden */ export function* toss( - generator: IProperty, + generator: IRawProperty, seed: number, random: (seed: number) => prand.RandomGenerator, examples: Ts[] diff --git a/src/fast-check-default.ts b/src/fast-check-default.ts index a124935f0c8..762ba8f00a7 100644 --- a/src/fast-check-default.ts +++ b/src/fast-check-default.ts @@ -1,6 +1,7 @@ import { pre } from './check/precondition/Pre'; -import { asyncProperty } from './check/property/AsyncProperty'; -import { property } from './check/property/Property'; +import { asyncProperty, IAsyncProperty } from './check/property/AsyncProperty'; +import { property, IProperty } from './check/property/Property'; +import { IRawProperty } from './check/property/IRawProperty'; import { Parameters } from './check/runner/configuration/Parameters'; import { RunDetails } from './check/runner/reporter/RunDetails'; import { assert, check } from './check/runner/Runner'; @@ -106,6 +107,9 @@ export { // property definition property, asyncProperty, + IRawProperty, + IProperty, + IAsyncProperty, // pre-built arbitraries boolean, float, diff --git a/test/unit/check/property/SkipAfterProperty.spec.ts b/test/unit/check/property/SkipAfterProperty.spec.ts index 6029aedfe83..b8716ee0c1f 100644 --- a/test/unit/check/property/SkipAfterProperty.spec.ts +++ b/test/unit/check/property/SkipAfterProperty.spec.ts @@ -1,4 +1,4 @@ -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { SkipAfterProperty } from '../../../../src/check/property/SkipAfterProperty'; // Mocks @@ -12,7 +12,7 @@ function buildProperty() { generate: jest.fn(), run: jest.fn() }; - return { mocks, property: mocks as IProperty }; + return { mocks, property: mocks as IRawProperty }; } function buildRandom() { @@ -78,7 +78,7 @@ describe('SkipAfterProperty', () => { expect(PreconditionFailure.isFailure(out)).toBe(true); expect(timerMock.mock.calls.length).toBe(2); - expect(propertyMock.isAsync.mock.calls.length).toBe(0); + expect(propertyMock.isAsync.mock.calls.length).toBe(1); // check expected return type: return a resolved Promise if async, a value otherwise expect(propertyMock.generate.mock.calls.length).toBe(0); expect(propertyMock.run.mock.calls.length).toBe(0); }); diff --git a/test/unit/check/property/TimeoutProperty.utest.spec.ts b/test/unit/check/property/TimeoutProperty.utest.spec.ts index 1c8319106e6..821e7085968 100644 --- a/test/unit/check/property/TimeoutProperty.utest.spec.ts +++ b/test/unit/check/property/TimeoutProperty.utest.spec.ts @@ -1,5 +1,5 @@ import { Shrinkable } from '../../../../src/check/arbitrary/definition/Shrinkable'; -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { TimeoutProperty } from '../../../../src/check/property/TimeoutProperty'; import * as stubRng from '../../stubs/generators'; @@ -18,7 +18,7 @@ describe('TimeoutProperty', () => { const expectedMrng = mrng(); const expectedRunId = 42; const expectedOut = new Shrinkable({}); - const p: IProperty = { + const p: IRawProperty = { isAsync: () => true, generate: jest.fn().mockReturnValueOnce(expectedOut), run: jest.fn() @@ -37,7 +37,7 @@ describe('TimeoutProperty', () => { it('Should forward inputs to run', async () => { // Arrange const runInput = {}; - const p: IProperty = { + const p: IRawProperty = { isAsync: () => true, generate: jest.fn(), run: jest.fn() @@ -56,7 +56,7 @@ describe('TimeoutProperty', () => { it('Should not timeout if it succeeds in time', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockReturnValueOnce( @@ -77,7 +77,7 @@ describe('TimeoutProperty', () => { it('Should not timeout if it fails in time', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockReturnValueOnce( @@ -99,7 +99,7 @@ describe('TimeoutProperty', () => { it('Should clear all started timeouts on success', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockResolvedValueOnce(null) @@ -116,7 +116,7 @@ describe('TimeoutProperty', () => { it('Should clear all started timeouts on failure', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockResolvedValueOnce('plop') @@ -133,7 +133,7 @@ describe('TimeoutProperty', () => { it('Should timeout if it takes to long', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockReturnValueOnce( @@ -154,7 +154,7 @@ describe('TimeoutProperty', () => { it('Should timeout if it never ends', async () => { // Arrange - const p: IProperty<{}> = { + const p: IRawProperty<{}> = { isAsync: () => true, generate: jest.fn(), run: jest.fn().mockReturnValueOnce(new Promise(function(resolve, reject) {})) diff --git a/test/unit/check/property/UnbiasedProperty.spec.ts b/test/unit/check/property/UnbiasedProperty.spec.ts index 7e2d7df4278..b27bcb0f016 100644 --- a/test/unit/check/property/UnbiasedProperty.spec.ts +++ b/test/unit/check/property/UnbiasedProperty.spec.ts @@ -1,5 +1,5 @@ import { Shrinkable } from '../../../../src/check/arbitrary/definition/Shrinkable'; -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { UnbiasedProperty } from '../../../../src/check/property/UnbiasedProperty'; import * as stubRng from '../../stubs/generators'; @@ -7,7 +7,7 @@ import * as stubRng from '../../stubs/generators'; describe('UnbiasedProperty', () => { it('Should forward parameters correctly (asynchronous property)', () => { let calledWithRunId: number | undefined = undefined; - const pAsync = new (class implements IProperty { + const pAsync = new (class implements IRawProperty { isAsync = () => true; generate = (mrng: any, runId?: number) => { calledWithRunId = runId; @@ -27,7 +27,7 @@ describe('UnbiasedProperty', () => { }); it('Should forward parameters correctly (synchronous property)', () => { let calledWithRunId: number | undefined = undefined; - const pSync = new (class implements IProperty { + const pSync = new (class implements IRawProperty { isAsync = () => false; generate = (mrng: any, runId?: number) => { calledWithRunId = runId; diff --git a/test/unit/check/runner/DecorateProperty.spec.ts b/test/unit/check/runner/DecorateProperty.spec.ts index 679c019994b..81d97c46634 100644 --- a/test/unit/check/runner/DecorateProperty.spec.ts +++ b/test/unit/check/runner/DecorateProperty.spec.ts @@ -1,5 +1,5 @@ import { decorateProperty } from '../../../../src/check/runner/DecorateProperty'; -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { Shrinkable } from '../../../../src/check/arbitrary/definition/Shrinkable'; // Mocks @@ -15,7 +15,7 @@ function buildProperty(asyncProp: boolean) { isAsync: () => asyncProp, generate: () => new Shrinkable({}), run: () => null - } as IProperty; + } as IRawProperty; } describe('decorateProperty', () => { diff --git a/test/unit/check/runner/Runner.spec.ts b/test/unit/check/runner/Runner.spec.ts index 6fcffd15765..740879cdbef 100644 --- a/test/unit/check/runner/Runner.spec.ts +++ b/test/unit/check/runner/Runner.spec.ts @@ -2,7 +2,7 @@ import * as fc from '../../../../lib/fast-check'; import { Shrinkable } from '../../../../src/check/arbitrary/definition/Shrinkable'; import { char } from '../../../../src/check/arbitrary/CharacterArbitrary'; -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { check, assert as rAssert } from '../../../../src/check/runner/Runner'; import { Random } from '../../../../src/random/generator/Random'; import { RunDetails } from '../../../../src/check/runner/reporter/RunDetails'; @@ -14,18 +14,18 @@ const MAX_NUM_RUNS = 1000; describe('Runner', () => { describe('check', () => { it('Should throw if property is null', () => { - expect(() => check((null as any) as IProperty<{}>)).toThrowError(); + expect(() => check((null as any) as IRawProperty<{}>)).toThrowError(); }); it('Should throw if property is not a property at all', () => { - expect(() => check({} as IProperty<{}>)).toThrowError(); + expect(() => check({} as IRawProperty<{}>)).toThrowError(); }); it('Should throw if property is an Arbitrary', () => { - expect(() => check((char() as any) as IProperty<{}>)).toThrowError(); + expect(() => check((char() as any) as IRawProperty<{}>)).toThrowError(); }); it('Should call the property 100 times by default (on success)', () => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { expect(numCallsRun).toEqual(numCallsGenerate); // called run before calling back @@ -46,7 +46,7 @@ describe('Runner', () => { it('Should call the property 100 times even when path provided (on success)', () => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { expect(numCallsRun).toEqual(numCallsGenerate); // called run before calling back @@ -67,7 +67,7 @@ describe('Runner', () => { it('Should call the property on all shrunk values for path (on success)', () => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { ++numCallsGenerate; @@ -102,7 +102,7 @@ describe('Runner', () => { async (successIds, isAsyncProp, failAtId) => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => isAsyncProp, generate: () => new Shrinkable([numCallsGenerate++]) as Shrinkable<[number]>, run: (value: [number]) => { @@ -142,7 +142,7 @@ describe('Runner', () => { async (settings, isAsyncProp) => { let numCallsGenerate = 0; let numPreconditionFailures = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => isAsyncProp, generate: () => new Shrinkable([numCallsGenerate++]) as Shrinkable<[number]>, run: (value: [number]) => { @@ -165,7 +165,7 @@ describe('Runner', () => { it('Should never call shrink on success', () => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { ++numCallsGenerate; @@ -188,7 +188,7 @@ describe('Runner', () => { fc.property(fc.integer(1, 100), fc.integer(), (num, seed) => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { ++numCallsGenerate; @@ -212,7 +212,7 @@ describe('Runner', () => { fc.property(fc.nat(MAX_NUM_RUNS), num => { let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { ++numCallsGenerate; @@ -234,7 +234,7 @@ describe('Runner', () => { fc.assert( fc.property(fc.integer(), seed => { const buildPropertyFor = function(runOn: number[]) { - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: (rng: Random) => { return new Shrinkable([rng.nextInt()]) as Shrinkable<[number]>; @@ -255,7 +255,7 @@ describe('Runner', () => { }) )); it('Should never call shrink if endOnFailure', () => { - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { return new Shrinkable([0], () => { @@ -271,7 +271,7 @@ describe('Runner', () => { expect(out.numShrinks).toEqual(0); }); it('Should compute values for path before removing shrink if endOnFailure', () => { - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { const g = function*() { @@ -290,7 +290,7 @@ describe('Runner', () => { expect(out.numShrinks).toEqual(0); }); it('Should not provide list of failures by default (no verbose)', () => { - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => new Shrinkable([42]) as Shrinkable<[number]>, run: () => 'failure' @@ -303,7 +303,7 @@ describe('Runner', () => { yield new Shrinkable([48]) as Shrinkable<[number]>; yield new Shrinkable([12]) as Shrinkable<[number]>; }; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => new Shrinkable([42], () => stream(g())) as Shrinkable<[number]>, run: () => 'failure' @@ -330,7 +330,7 @@ describe('Runner', () => { let idx = 0; let remainingBeforeFailure = failurePoints[idx]; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: (rng: Random) => deepShrinkable(failurePoints.length - 1), run: (value: [number]) => { @@ -357,7 +357,7 @@ describe('Runner', () => { const waitingResolve: (() => void)[] = []; let numCallsGenerate = 0; let numCallsRun = 0; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => true, generate: () => { ++numCallsGenerate; @@ -399,7 +399,7 @@ describe('Runner', () => { }) )); it('Should not timeout if no timeout defined', async () => { - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => true, generate: () => new Shrinkable([1]) as Shrinkable<[number]>, run: async (value: [number]) => null @@ -409,7 +409,7 @@ describe('Runner', () => { }); it('Should not timeout if timeout not reached', async () => { const wait = (timeMs: number) => new Promise((resolve, reject) => setTimeout(resolve, timeMs)); - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => true, generate: () => new Shrinkable([1]) as Shrinkable<[number]>, run: async (value: [number]) => await wait(0) @@ -419,7 +419,7 @@ describe('Runner', () => { }); it('Should timeout if it reached the timeout', async () => { const wait = (timeMs: number) => new Promise((resolve, reject) => setTimeout(resolve, timeMs)); - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => true, generate: () => new Shrinkable([1]) as Shrinkable<[number]>, run: async (value: [number]) => await wait(100) @@ -429,7 +429,7 @@ describe('Runner', () => { }); it('Should timeout if task never ends', async () => { const neverEnds = () => new Promise((resolve, reject) => {}); - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => true, generate: () => new Shrinkable([1]) as Shrinkable<[number]>, run: async (value: [number]) => await neverEnds() @@ -441,30 +441,30 @@ describe('Runner', () => { describe('assert', () => { const v1 = { toString: () => 'toString(value#1)' }; const v2 = { a: 'Hello', b: 21 }; - const failingProperty: IProperty<[any, any]> = { + const failingProperty: IRawProperty<[any, any]> = { isAsync: () => false, generate: () => new Shrinkable([v1, v2]) as Shrinkable<[any, any]>, run: (v: [any, any]) => 'error in failingProperty' }; - const failingComplexProperty: IProperty<[any, any, any]> = { + const failingComplexProperty: IRawProperty<[any, any, any]> = { isAsync: () => false, generate: () => new Shrinkable([[v1, v2], v2, v1]) as Shrinkable<[any, any, any]>, run: (v: [any, any, any]) => 'error in failingComplexProperty' }; - const successProperty: IProperty<[any, any]> = { + const successProperty: IRawProperty<[any, any]> = { isAsync: () => false, generate: () => new Shrinkable([v1, v2]) as Shrinkable<[any, any]>, run: (v: [any, any]) => null }; it('Should throw if property is null', () => { - expect(() => rAssert((null as any) as IProperty<{}>)).toThrowError(); + expect(() => rAssert((null as any) as IRawProperty<{}>)).toThrowError(); }); it('Should throw if property is not a property at all', () => { - expect(() => rAssert({} as IProperty<{}>)).toThrowError(); + expect(() => rAssert({} as IRawProperty<{}>)).toThrowError(); }); it('Should throw if property is an Arbitrary', () => { - expect(() => rAssert((char() as any) as IProperty<{}>)).toThrowError(); + expect(() => rAssert((char() as any) as IRawProperty<{}>)).toThrowError(); }); it('Should never throw if no failure occured', () => { expect(() => rAssert(successProperty, { seed: 42 })).not.toThrow(); @@ -491,7 +491,7 @@ describe('Runner', () => { }); describe('Impact of VerbosityLevel in case of failure', () => { const baseErrorMessage = ''; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => { const g = function*() { @@ -534,7 +534,7 @@ describe('Runner', () => { }); describe('Impact of VerbosityLevel in case of too many skipped runs', () => { const baseErrorMessage = 'Failed to run property, too many pre-condition failures encountered'; - const p: IProperty<[number]> = { + const p: IRawProperty<[number]> = { isAsync: () => false, generate: () => new Shrinkable([42]) as Shrinkable<[number]>, run: () => new PreconditionFailure() diff --git a/test/unit/check/runner/Tosser.spec.ts b/test/unit/check/runner/Tosser.spec.ts index d53241157bf..46346b50346 100644 --- a/test/unit/check/runner/Tosser.spec.ts +++ b/test/unit/check/runner/Tosser.spec.ts @@ -3,14 +3,14 @@ import * as fc from '../../../../lib/fast-check'; import { toss } from '../../../../src/check/runner/Tosser'; import { stream } from '../../../../src/stream/Stream'; import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary'; -import { IProperty } from '../../../../src/check/property/IProperty'; +import { IRawProperty } from '../../../../src/check/property/IRawProperty'; import { Random } from '../../../../src/random/generator/Random'; import * as stubArb from '../../stubs/arbitraries'; import prand from 'pure-rand'; -const wrap = (arb: Arbitrary): IProperty => - new (class implements IProperty { +const wrap = (arb: Arbitrary): IRawProperty => + new (class implements IRawProperty { constructor(readonly arb: Arbitrary) {} isAsync = () => false; generate = (rng: Random) => this.arb.generate(rng);