Skip to content

Commit c981309

Browse files
committed
Add Jest integration documentation
1 parent 9b92f75 commit c981309

File tree

8 files changed

+548
-130
lines changed

8 files changed

+548
-130
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Jazzer.js has the following dependencies when built from source:
66

7-
- [Node.js 14](https://nodejs.org/)
7+
- [Node.js 16](https://nodejs.org/)
88
- [NPM 7.0](https://www.npmjs.com/)
99
- [cmake-js](https://github.com/cmake-js/cmake-js) dependencies
1010
- [CMake](https://cmake.org/download/) version 3.10 or later
@@ -26,20 +26,22 @@ and building libFuzzer via `cmake-js`.
2626

2727
## Test
2828

29-
All tests can be executed via the `test:all` npm script in the root directory.
29+
All tests can be executed via the `test` npm script in the root directory.
30+
Please make sure that you build the newest version with the commands mentioned
31+
above.
3032

3133
```shell
3234
npm run test
3335
```
3436

3537
This executes all [Jest](https://jestjs.io/) unit tests and also all `test`
36-
scripts in the workspaces.
38+
scripts in the workspaces, plus a `dryRun` of all example projects.
3739

3840
**Note**: Please make sure to provide test cases for all code changes.
3941

4042
## Format and lint
4143

42-
All code and documentation has to satisfy the format and linting rules. This is
44+
All code and documentation have to satisfy format and linting rules. This is
4345
enforced through a git pre-commit hook. The `check` npm script in the root
4446
directory runs the appropriate checks.
4547

README.md

Lines changed: 36 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Jazzer.js currently supports the following platforms:
4444

4545
To use Jazzer.js in your own project follow these few simple steps:
4646

47-
1. Add the `@jazzer.js/core` dev-dependency
47+
1. Add the `@jazzer.js/core` `dev-dependency`
4848

4949
```shell
5050
npm install --save-dev @jazzer.js/core
@@ -76,152 +76,62 @@ To use Jazzer.js in your own project follow these few simple steps:
7676

7777
## Usage
7878

79-
### Creating a fuzz target
79+
Jazzer.js can be used in two ways: Creating dedicated fuzz targets, as shown in
80+
the `Quickstart` section, or integrated into the Jest test framework.
8081

81-
Jazzer.js requires an entry point for the fuzzer, this is commonly referred to
82-
as fuzz target. A simple example is shown below.
82+
### Using test framework integration
8383

84-
```js
85-
module.exports.fuzz = function (data) {
86-
myAwesomeCode(data.toString());
87-
};
88-
```
89-
90-
A fuzz target module needs to export a function called `fuzz`, which takes a
91-
`Buffer` parameter and executes the actual code under test.
92-
93-
The `Buffer`, a subclass of `Uint8Array`, can be used to create needed
94-
parameters for the actual code under test, so that the fuzzer can detect the
95-
usage of parts of the input and mutate them in the next iterations to reach new
96-
code paths. However, `Buffer` is not the nicest abstraction to work with. For
97-
that reason, Jazzer.js provides a wrapper class `FuzzedDataProvider` that allows
98-
reading primitive types from the `Buffer`. An example on how to use the `data`
99-
and the `FuzzedDataProvider` class is shown below.
100-
101-
```js
102-
const { FuzzedDataProvider } = require("@jazzer.js/core");
103-
104-
module.exports.fuzz = function (fuzzerInputData) {
105-
const data = new FuzzedDataProvider(fuzzerInputData);
106-
const intParam = data.consumeIntegral(4);
107-
const stringParam = data.consumeString(4, "utf-8");
108-
myAwesomeCode(intParam, stringParam);
109-
};
110-
```
111-
112-
For more information on how to use the `FuzzedDataProvider` class, please refer
113-
to the [example](./examples/FuzzedDataProvider/fuzz.js), the
114-
[documentation](./packages/core/FuzzedDataProvider.ts) of the
115-
`FuzzedDataProvider` class, and the
116-
[tests](./packages/core/FuzzedDataProvider.test.ts).
117-
118-
#### Asynchronous fuzz targets
119-
120-
Jazzer.js supports asynchronous fuzz targets out of the box, no special handling
121-
or configuration is needed.
122-
123-
The resolution of a `Promise` returned by a fuzz target is awaited before the
124-
next fuzzing input is provided. This enables the fuzzing of `async`/`await`,
125-
`Promise` and callback based code.
126-
127-
Asynchronous code needs careful synchronization between the
128-
[Node.js Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)
129-
and the fuzzing thread, hence provides a lower throughput compared to
130-
synchronous fuzzing. Even so, asynchronous fuzzing is the default mode of
131-
Jazzer.js due to its prevalence in the JavaScript ecosystem and because it works
132-
for all fuzz targets.
133-
134-
Solely synchronous code can participate in the enhanced performance of
135-
synchronous fuzzing by setting the `--sync` flag when starting the fuzzer.
84+
To use fuzzing in your normal development workflow a tight integration with the
85+
[Jest test framework](https://jestjs.io/) is provided. This coupling allows the
86+
execution of fuzz tests alongside your normal unit tests and seamlessly detect
87+
problems on your local machine or in your CI, enabling you to check that found
88+
bugs stay resolved forever.
13689

137-
An example of a `Promise` based fuzz target can be found at
138-
[examples/promise/fuzz.js](examples/promise/fuzz.js).
90+
Furthermore, the Jest integration enables great IDE support, so that individual
91+
inputs can be run or even debugged, similar to what you would expect from normal
92+
Jest tests.
13993

140-
#### Using TypeScript to write fuzz targets
94+
**Note**: Detailed explanation on how to use the Jest integration can be found
95+
at [docs/jest-integration.md](docs/jest-integration.md).
14196

142-
It is also possible to use [TypeScript](https://www.typescriptlang.org), or in
143-
that matter any other language transpiling to JavaScript, to write fuzz targets,
144-
as long as a modules exporting a `fuzz` function is generated.
145-
146-
An example on how to use TypeScript to fuzz a library can be found at
147-
[examples/js-yaml/package.json](examples/js-yaml/package.json).
148-
149-
#### ⚠️ Using Jazzer.js on pure ESM projects ⚠️
150-
151-
ESM bring a couple of challenges to the table, which are currently not fully
152-
solved. Jazzer.js does have general ESM support as in your project should be
153-
loaded properly. If your project internally still relies on calls to
154-
`require()`, all of these dependencies will be hooked. However, _pure_
155-
ECMAScript projects will currently not be instrumented!
156-
157-
One such example that Jazzer.js can handle just fine can be found at
158-
[examples/protobufjs/fuzz.js](examples/protobufjs/fuzz.js):
97+
A fuzz test in Jest looks similar to the following example:
15998

16099
```js
161-
import proto from "protobufjs";
162-
import { temporaryWriteSync } from "tempy";
163-
164-
export function fuzz(data: Buffer) {
165-
try {
166-
// Fuzz logic
167-
} catch (e) {
168-
// Handle expected error ogic here
169-
}
170-
}
100+
describe("My function", () => {
101+
it.fuzz("can be fuzzed", (data) => {
102+
target.fuzzMe(data);
103+
});
104+
});
171105
```
172106

173-
You also have to adapt your `package.json` accordingly, by adding:
107+
### Using fuzz targets
174108

175-
```json
176-
{
177-
"type": "module"
178-
}
179-
```
180-
181-
### Running the fuzzer
109+
Creating fuzz targets and executing those via CLI commands is straightforward
110+
and similar to what you would expect from other fuzzers. This approach offers
111+
the most control and can easily be integrated in your CI pipelines via
112+
`npm`/`npx` commands.
182113

183-
After adding `@jazzer.js/core` as dev-dependency to a project the fuzzer can be
184-
executed using the `jazzer` npm command. To do so use `npx`:
185-
186-
```shell
187-
npx jazzer <fuzzer parameters>
188-
```
114+
**Note**: Detailed explanation on how to create and use fuzz targets can be
115+
found at [docs/fuzz-targets.md](docs/fuzz-targets.md).
189116

190-
Or add a new script to your `package.json`:
117+
A fuzz target can look as simple as this example:
191118

192-
```json
193-
"scripts": {
194-
"fuzz": "jazzer <fuzzer parameters>"
195-
}
196-
```
197-
198-
The general command format is:
199-
200-
```text
201-
jazzer <fuzzTarget> <fuzzerFlags> [corpus...] [-- <fuzzingEngineFlags>]
119+
```js
120+
// file "FuzzTarget.js"
121+
module.exports.fuzz = function (data /*: Buffer */) {
122+
const fuzzerData = data.toString();
123+
myAwesomeCode(fuzzerData);
124+
};
202125
```
203126

204-
Detailed documentation and some example calls are available using the `--help`
205-
flag, so that only the most important ones are discussed here.
206-
207-
| Parameter | Description |
208-
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
209-
| `<fuzzTarget>` | Import path to the fuzz target module. |
210-
| `[corpus...]` | Paths to the corpus directories. If not given, no initial seeds are used nor interesting inputs saved. |
211-
| `-- <fuzzingEngineFlags>` | Parameters after `--` are forwarded to the internal fuzzing engine (`libFuzzer`). Available settings can be found in its [options documentation](https://www.llvm.org/docs/LibFuzzer.html#options). |
212-
| `-i`, `--instrumentation_includes` / `-e`, `--instrumentation_excludes` | Part of filepath names to include/exclude in the instrumentation. A tailing `/` should be used to include directories and prevent confusion with filenames. `*` can be used to include all files. Can be specified multiple times. Default will include everything outside the `node_modules` directory. |
213-
| `--sync` | Enables synchronous fuzzing. **May only be used for entirely synchronous code**. |
214-
| `-h`, `--custom_hooks` | Filenames with custom hooks. Several hooks per file are possible. See further details in [docs/fuzz-settings.md](docs/fuzz-settings.md). |
215-
| `--help` | Detailed help message containing all flags. |
216-
217127
## Documentation
218128

219129
Further documentation is available at [docs/readme.md](docs/README.md).
220130

221131
### Demo Video - Introduction to Jazzer.js
222132

223-
We recorded a live demo in which shows how to get Jazzer.js up and running for
224-
your own projects. If you are just getting started, this might be helpful.
133+
We recorded a live demo which shows how to get Jazzer.js up and running for your
134+
own projects. If you are just getting started, this might be helpful.
225135

226136
You can watch the recording [here](https://youtu.be/KyIhxEiNnfc).
227137

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## User Guides
44

5+
- [Using fuzz targets](fuzz-targets.md)
6+
- [Using Jest integration](jest-integration.md)
57
- [Advanced Fuzzing Settings](fuzz-settings.md)
68

79
## Internal Documentation

0 commit comments

Comments
 (0)