- tests/wal_properties.rs — deterministic generator, reproducible by seed:
everything appended is read back intact (300 cases), and after ANY damage
to the file (bit flips, truncation, inserted/deleted bytes, duplicated or
rotated regions, overwritten ranges; 1500 cases) reading never panics and
yields an exact prefix of what was written — the guarantee the chained CRC
exists to give. Opening for append then repairs the tail and a new entry
lands right behind the surviving prefix.
- tests/crash_recovery.rs — builds the on-disk images a process crash can
leave and reopens each against a model of what was acknowledged: an image
after every operation (random saves, in-place updates, checkpoints, small
wal_max_entries), the checkpoint window (new .h5 + not-yet-truncated WAL)
over several rounds, and the WAL torn at every byte length, which must
recover the checkpoint plus a prefix of the operations logged since.
- fuzz/fuzz_wal_replay — arbitrary bytes as a WAL: read and open-for-append
must not panic, and open() must not change what is replayable. Based on the
target from the clawmates mission branch (4aee2fa), with the repair
property added. The CI fuzz step now covers both fuzz crates.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
127 lines
3.8 KiB
Bash
Executable File
127 lines
3.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CI test script — runs fmt, clippy (all targets + feature matrix), tests,
|
|
# Python interop suites, bench compilation, and no_std checks.
|
|
#
|
|
# Usage:
|
|
# ./scripts/ci-test.sh
|
|
#
|
|
# Environment:
|
|
# CLAWHDF5_REQUIRE_INTEROP=1 Fail (instead of skip) when python3 with
|
|
# h5py/netCDF4/xarray is missing. CI sets this.
|
|
# Unset locally, the interop steps are skipped
|
|
# if python3+h5py is not importable.
|
|
# CLAWHDF5_FUZZ_SECONDS=N Run each cargo-fuzz target for N seconds
|
|
# (needs nightly + cargo-fuzz). Default: skip.
|
|
#
|
|
# Exit codes:
|
|
# 0 — all checks passed
|
|
# 1 — one or more checks failed
|
|
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PASS=0
|
|
FAIL=0
|
|
STEPS=()
|
|
|
|
run_step() {
|
|
local name="$1"
|
|
shift
|
|
echo ""
|
|
echo "==> [$name]"
|
|
if "$@" 2>&1; then
|
|
echo " ✓ PASS: $name"
|
|
PASS=$((PASS + 1))
|
|
STEPS+=("PASS: $name")
|
|
else
|
|
echo " ✗ FAIL: $name"
|
|
FAIL=$((FAIL + 1))
|
|
STEPS+=("FAIL: $name")
|
|
fi
|
|
}
|
|
|
|
# All steps always run so one failure doesn't hide the others; the summary
|
|
# and the exit code at the end are the verdict.
|
|
|
|
# 1. Format check
|
|
run_step "cargo fmt --check" cargo fmt --check
|
|
|
|
# 2. Clippy over every target (lib, bins, tests, benches, examples). Without
|
|
# --all-targets, test and bench code is never linted. clawhdf5-py is
|
|
# excluded because it needs PyO3/Python headers.
|
|
run_step "cargo clippy --all-targets" cargo clippy \
|
|
--workspace \
|
|
--exclude clawhdf5-py \
|
|
--all-targets \
|
|
-- -D warnings
|
|
|
|
# 3. Clippy over clawhdf5-format's optional features, which the default
|
|
# workspace build never compiles (szip is left out: it needs libaec).
|
|
run_step "cargo clippy (format feature matrix)" cargo clippy \
|
|
-p clawhdf5-format \
|
|
--all-targets \
|
|
--features parallel,lz4,zstd,pcodec,fast-checksum \
|
|
-- -D warnings
|
|
|
|
# 4. Tests (exclude clawhdf5-py)
|
|
run_step "cargo test" cargo test \
|
|
--workspace \
|
|
--exclude clawhdf5-py
|
|
|
|
run_step "cargo test (format feature matrix)" cargo test \
|
|
-p clawhdf5-format \
|
|
--features parallel,lz4,zstd,pcodec,fast-checksum
|
|
|
|
# 5. Python interop suites. The h5py writer tests are #[ignore]d so a plain
|
|
# `cargo test` stays hermetic; run them explicitly here.
|
|
if python3 -c "import h5py" >/dev/null 2>&1 || [ "${CLAWHDF5_REQUIRE_INTEROP:-0}" = "1" ]; then
|
|
run_step "h5py interop (format, ignored tests)" cargo test \
|
|
-p clawhdf5-format --test writer_h5py_tests -- --include-ignored
|
|
else
|
|
echo ""
|
|
echo "==> [h5py interop] SKIPPED: python3 with h5py not available"
|
|
STEPS+=("SKIP: h5py interop (format, ignored tests)")
|
|
fi
|
|
|
|
# 6. Benches must keep compiling (they are not run).
|
|
run_step "cargo bench --no-run" cargo bench \
|
|
--workspace \
|
|
--exclude clawhdf5-py \
|
|
--no-run
|
|
|
|
# 7. no_std check
|
|
run_step "check-nostd.sh" "$SCRIPT_DIR/check-nostd.sh"
|
|
|
|
# 8. Optional fuzz smoke run
|
|
if [ -n "${CLAWHDF5_FUZZ_SECONDS:-}" ]; then
|
|
fuzz_smoke() {
|
|
local crate target
|
|
for crate in clawhdf5-format clawhdf5-agent; do
|
|
cd "$SCRIPT_DIR/../crates/$crate" || return 1
|
|
for target in $(cargo +nightly fuzz list); do
|
|
echo "--- fuzz: $crate/$target"
|
|
cargo +nightly fuzz run "$target" -- \
|
|
-max_total_time="$CLAWHDF5_FUZZ_SECONDS" || return 1
|
|
done
|
|
done
|
|
}
|
|
run_step "fuzz smoke (${CLAWHDF5_FUZZ_SECONDS}s/target)" fuzz_smoke
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "========================================"
|
|
echo " CI Summary"
|
|
echo "========================================"
|
|
for s in "${STEPS[@]}"; do
|
|
echo " $s"
|
|
done
|
|
echo "----------------------------------------"
|
|
echo " $PASS passed, $FAIL failed"
|
|
echo "========================================"
|
|
|
|
if [ "$FAIL" -gt 0 ]; then
|
|
exit 1
|
|
fi
|
|
exit 0
|