UNPKG

fast-check

Version:

Property based testing framework for JavaScript (like QuickCheck)

92 lines (91 loc) 3.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mixedCase = exports.computeNextFlags = exports.countToggledBits = void 0; const BigIntArbitrary_1 = require("./BigIntArbitrary"); const Arbitrary_1 = require("./definition/Arbitrary"); const Shrinkable_1 = require("./definition/Shrinkable"); function countToggledBits(n) { let count = 0; while (n > BigInt(0)) { if (n & BigInt(1)) ++count; n >>= BigInt(1); } return count; } exports.countToggledBits = countToggledBits; function computeNextFlags(flags, nextSize) { const allowedMask = (BigInt(1) << BigInt(nextSize)) - BigInt(1); const preservedFlags = flags & allowedMask; let numMissingFlags = countToggledBits(flags - preservedFlags); let nFlags = preservedFlags; for (let mask = BigInt(1); mask <= allowedMask && numMissingFlags !== 0; mask <<= BigInt(1)) { if (!(nFlags & mask)) { nFlags |= mask; --numMissingFlags; } } return nFlags; } exports.computeNextFlags = computeNextFlags; class MixedCaseArbitrary extends Arbitrary_1.Arbitrary { constructor(stringArb, toggleCase) { super(); this.stringArb = stringArb; this.toggleCase = toggleCase; } computeTogglePositions(chars) { const positions = []; for (let idx = 0; idx !== chars.length; ++idx) { if (this.toggleCase(chars[idx]) !== chars[idx]) positions.push(idx); } return positions; } wrapper(rawCase, chars, togglePositions, flags) { const newChars = chars.slice(); for (let idx = 0, mask = BigInt(1); idx !== togglePositions.length; ++idx, mask <<= BigInt(1)) { if (flags & mask) newChars[togglePositions[idx]] = this.toggleCase(newChars[togglePositions[idx]]); } return new Shrinkable_1.Shrinkable(newChars.join(''), () => this.shrinkImpl(rawCase, chars, togglePositions, flags)); } shrinkImpl(rawCase, chars, togglePositions, flags) { return rawCase .shrink() .map((s) => { const nChars = [...s.value_]; const nTogglePositions = this.computeTogglePositions(nChars); const nFlags = computeNextFlags(flags, nTogglePositions.length); return this.wrapper(s, nChars, nTogglePositions, nFlags); }) .join(BigIntArbitrary_1.bigUintN(togglePositions.length) .shrinkableFor(flags) .shrink() .map((nFlags) => { return this.wrapper(new Shrinkable_1.Shrinkable(rawCase.value), chars, togglePositions, nFlags.value_); })); } generate(mrng) { const rawCaseShrinkable = this.stringArb.generate(mrng); const chars = [...rawCaseShrinkable.value_]; const togglePositions = this.computeTogglePositions(chars); const flagsArb = BigIntArbitrary_1.bigUintN(togglePositions.length); const flags = flagsArb.generate(mrng).value_; return this.wrapper(rawCaseShrinkable, chars, togglePositions, flags); } } function defaultToggleCase(rawChar) { const upper = rawChar.toUpperCase(); if (upper !== rawChar) return upper; return rawChar.toLowerCase(); } function mixedCase(stringArb, constraints) { if (typeof BigInt === 'undefined') { throw new Error(`mixedCase requires BigInt support`); } const toggleCase = (constraints && constraints.toggleCase) || defaultToggleCase; return new MixedCaseArbitrary(stringArb, toggleCase); } exports.mixedCase = mixedCase;