docs/moon-codec-fuzzing.md
This repo contains Rust-driven fuzzers that exercise the MoonBit codec implementation by round-tripping real Loro data through the Moon CLI (compiled to JS) and validating the result in Rust.
These fuzzers are not cargo-fuzz targets. They are deterministic, seed-based test drivers that
produce reproducible artifacts on failure.
rust-toolchain)node)moon)Environment variables used by the drivers/tests:
MOON_BIN: path to the moon executable (default: moon)NODE_BIN: path to node (default: node)Example (common local setup):
export MOON_BIN="$HOME/.moon/bin/moon"
export NODE_BIN="node"
All fuzzers follow the same pattern:
seed controls randomness).moon/cmd/loro_codec_cli) compiled to JS and run with Node.<out-dir>/case-<seed>/.The Moon CLI is built automatically by each driver via:
moon build --target js --release cmd/loro_codec_cli
moon_snapshot_fuzzPurpose: Validate Moon’s snapshot decoding by comparing deep JSON.
What it tests:
export-deep-json).doc.get_deep_value().to_json_value().Run:
MOON_BIN="$HOME/.moon/bin/moon" NODE_BIN=node \
cargo run -p loro --example moon_snapshot_fuzz -- \
--seed 1 --iters 200 --ops 400 --commit-every 20 --peers 10
Repro on failure:
snapshot.blob, expected.json, and Moon outputs into:
moon_snapshot_fuzz_artifacts/case-<seed>/--iters 1:MOON_BIN="$HOME/.moon/bin/moon" NODE_BIN=node \
cargo run -p loro --example moon_snapshot_fuzz -- \
--seed <seed> --iters 1 --ops <ops> --commit-every <n> --peers <n>
moon_jsonschema_fuzzPurpose: Validate Moon’s encode-jsonschema (JsonSchema JSON → binary FastUpdates mode=4).
Why the oracle is “Rust updates” (not “original local doc”):
f64 accumulation; floating-point sums are not associative.f64 differences.(start_vv -> end_vv) range, by importing both and comparing the resulting state.What it tests:
start_frontiers (sometimes non-empty).schema.json via export_json_updates(start_vv, end_vv)updates_rust.blob via ExportMode::Updates { from: start_vv }base_snapshot.blob via ExportMode::SnapshotAt { version: start_frontiers }schema.json into updates_moon.blob.base_snapshot + updates_rust and base_snapshot + updates_moon and compares:
oplog_vv() (operation coverage)Run:
MOON_BIN="$HOME/.moon/bin/moon" NODE_BIN=node \
cargo run -p loro --example moon_jsonschema_fuzz -- \
--seed 1 --iters 300 --ops 400 --commit-every 20 --peers 10
Repro on failure:
moon_jsonschema_fuzz_artifacts/case-<seed>/.--iters 1.For longer runs (recommended before merging codec changes):
MOON_BIN="$HOME/.moon/bin/moon" NODE_BIN=node \
cargo run -p loro --example moon_jsonschema_fuzz -- \
--seed 1000 --iters 200 --ops 1000 --commit-every 50 --peers 20
--release for speed:MOON_BIN="$HOME/.moon/bin/moon" NODE_BIN=node \
cargo run -p loro --release --example moon_jsonschema_fuzz -- \
--seed 1 --iters 2000 --ops 1000 --commit-every 50 --peers 20
When adding new fuzz ops, prefer:
start_frontiers ranges (incremental import correctness).When a failure occurs:
In addition to semantic fuzzing, there are e2e tests that ensure the Moon CLI:
encode-jsonschema.These tests are meant to catch panics/crashes and “accepting garbage input”.