@firfi/quint-connect
Version:
Model-based testing framework connecting Quint specifications to TypeScript implementations
44 lines • 2.74 kB
JavaScript
import { Effect, Schema } from "effect";
import { QuintError } from "./errors.js";
import { DEFAULT_MAX_SAMPLES, DEFAULT_MAX_STEPS, DEFAULT_N_TRACES } from "./run-options.js";
const RANDOM_SEED_HEX_LENGTH = 16;
const HEX_RADIX = 16;
const MIN_EVALUATOR_THREADS = 2;
const CompiledEvaluatorRuntime = Schema.Struct({
nruns: Schema.optional(Schema.Number),
nsteps: Schema.optional(Schema.Number),
ntraces: Schema.optional(Schema.Number),
nthreads: Schema.optional(Schema.Number)
});
export const decodeCompiledEvaluatorInput = (input) => Schema.decodeUnknown(Schema.String)(input).pipe(Effect.mapError((error) => new QuintError({ message: `Invalid compiled evaluator input: ${error}` })), Effect.flatMap((source) => source.trimStart().startsWith("{")
? Schema.decodeUnknown(Schema.parseJson(CompiledEvaluatorRuntime))(source).pipe(Effect.mapError((error) => new QuintError({ message: `Invalid compiled evaluator input: ${error}` })), Effect.map((runtime) => ({ source, runtime })))
: Effect.succeed({ source, runtime: {} })));
const parseSeed = BigInt;
export const makeRandomSeedHex = () => Array.from({ length: RANDOM_SEED_HEX_LENGTH }, () => Math.floor(Math.random() * HEX_RADIX).toString(HEX_RADIX)).join("");
export const patchCompiledEvaluatorInput = (compiledInput, opts, cpuCount, randomSeedHex) => {
const nTraces = opts.nTraces ?? DEFAULT_N_TRACES;
const maxSamples = opts.maxSamples ?? DEFAULT_MAX_SAMPLES;
const maxSteps = opts.maxSteps ?? DEFAULT_MAX_STEPS;
const nThreads = Math.max(MIN_EVALUATOR_THREADS, Math.min(maxSamples, cpuCount));
let patchedInput = compiledInput.source;
if (compiledInput.runtime.nruns !== undefined) {
patchedInput = patchedInput.replace(/"nruns":\s*\d+/, `"nruns":${maxSamples}`);
}
if (compiledInput.runtime.nsteps !== undefined) {
patchedInput = patchedInput.replace(/"nsteps":\s*\d+/, `"nsteps":${maxSteps}`);
}
if (compiledInput.runtime.ntraces !== undefined) {
patchedInput = patchedInput.replace(/"ntraces":\s*\d+/, `"ntraces":${nTraces}`);
}
if (compiledInput.runtime.nthreads !== undefined) {
patchedInput = patchedInput.replace(/"nthreads":\s*\d+/, `"nthreads":${nThreads}`);
}
const seedBigint = opts.seed !== undefined ? parseSeed(opts.seed) : BigInt(`0x${randomSeedHex}`);
const seedHex = `0x${seedBigint.toString(HEX_RADIX)}`;
const seedReplaced = patchedInput.replace(/"seed":\s*(?:null|undefined|\d+)/, `"seed":${seedBigint}`);
patchedInput = seedReplaced === patchedInput
? patchedInput.replace(/}\s*$/, `,"seed":${seedBigint}}`)
: seedReplaced;
return { input: patchedInput, seedHex };
};
//# sourceMappingURL=compiled-evaluator-input.js.map