/** * @fileoverview An opinionated wrapper around eslint-fuzzer * @author Teddy Katz */ "use strict"; //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ const ProgressBar = require("progress"); const fuzz = require("./eslint-fuzzer"); const eslint = require(".."); const linter = new eslint.Linter(); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ // An estimate of how many times faster it is to do a crash-only fuzzer run versus an autofixing run. const ESTIMATED_CRASH_AUTOFIX_PERFORMANCE_RATIO = 4; // The number of crash-only tests to run for each autofix test. Right now, this is mostly arbitrary. const CRASH_AUTOFIX_TEST_COUNT_RATIO = 3; //------------------------------------------------------------------------------ // Public API //------------------------------------------------------------------------------ /** * Runs the fuzzer and outputs a progress bar * @param {Object} [options] Options for the fuzzer * @param {number} [options.amount=300] A positive integer indicating how much testing to do. Larger values result in a higher * chance of finding bugs, but cause the testing to take longer (linear increase). With the default value, the fuzzer * takes about 15 seconds to run. * @param {boolean} [options.fuzzBrokenAutofixes=true] true if the fuzzer should look for invalid autofixes in addition to rule crashes * @returns {Object[]} A list of objects, where each object represents a problem detected by the fuzzer. The objects have the same * schema as objects returned from eslint-fuzzer. */ function run({ amount = 300, fuzzBrokenAutofixes = true } = {}) { const crashTestCount = amount * CRASH_AUTOFIX_TEST_COUNT_RATIO; const autofixTestCount = fuzzBrokenAutofixes ? amount : 0; /* * To keep the progress bar moving at a roughly constant speed, apply a different weight for finishing * a crash-only fuzzer run versus an autofix fuzzer run. */ const progressBar = new ProgressBar( "Fuzzing rules [:bar] :percent, :elapseds elapsed, eta :etas, errors so far: :elapsedErrors", { width: 30, total: crashTestCount + autofixTestCount * ESTIMATED_CRASH_AUTOFIX_PERFORMANCE_RATIO } ); // Start displaying the progress bar. progressBar.tick(0, { elapsedErrors: 0 }); const crashTestResults = fuzz({ linter, count: crashTestCount, checkAutofixes: false, progressCallback(elapsedErrors) { progressBar.tick(1, { elapsedErrors }); progressBar.render(); } }); const autofixTestResults = fuzz({ linter, count: autofixTestCount, checkAutofixes: true, progressCallback(elapsedErrors) { progressBar.tick(ESTIMATED_CRASH_AUTOFIX_PERFORMANCE_RATIO, { elapsedErrors: crashTestResults.length + elapsedErrors }); progressBar.render(); } }); return crashTestResults.concat(autofixTestResults); } module.exports = { run };