UNPKG

fast-check

Version:

Property based testing framework for JavaScript (like QuickCheck)

72 lines (71 loc) 3.57 kB
import { Stream } from '../../stream/Stream.js'; import { Arbitrary } from './definition/Arbitrary.js'; import { biasWrapper } from './definition/BiasedArbitraryWrapper.js'; import { Shrinkable } from './definition/Shrinkable.js'; import { integer } from './IntegerArbitrary.js'; import { makeLazy } from '../../stream/LazyIterableIterator.js'; class SubarrayArbitrary extends Arbitrary { constructor(originalArray, isOrdered, minLength, maxLength) { super(); this.originalArray = originalArray; this.isOrdered = isOrdered; this.minLength = minLength; this.maxLength = maxLength; if (minLength < 0 || minLength > originalArray.length) throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be between 0 and the size of the original array'); if (maxLength < 0 || maxLength > originalArray.length) throw new Error('fc.*{s|S}ubarrayOf expects the maximal length to be between 0 and the size of the original array'); if (minLength > maxLength) throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be inferior or equal to the maximal length'); this.lengthArb = integer(minLength, maxLength); } wrapper(items, shrunkOnce) { return new Shrinkable(items, () => this.shrinkImpl(items, shrunkOnce).map((v) => this.wrapper(v, true))); } generate(mrng) { const remainingElements = this.originalArray.map((v, idx) => idx); const size = this.lengthArb.generate(mrng).value; const ids = []; for (let idx = 0; idx !== size; ++idx) { const selectedIdIndex = mrng.nextInt(0, remainingElements.length - 1); ids.push(remainingElements[selectedIdIndex]); remainingElements.splice(selectedIdIndex, 1); } if (this.isOrdered) ids.sort((a, b) => a - b); return this.wrapper(ids.map((i) => this.originalArray[i]), false); } shrinkImpl(items, shrunkOnce) { if (items.length === 0) { return Stream.nil(); } const size = this.lengthArb.shrinkableFor(items.length, shrunkOnce); return size .shrink() .map((l) => items.slice(items.length - l.value)) .join(items.length > this.minLength ? makeLazy(() => this.shrinkImpl(items.slice(1), false) .filter((vs) => this.minLength <= vs.length + 1) .map((vs) => [items[0]].concat(vs))) : Stream.nil()); } withBias(freq) { return this.minLength !== this.maxLength ? biasWrapper(freq, this, (originalArbitrary) => { return new SubarrayArbitrary(originalArbitrary.originalArray, originalArbitrary.isOrdered, originalArbitrary.minLength, originalArbitrary.minLength + Math.floor(Math.log(originalArbitrary.maxLength - originalArbitrary.minLength) / Math.log(2))); }) : this; } } function subarray(originalArray, minLength, maxLength) { if (minLength != null && maxLength != null) return new SubarrayArbitrary(originalArray, true, minLength, maxLength); return new SubarrayArbitrary(originalArray, true, 0, originalArray.length); } function shuffledSubarray(originalArray, minLength, maxLength) { if (minLength != null && maxLength != null) return new SubarrayArbitrary(originalArray, false, minLength, maxLength); return new SubarrayArbitrary(originalArray, false, 0, originalArray.length); } export { subarray, shuffledSubarray };