Repository navigation
test: property-based fuzz testing for js->zig->js roundtrip - #41
Open
nazarhussain wants to merge 19 commits into
Open
nazarhussain wants to merge 19 commits into
nazarhussain wants to merge 19 commits into
Conversation
wemeetagain
reviewed
Jul 24, 2026
| - name: Test | ||
| run: pnpm test:js | ||
|
|
||
| test-fuzz: |
Member
There was a problem hiding this comment.
seems a little strange to fuzz in CI
wemeetagain
reviewed
Jul 24, 2026
wemeetagain
left a comment
Member
There was a problem hiding this comment.
I think the API changes and additional comments are good
nazarhussain
force-pushed
the
nh/fuzz-testing
branch
2 times, most recently
from
October 19, 2026 10:11
4b09223 to
e3384ed
Compare
nazarhussain
changed the base branch from
main
to
nh/bigint-exact-conversions
October 19, 2026 10:11
nazarhussain
force-pushed
the
nh/fuzz-testing
branch
from
October 19, 2026 10:20
e3384ed to
959d16d
Compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Round-trips JS BigInt → i128 → JS BigInt via toI128 and fromWords. Property test covers the i128 boundary plus out-of-range truncation via BigInt.asIntN(128, ·). Oracle test adds deterministic boundary cases for zero, I128_MIN/MAX (exact), just-out-of-range ±1, and oversized values whose low 128 bits are all zero (expected result: 0n).
The seeds-workflow doc claimed NaN/Infinity could be persisted via a
{"__special": ...} encoding, but no corresponding reviver exists in
fuzz.test.ts — following the README literally would silently corrupt
test input. NaN/Infinity are already in edgeNumbers and exercised every
run, so persisting them adds nothing. Trim the README to match reality.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nazarhussain
force-pushed
the
nh/bigint-exact-conversions
branch
from
October 19, 2026 10:31
0773d1c to
0dcc598
Compare
nazarhussain
force-pushed
the
nh/fuzz-testing
branch
from
October 19, 2026 10:31
959d16d to
17080db
Compare
…90) Packages the fast-check fuzz targets from #41 as a Docker image for the [ChainSafe fuzz platform](https://github.com/ChainSafe/lodestar-ansible-development/tree/main/playbooks/fuzz), so they run continuously as one campaign (`zapi:round-trip`). > **Stacked on #41** (which is stacked on #83). Merge those first. ### Changes - `Dockerfile.fuzz` (+ `.dockerignore`): a build stage that downloads Zig 0.16.0 (checksum-verified) and builds `test_fuzz_numeric.node` with `ReleaseSafe` and `-Dcpu=baseline`. The runtime stage is `node:24-slim` with the addon, the tests and `node_modules`. - `tests/fuzz/platform/run-fuzz.ts`: the entrypoint, which implements the platform's container contract. It re-runs every `*.fuzz.test.ts` in a loop (100 000 cases per property by default, a fresh random seed each time) until SIGTERM. - A failing property is saved once to `$FUZZ_FAILURES/failure-<hash>.json`, de-duplicated by test name and shrunk counterexample. The file includes the seed and path for replay. Fuzzing then continues. - `$FUZZ_METRICS/status` is rewritten atomically after each iteration. It reports `execs_total`, `execs_per_second`, `crashes_total` and `last_find_timestamp_seconds`. There is no coverage or corpus field, because fast-check is not coverage-guided. - Counters persist in `$FUZZ_STATE/stats.json`. - A test file that fails to load, or a run with no tests, exits non-zero (an infrastructure failure). - `.github/workflows/fuzz-image.yml`: mirrors lodestar-z's `fuzz-image.yml`. A `build and test` job runs with read-only permissions and smoke-tests the image under the platform's restrictions (non-root uid, read-only rootfs, no capabilities, no network, `--init`). Publishing is **manual** (`workflow_dispatch`): a separate `publish` job, the only one with `packages: write`, pushes the exact tested image as `main` (run on `main`) or `branch-<name>` (any other branch), plus `sha-<short>`, and keeps the newest 20 versions. lodestar-z's AFL++-only steps (seed replay, `core_pattern`, minimize) are omitted; the platform reads none of them. - `tests/fuzz/README.md`: a section on continuous fuzzing. ### Verified locally (arm64 Docker, platform restrictions) - Runs continuously and stops on SIGTERM with exit 0. - The status file is written and updated. - Counters resume across restarts. - A planted failing property is saved once over about 20 failing iterations. - A hidden addon gives `FATAL a test suite failed to load` and exit 1. The amd64 build and the workflow itself have not run yet; this PR's CI is their first run. ### Follow-ups - After merging, publish by running the workflow on `main` from the Actions tab. Then set the GHCR package `zapi-fuzz` to **public**. The platform pulls without credentials. - Add the target to `group_vars/fuzzer/vars.yml` in lodestar-ansible-development: ```yaml - project: zapi target: round-trip image: ghcr.io/chainsafe/zapi-fuzz:main cpu_mhz: 1000 memory_mb: 1024 duration: 0 uid: 60011 gid: 60011 ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The fuzz-image workflow already runs the fuzz properties on pull requests, so the separate test-fuzz CI job is redundant. The fixed edge-value checks move to tests/unit and run with test:js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a property-based fuzz harness for zapi
Number,BigIntandUint8Arrayconverters (vitest + fast-check, driven through a dedicatedtest_fuzz_numeric.nodeaddon). The harness surfaced several latent bugs and an API sharp edge.Changes
tests/fuzz/: round-trip fuzz targets and fast-check properties forNumber,BigIntandUint8Array, with a seeds workflow (seetests/fuzz/README.md).tests/unit/conversions.test.ts: fixed edge-value checks of the same targets against their oracles, run bytest:js.tests/build.zig.zon/tests/build.zig: a separate Zig package for the fuzz addon, mirroringexamples/and consuming zapi via--fork=... It installs to the rootzig-out/.package.json:build:zignow runsbuild:zig:examplesandbuild:zig:tests;test:jsalso runstests/unit/; addstest:fuzz:round_tripand thefast-checkdev dependency.Dockerfile.fuzz,tests/fuzz/platform/run-fuzz.tsand.github/workflows/fuzz-image.yml: the fuzz image for the ChainSafe fuzz platform. Pull requests build and smoke-test it, which covers the fuzz properties in CI; publishing to GHCR is a manual run.🤖 Generated with Claude Code