Home

Awesome

eslump Build Status

Fuzz testing JavaScript parsers and suchlike programs.

es : short for ECMAScript (the JavaScript standard)
lump : a piece or mass of indefinite size and shape
slump : the Swedish word for “chance”

Inspired by esfuzz. Powered by shift-fuzzer and shift-codegen.

Contents

<!-- prettier-ignore-start --> <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- prettier-ignore-end -->

Installation

eslump is primarily intended to be used as a CLI tool.

npm install --global eslump

You can also use parts of it as a Node.js module.

npm install eslump

CLI

<details> <summary><code>eslump --help</code></summary>
Usage: eslump [options]
   or: eslump TEST_FILE OUTPUT_DIR [options]

Options:

  --max-depth Number    The maximum depth of the random JavaScript. - default: 7
  --source-type String  Parsing mode. - either: module or script - default: module
  --whitespace          Randomize the whitespace in the random JavaScript.
  --comments            Insert random comments into the random JavaScript.
  -r, --reproduce       Reproduce a previous error using files in OUTPUT_DIR.
  -h, --help            Show help
  -v, --version         Show version

When no arguments are provided, random JavaScript is printed to stdout.
Otherwise, TEST_FILE is executed until an error occurs, or you kill the
program. When an error occurs, the error is printed to stdout and files
are written to OUTPUT_DIR:

  - random.js contains the random JavaScript that caused the error.
  - random.backup.js is a backup of random.js.
  - reproductionData.json contains additional data defined by TEST_FILE
    needed to reproduce the error caused by random.js, if any.
  - Other files, if any, are defined by TEST_FILE.

OUTPUT_DIR is created as with `mkdir -p` if non-existent.

For information on how to write a TEST_FILE, see:
https://github.com/lydell/eslump#test-files

Examples:

  # See how "prettier" pretty-prints random JavaScript.
  $ eslump | prettier --parser babel

  # Run test.js and save the results in output/.
  $ eslump test.js output/

  # Narrow down the needed JavaScript to produce the error.
  # output/random.backup.js is handy if you go too far.
  $ vim output/random.js

  # Reproduce the narrowed down case.
  $ eslump test.js output/ --reproduce
</details>

Module

const { generateRandomJS } = require("eslump");

const randomJSString = generateRandomJS({
  sourceType: "module",
  maxDepth: 7,
  comments: false,
  whitespace: false,
});

generateRandomJS(options = {})

Returns a string of random JavaScript code.

If you want, you can pass some options:

OptionTypeDefaultDescription
sourceType"module" or "script""module"The type of code to generate.
maxDepthinteger7How deeply nested AST:s to generate.
commentsbooleanfalseWhether or not to generate random comments.
whitespacebooleanfalseWhether or not to generate random whitespace.

Disclaimer

eslump was created from the need of finding edge cases in Prettier. It started out as a bare-bones little script in a branch on my fork of that repo. As I wanted more and more features, I extracted it and fleshed it out in its own repo. Then I realized that it might be useful to others, so I put it on GitHub and made the CLI installable from npm.

Initially, eslump basically just strung together shift-fuzzer and shift-codegen. Then, I realized that no random comments were generated, so I hacked that in (along with random whitespace) since comments are very difficult to get right in Prettier. Then, random parentheses and semicolons where requested, so I hacked that in as well.

eslump has successfully found lots of little edge cases in Prettier, so it evidently works. But there aren’t many tests. (I’ve mostly gone meta and fuzz-tested it using itself basically.)

From the beginning eslump was only ever intended to be a CLI tool, but other people have started to want to use eslump’s code generation as an npm module, so these days it can also be used as a module. If you know what you’re doing.

Here are some features I’d like to see from a proper random JS library:

Examples

There are several examples in the examples directory.

To run the Acorn example, for instance, follow these steps:

  1. Clone this repository.
  2. npm ci
  3. eslump examples/acorn.js output

Test files

$ eslump test.js output/

Test files, test.js in the above example, must follow this pattern:

module.exports = ({
  code, // String.
  sourceType, // String, either "module" or "script".
  reproductionData = {}, // undefined or anything that `JSON.parse` can return.
}) => {
  if (testFailedSomehow) {
    return {
      error, // Caught Error object.
      reproductionData, // Optional. Anything that `JSON.stringify` can handle.
      artifacts, // Optional. Object mapping file names to string contents.
    };
  }
  // If the test passed, return nothing.
};

License

MIT.