UNPKG

fast-check

Version:

Property based testing framework for JavaScript (like QuickCheck)

1,698 lines 350 kB
import { t as __exportAll } from "./chunk-pbuEa-1d.js"; import { congruential32 } from "pure-rand/generator/congruential32"; import { mersenne } from "pure-rand/generator/mersenne"; import { xorshift128plus } from "pure-rand/generator/xorshift128plus"; import { xoroshiro128plus } from "pure-rand/generator/xoroshiro128plus"; import { skipN } from "pure-rand/utils/skipN"; import { uniformBigInt } from "pure-rand/distribution/uniformBigInt"; import { uniformInt } from "pure-rand/distribution/uniformInt"; //#region src/check/precondition/PreconditionFailure.ts /** @internal */ const SharedFootPrint = Symbol.for("fast-check/PreconditionFailure"); /** * Error type produced whenever a precondition fails * @remarks Since 2.2.0 * @public */ var PreconditionFailure = class extends Error { constructor(interruptExecution = false) { super(); this.interruptExecution = interruptExecution; this.footprint = SharedFootPrint; } static isFailure(err) { return err !== null && err !== void 0 && err.footprint === SharedFootPrint; } }; //#endregion //#region src/check/precondition/Pre.ts /** * Add pre-condition checks inside a property execution * @param expectTruthy - cancel the run whenever this value is falsy * @remarks Since 1.3.0 * @public */ function pre(expectTruthy) { if (!expectTruthy) throw new PreconditionFailure(); } //#endregion //#region src/stream/StreamHelpers.ts var Nil = class { [Symbol.iterator]() { return this; } next(value) { return { value, done: true }; } }; /** @internal */ const nil = new Nil(); /** @internal */ function nilHelper() { return nil; } /** @internal */ function* mapHelper(g, f) { for (const v of g) yield f(v); } /** @internal */ function* flatMapHelper(g, f) { for (const v of g) yield* f(v); } /** @internal */ function* filterHelper(g, f) { for (const v of g) if (f(v)) yield v; } /** @internal */ function* takeNHelper(g, n) { for (let i = 0; i < n; ++i) { const cur = g.next(); if (cur.done) break; yield cur.value; } } /** @internal */ function* takeWhileHelper(g, f) { let cur = g.next(); while (!cur.done && f(cur.value)) { yield cur.value; cur = g.next(); } } /** @internal */ function* joinHelper(g, others) { for (let cur = g.next(); !cur.done; cur = g.next()) yield cur.value; for (const s of others) for (let cur = s.next(); !cur.done; cur = s.next()) yield cur.value; } //#endregion //#region src/stream/Stream.ts const safeSymbolIterator$1 = Symbol.iterator; /** * Wrapper around `IterableIterator` interface * offering a set of helpers to deal with iterations in a simple way * * @remarks Since 0.0.7 * @public */ var Stream = class Stream { /** * Create an empty stream of T * @remarks Since 0.0.1 */ static nil() { return new Stream(nilHelper()); } /** * Create a stream of T from a variable number of elements * * @param elements - Elements used to create the Stream * @remarks Since 2.12.0 */ static of(...elements) { return new Stream(elements[safeSymbolIterator$1]()); } /** * Create a Stream based on `g` * @param g - Underlying data of the Stream */ constructor(g) { this.g = g; } next() { return this.g.next(); } [Symbol.iterator]() { return this.g; } /** * Map all elements of the Stream using `f` * * WARNING: It closes the current stream * * @param f - Mapper function * @remarks Since 0.0.1 */ map(f) { return new Stream(mapHelper(this.g, f)); } /** * Flat map all elements of the Stream using `f` * * WARNING: It closes the current stream * * @param f - Mapper function * @remarks Since 0.0.1 */ flatMap(f) { return new Stream(flatMapHelper(this.g, f)); } /** * Drop elements from the Stream while `f(element) === true` * * WARNING: It closes the current stream * * @param f - Drop condition * @remarks Since 0.0.1 */ dropWhile(f) { let foundEligible = false; function* helper(v) { if (foundEligible || !f(v)) { foundEligible = true; yield v; } } return this.flatMap(helper); } /** * Drop `n` first elements of the Stream * * WARNING: It closes the current stream * * @param n - Number of elements to drop * @remarks Since 0.0.1 */ drop(n) { if (n <= 0) return this; let idx = 0; function helper() { return idx++ < n; } return this.dropWhile(helper); } /** * Take elements from the Stream while `f(element) === true` * * WARNING: It closes the current stream * * @param f - Take condition * @remarks Since 0.0.1 */ takeWhile(f) { return new Stream(takeWhileHelper(this.g, f)); } /** * Take `n` first elements of the Stream * * WARNING: It closes the current stream * * @param n - Number of elements to take * @remarks Since 0.0.1 */ take(n) { return new Stream(takeNHelper(this.g, n)); } filter(f) { return new Stream(filterHelper(this.g, f)); } /** * Check whether all elements of the Stream are successful for `f` * * WARNING: It closes the current stream * * @param f - Condition to check * @remarks Since 0.0.1 */ every(f) { for (const v of this.g) if (!f(v)) return false; return true; } /** * Check whether one of the elements of the Stream is successful for `f` * * WARNING: It closes the current stream * * @param f - Condition to check * @remarks Since 0.0.1 */ has(f) { for (const v of this.g) if (f(v)) return [true, v]; return [false, null]; } /** * Join `others` Stream to the current Stream * * WARNING: It closes the current stream and the other ones (as soon as it iterates over them) * * @param others - Streams to join to the current Stream * @remarks Since 0.0.1 */ join(...others) { return new Stream(joinHelper(this.g, others)); } /** * Take the `nth` element of the Stream of the last (if it does not exist) * * WARNING: It closes the current stream * * @param nth - Position of the element to extract * @remarks Since 0.0.12 */ getNthOrLast(nth) { let remaining = nth; let last = null; for (const v of this.g) { if (remaining-- === 0) return v; last = v; } return last; } }; /** * Create a Stream based on `g` * * @param g - Underlying data of the Stream * * @remarks Since 0.0.7 * @public */ function stream(g) { return new Stream(g); } //#endregion //#region src/check/symbols.ts /** * Generated instances having a method [cloneMethod] * will be automatically cloned whenever necessary * * This is pretty useful for statefull generated values. * For instance, whenever you use a Stream you directly impact it. * Implementing [cloneMethod] on the generated Stream would force * the framework to clone it whenever it has to re-use it * (mainly required for chrinking process) * * @remarks Since 1.8.0 * @public */ const cloneMethod = Symbol.for("fast-check/cloneMethod"); /** * Check if an instance has to be clone * @remarks Since 2.15.0 * @public */ function hasCloneMethod(instance) { return instance !== null && (typeof instance === "object" || typeof instance === "function") && cloneMethod in instance && typeof instance[cloneMethod] === "function"; } /** * Clone an instance if needed * @remarks Since 2.15.0 * @public */ function cloneIfNeeded(instance) { return hasCloneMethod(instance) ? instance[cloneMethod]() : instance; } //#endregion //#region src/check/arbitrary/definition/Value.ts const safeObjectDefineProperty$4 = Object.defineProperty; /** * A `Value<T, TShrink = T>` holds an internal value of type `T` * and its associated context * * @remarks Since 3.0.0 (previously called `NextValue` in 2.15.0) * @public */ var Value = class { /** * @param value_ - Internal value of the shrinkable * @param context - Context associated to the generated value (useful for shrink) * @param customGetValue - Limited to internal usages (to ease migration to next), it will be removed on next major */ constructor(value_, context, customGetValue = void 0) { this.value_ = value_; this.context = context; this.hasToBeCloned = customGetValue !== void 0 || hasCloneMethod(value_); this.readOnce = false; if (this.hasToBeCloned) safeObjectDefineProperty$4(this, "value", { get: customGetValue !== void 0 ? customGetValue : this.getValue }); else this.value = value_; } /** @internal */ getValue() { if (this.hasToBeCloned) { if (!this.readOnce) { this.readOnce = true; return this.value_; } return this.value_[cloneMethod](); } return this.value_; } }; //#endregion //#region src/check/arbitrary/definition/Arbitrary.ts /** * Abstract class able to generate values on type `T` * * The values generated by an instance of Arbitrary can be previewed - with {@link sample} - or classified - with {@link statistics}. * * @remarks Since 0.0.7 * @public */ var Arbitrary = class { filter(refinement) { return new FilterArbitrary(this, refinement); } /** * Create another arbitrary by mapping all produced values using the provided `mapper` * Values produced by the new arbitrary are the result of applying `mapper` value by value * * @example * ```typescript * const rgbChannels: Arbitrary<{r:number,g:number,b:number}> = ...; * const color: Arbitrary<string> = rgbChannels.map(ch => `#${(ch.r*65536 + ch.g*256 + ch.b).toString(16).padStart(6, '0')}`); * // transform an Arbitrary producing {r,g,b} integers into an Arbitrary of '#rrggbb' * ``` * * @param mapper - Map function, to produce a new element based on an old one * @param unmapper - Optional unmap function, it will never be used except when shrinking user defined values. Must throw if value is not compatible (since 3.0.0) * @returns New arbitrary with mapped elements * * @remarks Since 0.0.1 */ map(mapper, unmapper) { return new MapArbitrary(this, mapper, unmapper); } /** * Create another arbitrary by mapping a value from a base Arbirary using the provided `fmapper` * Values produced by the new arbitrary are the result of the arbitrary generated by applying `fmapper` to a value * @example * ```typescript * const arrayAndLimitArbitrary = fc.nat().chain((c: number) => fc.tuple( fc.array(fc.nat(c)), fc.constant(c))); * ``` * * @param chainer - Chain function, to produce a new Arbitrary using a value from another Arbitrary * @returns New arbitrary of new type * * @remarks Since 1.2.0 */ chain(chainer) { return new ChainArbitrary(this, chainer); } }; /** @internal */ var ChainArbitrary = class extends Arbitrary { constructor(arb, chainer) { super(); this.arb = arb; this.chainer = chainer; } generate(mrng, biasFactor) { const clonedMrng = mrng.clone(); const src = this.arb.generate(mrng, biasFactor); return this.valueChainer(src, mrng, clonedMrng, biasFactor); } canShrinkWithoutContext(value) { return false; } shrink(value, context) { if (this.isSafeContext(context)) return (!context.stoppedForOriginal ? this.arb.shrink(context.originalValue, context.originalContext).map((v) => this.valueChainer(v, context.clonedMrng.clone(), context.clonedMrng, context.originalBias)) : Stream.nil()).join(context.chainedArbitrary.shrink(value, context.chainedContext).map((dst) => { const newContext = { ...context, chainedContext: dst.context, stoppedForOriginal: true }; return new Value(dst.value_, newContext); })); return Stream.nil(); } valueChainer(v, generateMrng, clonedMrng, biasFactor) { const chainedArbitrary = this.chainer(v.value_); const dst = chainedArbitrary.generate(generateMrng, biasFactor); const context = { originalBias: biasFactor, originalValue: v.value_, originalContext: v.context, stoppedForOriginal: false, chainedArbitrary, chainedContext: dst.context, clonedMrng }; return new Value(dst.value_, context); } isSafeContext(context) { return context !== null && context !== void 0 && typeof context === "object" && "originalBias" in context && "originalValue" in context && "originalContext" in context && "stoppedForOriginal" in context && "chainedArbitrary" in context && "chainedContext" in context && "clonedMrng" in context; } }; /** @internal */ var MapArbitrary = class extends Arbitrary { constructor(arb, mapper, unmapper) { super(); this.arb = arb; this.mapper = mapper; this.unmapper = unmapper; this.bindValueMapper = (v) => this.valueMapper(v); } generate(mrng, biasFactor) { const g = this.arb.generate(mrng, biasFactor); return this.valueMapper(g); } canShrinkWithoutContext(value) { if (this.unmapper !== void 0) try { const unmapped = this.unmapper(value); return this.arb.canShrinkWithoutContext(unmapped); } catch { return false; } return false; } shrink(value, context) { if (this.isSafeContext(context)) return this.arb.shrink(context.originalValue, context.originalContext).map(this.bindValueMapper); if (this.unmapper !== void 0) { const unmapped = this.unmapper(value); return this.arb.shrink(unmapped, void 0).map(this.bindValueMapper); } return Stream.nil(); } mapperWithCloneIfNeeded(v) { const sourceValue = v.value; const mappedValue = this.mapper(sourceValue); if (v.hasToBeCloned && (typeof mappedValue === "object" && mappedValue !== null || typeof mappedValue === "function") && Object.isExtensible(mappedValue) && !hasCloneMethod(mappedValue)) Object.defineProperty(mappedValue, cloneMethod, { get: () => () => this.mapperWithCloneIfNeeded(v)[0] }); return [mappedValue, sourceValue]; } valueMapper(v) { const [mappedValue, sourceValue] = this.mapperWithCloneIfNeeded(v); return new Value(mappedValue, { originalValue: sourceValue, originalContext: v.context }); } isSafeContext(context) { return context !== null && context !== void 0 && typeof context === "object" && "originalValue" in context && "originalContext" in context; } }; /** @internal */ var FilterArbitrary = class extends Arbitrary { constructor(arb, refinement) { super(); this.arb = arb; this.refinement = refinement; this.bindRefinementOnValue = (v) => this.refinementOnValue(v); } generate(mrng, biasFactor) { while (true) { const g = this.arb.generate(mrng, biasFactor); if (this.refinementOnValue(g)) return g; } } canShrinkWithoutContext(value) { return this.arb.canShrinkWithoutContext(value) && this.refinement(value); } shrink(value, context) { return this.arb.shrink(value, context).filter(this.bindRefinementOnValue); } refinementOnValue(v) { return this.refinement(v.value); } }; /** * Ensure an instance is an instance of Arbitrary * @param instance - The instance to be checked * @internal */ function isArbitrary(instance) { return typeof instance === "object" && instance !== null && "generate" in instance && "shrink" in instance && "canShrinkWithoutContext" in instance; } /** * Ensure an instance is an instance of Arbitrary * @param instance - The instance to be checked * @internal */ function assertIsArbitrary(instance) { if (!isArbitrary(instance)) throw new Error("Unexpected value received: not an instance of Arbitrary"); } //#endregion //#region src/utils/apply.ts const untouchedApply = Function.prototype.apply; const ApplySymbol = Symbol("apply"); /** * Extract apply or return undefined * @param f - Function to extract apply from * @internal */ function safeExtractApply(f) { try { return f.apply; } catch { return; } } /** * Equivalent to `f.apply(instance, args)` but temporary altering the instance * @internal */ function safeApplyHacky(f, instance, args) { const ff = f; ff[ApplySymbol] = untouchedApply; const out = ff[ApplySymbol](instance, args); delete ff[ApplySymbol]; return out; } /** * Equivalent to `f.apply(instance, args)` * @internal */ function safeApply(f, instance, args) { if (safeExtractApply(f) === untouchedApply) return f.apply(instance, args); return safeApplyHacky(f, instance, args); } //#endregion //#region src/utils/globals.ts const SArray = Array; const SBigInt = BigInt; const SBigInt64Array = BigInt64Array; const SBigUint64Array = BigUint64Array; const SBoolean = Boolean; const SDate = Date; const SError = Error; const SFloat32Array = Float32Array; const SFloat64Array = Float64Array; const SInt8Array = Int8Array; const SInt16Array = Int16Array; const SInt32Array = Int32Array; const SNumber = Number; const SString = String; const SSet = Set; const SUint8Array = Uint8Array; const SUint8ClampedArray = Uint8ClampedArray; const SUint16Array = Uint16Array; const SUint32Array = Uint32Array; const SencodeURIComponent = encodeURIComponent; const SMap$1 = Map; const SSymbol = Symbol; const untouchedForEach = Array.prototype.forEach; const untouchedIndexOf = Array.prototype.indexOf; const untouchedJoin = Array.prototype.join; const untouchedMap = Array.prototype.map; const untouchedFlat = Array.prototype.flat; const untouchedFilter = Array.prototype.filter; const untouchedPush = Array.prototype.push; const untouchedPop = Array.prototype.pop; const untouchedSplice = Array.prototype.splice; const untouchedSlice = Array.prototype.slice; const untouchedSort = Array.prototype.sort; const untouchedEvery = Array.prototype.every; function extractForEach(instance) { try { return instance.forEach; } catch { return; } } function extractIndexOf(instance) { try { return instance.indexOf; } catch { return; } } function extractJoin(instance) { try { return instance.join; } catch { return; } } function extractMap(instance) { try { return instance.map; } catch { return; } } function extractFlat(instance) { try { return instance.flat; } catch { return; } } function extractFilter(instance) { try { return instance.filter; } catch { return; } } function extractPush(instance) { try { return instance.push; } catch { return; } } function extractPop(instance) { try { return instance.pop; } catch { return; } } function extractSplice(instance) { try { return instance.splice; } catch { return; } } function extractSlice(instance) { try { return instance.slice; } catch { return; } } function extractSort(instance) { try { return instance.sort; } catch { return; } } function extractEvery(instance) { try { return instance.every; } catch { return; } } function safeForEach(instance, fn) { if (extractForEach(instance) === untouchedForEach) return instance.forEach(fn); return safeApply(untouchedForEach, instance, [fn]); } function safeIndexOf(instance, ...args) { if (extractIndexOf(instance) === untouchedIndexOf) return instance.indexOf(...args); return safeApply(untouchedIndexOf, instance, args); } function safeJoin(instance, ...args) { if (extractJoin(instance) === untouchedJoin) return instance.join(...args); return safeApply(untouchedJoin, instance, args); } function safeMap(instance, fn) { if (extractMap(instance) === untouchedMap) return instance.map(fn); return safeApply(untouchedMap, instance, [fn]); } function safeFlat(instance, depth) { if (extractFlat(instance) === untouchedFlat) { [].flat(); return instance.flat(depth); } return safeApply(untouchedFlat, instance, [depth]); } function safeFilter(instance, predicate) { if (extractFilter(instance) === untouchedFilter) return instance.filter(predicate); return safeApply(untouchedFilter, instance, [predicate]); } function safePush(instance, ...args) { if (extractPush(instance) === untouchedPush) return instance.push(...args); return safeApply(untouchedPush, instance, args); } function safePop$1(instance) { if (extractPop(instance) === untouchedPop) return instance.pop(); return safeApply(untouchedPop, instance, []); } function safeSplice(instance, ...args) { if (extractSplice(instance) === untouchedSplice) return instance.splice(...args); return safeApply(untouchedSplice, instance, args); } function safeSlice(instance, ...args) { if (extractSlice(instance) === untouchedSlice) return instance.slice(...args); return safeApply(untouchedSlice, instance, args); } function safeSort(instance, ...args) { if (extractSort(instance) === untouchedSort) return instance.sort(...args); return safeApply(untouchedSort, instance, args); } function safeEvery(instance, ...args) { if (extractEvery(instance) === untouchedEvery) return instance.every(...args); return safeApply(untouchedEvery, instance, args); } const untouchedGetTime = Date.prototype.getTime; const untouchedToISOString = Date.prototype.toISOString; function extractGetTime(instance) { try { return instance.getTime; } catch { return; } } function extractToISOString(instance) { try { return instance.toISOString; } catch { return; } } function safeGetTime(instance) { if (extractGetTime(instance) === untouchedGetTime) return instance.getTime(); return safeApply(untouchedGetTime, instance, []); } function safeToISOString(instance) { if (extractToISOString(instance) === untouchedToISOString) return instance.toISOString(); return safeApply(untouchedToISOString, instance, []); } const untouchedAdd = Set.prototype.add; const untouchedHas = Set.prototype.has; function extractAdd(instance) { try { return instance.add; } catch { return; } } function extractHas(instance) { try { return instance.has; } catch (err) { return; } } function safeAdd(instance, value) { if (extractAdd(instance) === untouchedAdd) return instance.add(value); return safeApply(untouchedAdd, instance, [value]); } function safeHas(instance, value) { if (extractHas(instance) === untouchedHas) return instance.has(value); return safeApply(untouchedHas, instance, [value]); } const untouchedSet = WeakMap.prototype.set; const untouchedGet = WeakMap.prototype.get; function extractSet(instance) { try { return instance.set; } catch (err) { return; } } function extractGet(instance) { try { return instance.get; } catch (err) { return; } } function safeSet(instance, key, value) { if (extractSet(instance) === untouchedSet) return instance.set(key, value); return safeApply(untouchedSet, instance, [key, value]); } function safeGet(instance, key) { if (extractGet(instance) === untouchedGet) return instance.get(key); return safeApply(untouchedGet, instance, [key]); } const untouchedMapSet = Map.prototype.set; const untouchedMapGet = Map.prototype.get; const untouchedMapHas = Map.prototype.has; function extractMapSet(instance) { try { return instance.set; } catch (err) { return; } } function extractMapGet(instance) { try { return instance.get; } catch (err) { return; } } function extractMapHas(instance) { try { return instance.has; } catch (err) { return; } } function safeMapSet(instance, key, value) { if (extractMapSet(instance) === untouchedMapSet) return instance.set(key, value); return safeApply(untouchedMapSet, instance, [key, value]); } function safeMapGet(instance, key) { if (extractMapGet(instance) === untouchedMapGet) return instance.get(key); return safeApply(untouchedMapGet, instance, [key]); } function safeMapHas(instance, key) { if (extractMapHas(instance) === untouchedMapHas) return instance.has(key); return safeApply(untouchedMapHas, instance, [key]); } const untouchedSplit = String.prototype.split; const untouchedStartsWith = String.prototype.startsWith; const untouchedEndsWith = String.prototype.endsWith; const untouchedSubstring = String.prototype.substring; const untouchedToLowerCase = String.prototype.toLowerCase; const untouchedToUpperCase = String.prototype.toUpperCase; const untouchedPadStart = String.prototype.padStart; const untouchedCharCodeAt = String.prototype.charCodeAt; const untouchedNormalize = String.prototype.normalize; const untouchedReplace = String.prototype.replace; function extractSplit(instance) { try { return instance.split; } catch { return; } } function extractStartsWith(instance) { try { return instance.startsWith; } catch { return; } } function extractEndsWith(instance) { try { return instance.endsWith; } catch { return; } } function extractSubstring(instance) { try { return instance.substring; } catch { return; } } function extractToLowerCase(instance) { try { return instance.toLowerCase; } catch { return; } } function extractToUpperCase(instance) { try { return instance.toUpperCase; } catch { return; } } function extractPadStart(instance) { try { return instance.padStart; } catch { return; } } function extractCharCodeAt(instance) { try { return instance.charCodeAt; } catch { return; } } function extractNormalize(instance) { try { return instance.normalize; } catch (err) { return; } } function extractReplace(instance) { try { return instance.replace; } catch { return; } } function safeSplit(instance, ...args) { if (extractSplit(instance) === untouchedSplit) return instance.split(...args); return safeApply(untouchedSplit, instance, args); } function safeStartsWith(instance, ...args) { if (extractStartsWith(instance) === untouchedStartsWith) return instance.startsWith(...args); return safeApply(untouchedStartsWith, instance, args); } function safeEndsWith(instance, ...args) { if (extractEndsWith(instance) === untouchedEndsWith) return instance.endsWith(...args); return safeApply(untouchedEndsWith, instance, args); } function safeSubstring(instance, ...args) { if (extractSubstring(instance) === untouchedSubstring) return instance.substring(...args); return safeApply(untouchedSubstring, instance, args); } function safeToLowerCase(instance) { if (extractToLowerCase(instance) === untouchedToLowerCase) return instance.toLowerCase(); return safeApply(untouchedToLowerCase, instance, []); } function safeToUpperCase(instance) { if (extractToUpperCase(instance) === untouchedToUpperCase) return instance.toUpperCase(); return safeApply(untouchedToUpperCase, instance, []); } function safePadStart(instance, ...args) { if (extractPadStart(instance) === untouchedPadStart) return instance.padStart(...args); return safeApply(untouchedPadStart, instance, args); } function safeCharCodeAt(instance, index) { if (extractCharCodeAt(instance) === untouchedCharCodeAt) return instance.charCodeAt(index); return safeApply(untouchedCharCodeAt, instance, [index]); } function safeNormalize(instance, form) { if (extractNormalize(instance) === untouchedNormalize) return instance.normalize(form); return safeApply(untouchedNormalize, instance, [form]); } function safeReplace(instance, pattern, replacement) { if (extractReplace(instance) === untouchedReplace) return instance.replace(pattern, replacement); return safeApply(untouchedReplace, instance, [pattern, replacement]); } const untouchedNumberToString = Number.prototype.toString; function extractNumberToString(instance) { try { return instance.toString; } catch { return; } } function safeNumberToString(instance, ...args) { if (extractNumberToString(instance) === untouchedNumberToString) return instance.toString(...args); return safeApply(untouchedNumberToString, instance, args); } const untouchedHasOwnProperty = Object.prototype.hasOwnProperty; const untouchedToString = Object.prototype.toString; function safeHasOwnProperty(instance, v) { return safeApply(untouchedHasOwnProperty, instance, [v]); } function safeToString(instance) { return safeApply(untouchedToString, instance, []); } const untouchedErrorToString = Error.prototype.toString; function safeErrorToString(instance) { return safeApply(untouchedErrorToString, instance, []); } //#endregion //#region src/stream/LazyIterableIterator.ts /** @internal */ var LazyIterableIterator = class { constructor(producer) { this.producer = producer; } [Symbol.iterator]() { if (this.it === void 0) this.it = this.producer(); return this.it; } next() { if (this.it === void 0) this.it = this.producer(); return this.it.next(); } }; /** * Create an IterableIterator based on a function that will only be called once if needed * * @param producer - Function to instanciate the underlying IterableIterator * * @internal */ function makeLazy(producer) { return new LazyIterableIterator(producer); } //#endregion //#region src/arbitrary/_internals/TupleArbitrary.ts const safeArrayIsArray$4 = Array.isArray; const safeObjectDefineProperty$3 = Object.defineProperty; /** @internal */ function tupleMakeItCloneable(vs, values) { return safeObjectDefineProperty$3(vs, cloneMethod, { value: () => { const cloned = []; for (let idx = 0; idx !== values.length; ++idx) safePush(cloned, values[idx].value); tupleMakeItCloneable(cloned, values); return cloned; } }); } /** @internal */ function tupleWrapper(values) { let cloneable = false; const vs = []; const ctxs = []; for (let idx = 0; idx !== values.length; ++idx) { const v = values[idx]; cloneable = cloneable || v.hasToBeCloned; safePush(vs, v.value); safePush(ctxs, v.context); } if (cloneable) tupleMakeItCloneable(vs, values); return new Value(vs, ctxs); } /** @internal */ function tupleShrink(arbs, value, context) { const shrinks = []; const safeContext = safeArrayIsArray$4(context) ? context : []; for (let idx = 0; idx !== arbs.length; ++idx) safePush(shrinks, makeLazy(() => arbs[idx].shrink(value[idx], safeContext[idx]).map((v) => { const nextValues = safeMap(value, (v, idx) => new Value(cloneIfNeeded(v), safeContext[idx])); return [ ...safeSlice(nextValues, 0, idx), v, ...safeSlice(nextValues, idx + 1) ]; }).map(tupleWrapper))); return Stream.nil().join(...shrinks); } /** @internal */ var TupleArbitrary = class extends Arbitrary { constructor(arbs) { super(); this.arbs = arbs; for (let idx = 0; idx !== arbs.length; ++idx) { const arb = arbs[idx]; if (arb === null || arb === void 0 || arb.generate === null || arb.generate === void 0) throw new Error(`Invalid parameter encountered at index ${idx}: expecting an Arbitrary`); } } generate(mrng, biasFactor) { const mapped = []; for (let idx = 0; idx !== this.arbs.length; ++idx) safePush(mapped, this.arbs[idx].generate(mrng, biasFactor)); return tupleWrapper(mapped); } canShrinkWithoutContext(value) { if (!safeArrayIsArray$4(value) || value.length !== this.arbs.length) return false; for (let index = 0; index !== this.arbs.length; ++index) if (!this.arbs[index].canShrinkWithoutContext(value[index])) return false; return true; } shrink(value, context) { return tupleShrink(this.arbs, value, context); } }; //#endregion //#region src/arbitrary/tuple.ts /** * For tuples produced using the provided `arbs` * * @param arbs - Ordered list of arbitraries * * @remarks Since 0.0.1 * @public */ function tuple(...arbs) { return new TupleArbitrary(arbs); } //#endregion //#region src/check/property/IRawProperty.ts const safeMathLog$3 = Math.log; /** * Convert runId (IProperty) into a frequency (Arbitrary) * * @param runId - Id of the run starting at 0 * @returns Frequency of bias starting at 2 * * @internal */ function runIdToFrequency(runId) { return 2 + ~~(safeMathLog$3(runId + 1) * .4342944819032518); } //#endregion //#region src/check/runner/configuration/GlobalParameters.ts /** @internal */ let globalParameters = {}; /** * Define global parameters that will be used by all the runners * * @example * ```typescript * fc.configureGlobal({ numRuns: 10 }); * //... * fc.assert( * fc.property( * fc.nat(), fc.nat(), * (a, b) => a + b === b + a * ), { seed: 42 } * ) // equivalent to { numRuns: 10, seed: 42 } * ``` * * @param parameters - Global parameters * * @remarks Since 1.18.0 * @public */ function configureGlobal(parameters) { globalParameters = parameters; } /** * Read global parameters that will be used by runners * @remarks Since 1.18.0 * @public */ function readConfigureGlobal() { return globalParameters; } /** * Reset global parameters * @remarks Since 1.18.0 * @public */ function resetConfigureGlobal() { globalParameters = {}; } //#endregion //#region src/arbitrary/_internals/helpers/NoUndefinedAsContext.ts /** @internal */ const UndefinedContextPlaceholder = Symbol("UndefinedContextPlaceholder"); /** @internal */ function noUndefinedAsContext(value) { if (value.context !== void 0) return value; if (value.hasToBeCloned) return new Value(value.value_, UndefinedContextPlaceholder, () => value.value); return new Value(value.value_, UndefinedContextPlaceholder); } //#endregion //#region src/check/property/AsyncProperty.generic.ts const dummyHook$1 = () => {}; /** * Asynchronous property, see {@link IAsyncProperty} * * Prefer using {@link asyncProperty} instead * * @internal */ var AsyncProperty = class { constructor(arb, predicate) { this.arb = arb; this.predicate = predicate; const { asyncBeforeEach, asyncAfterEach, beforeEach, afterEach } = readConfigureGlobal() || {}; if (asyncBeforeEach !== void 0 && beforeEach !== void 0) throw SError("Global \"asyncBeforeEach\" and \"beforeEach\" parameters can't be set at the same time when running async properties"); if (asyncAfterEach !== void 0 && afterEach !== void 0) throw SError("Global \"asyncAfterEach\" and \"afterEach\" parameters can't be set at the same time when running async properties"); this.beforeEachHook = asyncBeforeEach || beforeEach || dummyHook$1; this.afterEachHook = asyncAfterEach || afterEach || dummyHook$1; } isAsync() { return true; } generate(mrng, runId) { return noUndefinedAsContext(this.arb.generate(mrng, runId !== void 0 ? runIdToFrequency(runId) : void 0)); } shrink(value) { if (value.context === void 0 && !this.arb.canShrinkWithoutContext(value.value_)) return Stream.nil(); const safeContext = value.context !== UndefinedContextPlaceholder ? value.context : void 0; return this.arb.shrink(value.value_, safeContext).map(noUndefinedAsContext); } async runBeforeEach() { await this.beforeEachHook(); } async runAfterEach() { await this.afterEachHook(); } async run(v) { try { const output = await this.predicate(v); return output === void 0 || output === true ? null : { error: new SError("Property failed by returning false") }; } catch (err) { if (PreconditionFailure.isFailure(err)) return err; return { error: err }; } } /** * Define a function that should be called before all calls to the predicate * @param hookFunction - Function to be called */ beforeEach(hookFunction) { const previousBeforeEachHook = this.beforeEachHook; this.beforeEachHook = () => hookFunction(previousBeforeEachHook); return this; } /** * Define a function that should be called after all calls to the predicate * @param hookFunction - Function to be called */ afterEach(hookFunction) { const previousAfterEachHook = this.afterEachHook; this.afterEachHook = () => hookFunction(previousAfterEachHook); return this; } }; //#endregion //#region src/arbitrary/_internals/AlwaysShrinkableArbitrary.ts /** * Arbitrary considering any value as shrinkable whatever the received context. * In case the context corresponds to nil, it will be checked when calling shrink: * valid would mean stream coming from shrink, otherwise empty stream * @internal */ var AlwaysShrinkableArbitrary = class extends Arbitrary { constructor(arb) { super(); this.arb = arb; } generate(mrng, biasFactor) { return noUndefinedAsContext(this.arb.generate(mrng, biasFactor)); } canShrinkWithoutContext(value) { return true; } shrink(value, context) { if (context === void 0 && !this.arb.canShrinkWithoutContext(value)) return Stream.nil(); const safeContext = context !== UndefinedContextPlaceholder ? context : void 0; return this.arb.shrink(value, safeContext).map(noUndefinedAsContext); } }; //#endregion //#region src/check/property/AsyncProperty.ts /** * Instantiate a new {@link fast-check#IAsyncProperty} * @param predicate - Assess the success of the property. Would be considered falsy if it throws or if its output evaluates to false * @remarks Since 0.0.7 * @public */ function asyncProperty(...args) { if (args.length < 2) throw new Error("asyncProperty expects at least two parameters"); const arbs = safeSlice(args, 0, args.length - 1); const p = args[args.length - 1]; safeForEach(arbs, assertIsArbitrary); return new AsyncProperty(tuple(...safeMap(arbs, (arb) => new AlwaysShrinkableArbitrary(arb))), (t) => p(...t)); } //#endregion //#region src/check/property/Property.generic.ts const dummyHook = () => {}; /** * Property, see {@link IProperty} * * Prefer using {@link property} instead * * @internal */ var Property = class { constructor(arb, predicate) { this.arb = arb; this.predicate = predicate; const { beforeEach = dummyHook, afterEach = dummyHook, asyncBeforeEach, asyncAfterEach } = readConfigureGlobal() || {}; if (asyncBeforeEach !== void 0) throw SError("\"asyncBeforeEach\" can't be set when running synchronous properties"); if (asyncAfterEach !== void 0) throw SError("\"asyncAfterEach\" can't be set when running synchronous properties"); this.beforeEachHook = beforeEach; this.afterEachHook = afterEach; } isAsync() { return false; } generate(mrng, runId) { return noUndefinedAsContext(this.arb.generate(mrng, runId !== void 0 ? runIdToFrequency(runId) : void 0)); } shrink(value) { if (value.context === void 0 && !this.arb.canShrinkWithoutContext(value.value_)) return Stream.nil(); const safeContext = value.context !== UndefinedContextPlaceholder ? value.context : void 0; return this.arb.shrink(value.value_, safeContext).map(noUndefinedAsContext); } runBeforeEach() { this.beforeEachHook(); } runAfterEach() { this.afterEachHook(); } run(v) { try { const output = this.predicate(v); return output === void 0 || output === true ? null : { error: new SError("Property failed by returning false") }; } catch (err) { if (PreconditionFailure.isFailure(err)) return err; return { error: err }; } } beforeEach(hookFunction) { const previousBeforeEachHook = this.beforeEachHook; this.beforeEachHook = () => hookFunction(previousBeforeEachHook); return this; } afterEach(hookFunction) { const previousAfterEachHook = this.afterEachHook; this.afterEachHook = () => hookFunction(previousAfterEachHook); return this; } }; //#endregion //#region src/check/property/Property.ts /** * Instantiate a new {@link fast-check#IProperty} * @param predicate - Assess the success of the property. Would be considered falsy if it throws or if its output evaluates to false * @remarks Since 0.0.1 * @public */ function property(...args) { if (args.length < 2) throw new Error("property expects at least two parameters"); const arbs = safeSlice(args, 0, args.length - 1); const p = args[args.length - 1]; safeForEach(arbs, assertIsArbitrary); return new Property(tuple(...safeMap(arbs, (arb) => new AlwaysShrinkableArbitrary(arb))), (t) => p(...t)); } //#endregion //#region src/check/runner/configuration/VerbosityLevel.ts /** * Verbosity level * @remarks Since 1.9.1 * @public */ let VerbosityLevel = /* @__PURE__ */ function(VerbosityLevel) { /** * Level 0 (default) * * Minimal reporting: * - minimal failing case * - error log corresponding to the minimal failing case * * @remarks Since 1.9.1 */ VerbosityLevel[VerbosityLevel["None"] = 0] = "None"; /** * Level 1 * * Failures reporting: * - same as `VerbosityLevel.None` * - list all the failures encountered during the shrinking process * * @remarks Since 1.9.1 */ VerbosityLevel[VerbosityLevel["Verbose"] = 1] = "Verbose"; /** * Level 2 * * Execution flow reporting: * - same as `VerbosityLevel.None` * - all runs with their associated status displayed as a tree * * @remarks Since 1.9.1 */ VerbosityLevel[VerbosityLevel["VeryVerbose"] = 2] = "VeryVerbose"; return VerbosityLevel; }({}); //#endregion //#region src/random/generator/RandomGenerator.ts /** @internal */ function adaptRandomGeneratorTo8x(rng) { if ("unsafeNext" in rng) { if (rng.unsafeJump === void 0) return { clone: () => adaptRandomGeneratorTo8x(rng), next: () => rng.unsafeNext(), getState: () => rng.getState() }; return { clone: () => adaptRandomGeneratorTo8x(rng), next: () => rng.unsafeNext(), jump: () => rng.unsafeJump(), getState: () => rng.getState() }; } return rng; } /** @internal */ function adaptRandomGeneratorToInternal(rng) { if ("jump" in rng && typeof rng.jump === "function") return rng; return { clone: () => adaptRandomGeneratorToInternal(rng), next: () => rng.next(), jump: () => skipN(rng, 42), getState: () => rng.getState() }; } /** @internal */ function adaptRandomGenerator(rng) { return adaptRandomGeneratorToInternal(adaptRandomGeneratorTo8x(rng)); } //#endregion //#region src/check/runner/configuration/QualifiedParameters.ts const safeDateNow$1 = Date.now; const safeMathMin$6 = Math.min; const safeMathRandom = Math.random; /** * Configuration extracted from incoming Parameters * * It handles and set the default settings that will be used by runners. * * @internal */ var QualifiedParameters = class { constructor(op) { const p = op || {}; this.seed = readSeed(p); this.randomType = readRandomType(p); this.numRuns = readNumRuns(p); this.verbose = readVerbose(p); this.maxSkipsPerRun = p.maxSkipsPerRun !== void 0 ? p.maxSkipsPerRun : 100; this.timeout = safeTimeout(p.timeout); this.skipAllAfterTimeLimit = safeTimeout(p.skipAllAfterTimeLimit); this.interruptAfterTimeLimit = safeTimeout(p.interruptAfterTimeLimit); this.markInterruptAsFailure = p.markInterruptAsFailure === true; this.skipEqualValues = p.skipEqualValues === true; this.ignoreEqualValues = p.ignoreEqualValues === true; this.logger = p.logger !== void 0 ? p.logger : (v) => { console.log(v); }; this.path = p.path !== void 0 ? p.path : ""; this.unbiased = p.unbiased === true; this.examples = p.examples !== void 0 ? p.examples : []; this.endOnFailure = p.endOnFailure === true; this.reporter = p.reporter; this.asyncReporter = p.asyncReporter; this.includeErrorInReport = p.includeErrorInReport === true; } toParameters() { return { seed: this.seed, randomType: this.randomType, numRuns: this.numRuns, maxSkipsPerRun: this.maxSkipsPerRun, timeout: this.timeout, skipAllAfterTimeLimit: this.skipAllAfterTimeLimit, interruptAfterTimeLimit: this.interruptAfterTimeLimit, markInterruptAsFailure: this.markInterruptAsFailure, skipEqualValues: this.skipEqualValues, ignoreEqualValues: this.ignoreEqualValues, path: this.path, logger: this.logger, unbiased: this.unbiased, verbose: this.verbose, examples: this.examples, endOnFailure: this.endOnFailure, reporter: this.reporter, asyncReporter: this.asyncReporter, includeErrorInReport: this.includeErrorInReport }; } }; /** @internal */ function createQualifiedRandomGenerator(random) { return (seed) => { return adaptRandomGenerator(random(seed)); }; } /** @internal */ function readSeed(p) { if (p.seed === void 0) return safeDateNow$1() ^ safeMathRandom() * 4294967296; const seed32 = p.seed | 0; if (p.seed === seed32) return seed32; return seed32 ^ (p.seed - seed32) * 4294967296; } /** @internal */ function readRandomType(p) { if (p.randomType === void 0) return xorshift128plus; if (typeof p.randomType === "string") switch (p.randomType) { case "mersenne": return createQualifiedRandomGenerator(mersenne); case "congruential": case "congruential32": return createQualifiedRandomGenerator(congruential32); case "xorshift128plus": return xorshift128plus; case "xoroshiro128plus": return xoroshiro128plus; default: throw new Error(`Invalid random specified: '${p.randomType}'`); } const mrng = p.randomType(0); if ("min" in mrng && mrng.min !== -2147483648) throw new Error(`Invalid random number generator: min must equal -0x80000000, got ${String(mrng.min)}`); if ("max" in mrng && mrng.max !== 2147483647) throw new Error(`Invalid random number generator: max must equal 0x7fffffff, got ${String(mrng.max)}`); if (mrng === adaptRandomGenerator(mrng)) return p.randomType; return createQualifiedRandomGenerator(p.randomType); } /** @internal */ function readNumRuns(p) { const defaultValue = 100; if (p.numRuns !== void 0) return p.numRuns; if (p.num_runs !== void 0) return p.num_runs; return defaultValue; } /** @internal */ function readVerbose(p) { if (p.verbose === void 0) return VerbosityLevel.None; if (typeof p.verbose === "boolean") return p.verbose === true ? VerbosityLevel.Verbose : VerbosityLevel.None; if (p.verbose <= VerbosityLevel.None) return VerbosityLevel.None; if (p.verbose >= VerbosityLevel.VeryVerbose) return VerbosityLevel.VeryVerbose; return p.verbose | 0; } /** @internal */ function safeTimeout(value) { if (value === void 0) return; return safeMathMin$6(value, 2147483647); } /** * Extract a runner configuration from Parameters * @param p - Incoming Parameters */ function read(op) { return new QualifiedParameters(op); } //#endregion //#region src/check/property/SkipAfterProperty.ts /** @internal */ function interruptAfter(timeMs, setTimeoutSafe, clearTimeoutSafe) { let timeoutHandle = null; return { clear: () => clearTimeoutSafe(timeoutHandle), promise: new Promise((resolve) => { timeoutHandle = setTimeoutSafe(() => { resolve(new PreconditionFailure(true)); }, timeMs); }) }; } /** @internal */ var SkipAfterProperty = class { constructor(property, getTime, timeLimit, interruptExecution, setTimeoutSafe, clearTimeoutSafe) { this.property = property; this.getTime = getTime; this.interruptExecution = interruptExecution; this.setTimeoutSafe = setTimeoutSafe; this.clearTimeoutSafe = clearTimeoutSafe; this.skipAfterTime = this.getTime() + timeLimit; } isAsync() { return this.property.isAsync(); } generate(mrng, runId) { return this.property.generate(mrng, runId); } shrink(value) { return this.property.shrink(value); } run(v) { const remainingTime = this.skipAfterTime - this.getTime(); if (remainingTime <= 0) { const preconditionFailure = new PreconditionFailure(this.interruptExecution); if (this.isAsync()) return Promise.resolve(preconditionFailure); else return preconditionFailure; } if (this.interruptExecution && this.isAsync()) { const t = interruptAfter(remainingTime, this.setTimeoutSafe, this.clearTimeoutSafe); const propRun = Promise.race([this.property.run(v), t.promise]); propRun.then(t.clear, t.clear); return propRun; } return this.property.run(v); } runBeforeEach() { return this.property.runBeforeEach(); } runAfterEach() { return this.property.runAfterEach(); } }; //#endregion //#region src/check/property/TimeoutProperty.ts /** @internal */ const timeoutAfter = (timeMs, setTimeoutSafe, clearTimeoutSafe) => { let timeoutHandle = null; return { clear: () => clearTimeoutSafe(timeoutHandle), promise: new Promise((resolve) => { timeoutHandle = setTimeoutSafe(() => { resolve({ error: new SError(`Property timeout: exceeded limit of ${timeMs} milliseconds`) }); }, timeMs); }) }; }; /** @internal */ var TimeoutProperty = class { constructor(property, timeMs, setTimeoutSafe, clearTimeoutSafe) { this.property = property; this.timeMs = timeMs; this.setTimeoutSafe = setTimeoutSafe; this.clearTimeoutSafe = clearTimeoutSafe; } isAsync() { return true; } generate(mrng, runId) { return this.property.generate(mrng, runId); } shrink(value) { return this.property.shrink(value); } async run(v) { const t = timeoutAfter(this.timeMs, this.setTimeoutSafe, this.clearTimeoutSafe); const propRun = Promise.race([this.property.run(v), t.promise]); propRun.then(t.clear, t.clear); return propRun; } runBeforeEach() { return Promise.resolve(this.property.runBeforeEach()); } runAfterEach() { return Promise.resolve(this.property.runAfterEach()); } }; //#endregion //#region src/check/property/UnbiasedProperty.ts /** @internal */ var UnbiasedProperty = class { constructor(property) { this.property = property; } isAsync() { return this.property.isAsync(); } generate(mrng, _runId) { return this.property.generate(mrng, void 0); } shrink(value) { return this.property.shrink(value); } run(v) { return this.property.run(v); } runBeforeEach() { return this.property.runBeforeEach(); } runAfterEach() { return this.property.runAfterEach(); } }; //#endregion //#region src/utils/stringify.ts const safeArrayFrom = Array.from; const safeBufferIsBuffer = typeof Buffer !== "undefined" ? Buffer.isBuffer : void 0; const safeJsonStringify$1 = JSON.stringify; const safeNumberIsNaN$5 = Number.isNaN; const safeObjectKeys$5 = Object.keys; const safeObjectGetOwnPropertySymbols$2 = Object.getOwnPropertySymbols; const safeObjectGetOwnPropertyDescriptor$3 = Object.getOwnPropertyDescriptor; const safeObjectGetPrototypeOf$2 = Object.getPrototypeOf; const safeNegativeInfinity$7 = Number.NEGATIVE_INFINITY; const safePositiveInfinity$8 = Number.POSITIVE_INFINITY; /** * Use this symbol to define a custom serializer for your instances. * Serializer must be a function returning a string (see {@link WithToStringMethod}). * * @remarks Since 2.17.0 * @public */ const toStringMethod = Symbol.for("fast-check/toStringMethod"); /** * Check if an instance implements {@link WithToStringMethod} * * @remarks Since 2.17.0 * @public */ function hasToStringMethod(instance) { return instance !== null && (typeof instance === "object" || typeof instance === "function") && toStringMethod in instance && typeof instance[toStringMethod] === "function"; } /** * Use this symbol to define a custom serializer for your instances. * Serializer must be a function returning a promise of string (see {@link WithAsyncToStringMethod}). * * Please note that: * 1. It will only be useful for asynchronous properties. * 2. It has to return barely instantly. * * @remarks Since 2.17.0 * @public */ const asyncToStringMethod = Symbol.for("fast-check/asyncToStringMethod"); /** * Check if an instance implements {@link WithAsyncToStringMethod} * * @remarks Since 2.17.0 * @public */ function hasAsyncToStringMethod(instance) { return instance !== null && (typeof instance === "object" || typeof instance === "function") && asyncToStringMethod in instance && typeof instance[asyncToStringMethod] === "function"; } /** @internal */ const findSymbolNameRegex =