mirror of
https://github.com/kucherenko/jscpd.git
synced 2026-09-19 08:11:03 +08:00
425f57b142
Wave 1 of the perf-rust-optimization heist. Algorithmic-only wins, zero public-API breakage, identical detection results (290-pair golden gate). Changes: - hash.rs: `roll()` now takes a precomputed `window_power: u64` instead of recomputing `base_pow(window_size - 1)` on every call. Removes an O(window_size) loop from the inner sliding-window hot path. `base_pow` is now `pub` so callers can hoist the power once per format group. - detect.rs: hoist `window_power = base_pow(min_tokens - 1)` once before the outer file loop in `detect_in_group()`. Pass it into every `roll()` call. - detect.rs: switch the per-call `by_format` map from `std::HashMap` to `FxHashMap` for consistency with the rest of the detection path. - store.rs: add `Store::reserve(n)` as a default-noop trait method (performance hint only — correctness must not depend on it). Implement on `MemoryStore` as `self.inner.reserve(n)`. Trait remains `dyn`-safe (verified by new test that calls `reserve` through `&mut dyn Store`). - detect.rs: call `store.reserve(total_windows)` once before the detection loop, where `total_windows` is the sum of `hashes.len() - min_tokens` across all prepared files. Eliminates `FxHashMap` rehashing mid-detect. Tooling: - Add `rust/scripts/regression_check.sh` — golden-baseline gate run after each Wave change. Normalizes file paths to `../fixtures/...` form so the gate is independent of absolute vs relative path emission. - Add `rust/tests/golden.json` — frozen 290-pair clone set captured from the pre-Heist baseline. Verification: - `cargo test -p cpd-core` — 22 pass - `scripts/regression_check.sh` — 290 pairs match golden, exit 0
62 lines
2.1 KiB
Bash
Executable File
62 lines
2.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# regression_check.sh — verify detection output matches golden baseline
|
|
# Run after each Wave 2 and Wave 3 sub-change.
|
|
# Exit 0 = no regression. Exit 1 = regression or tool missing.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
RUST_DIR="$(dirname "$SCRIPT_DIR")"
|
|
GOLDEN="$RUST_DIR/tests/golden.json"
|
|
FIXTURES_DIR="$RUST_DIR/../fixtures"
|
|
BINARY="$RUST_DIR/target/release/cpd"
|
|
REPORT="$RUST_DIR/report/jscpd-report.json"
|
|
|
|
# Check prerequisites
|
|
if ! command -v jq &>/dev/null; then
|
|
echo "ERROR: jq is required but not found. Install with: brew install jq"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$BINARY" ]]; then
|
|
echo "ERROR: release binary not found at $BINARY"
|
|
echo " Run: cargo build --release --bin cpd"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$GOLDEN" ]]; then
|
|
echo "ERROR: golden baseline not found at $GOLDEN"
|
|
echo " Capture it before Wave 2: see Contract FR-013"
|
|
exit 1
|
|
fi
|
|
|
|
# Run detection and produce report
|
|
"$BINARY" "$FIXTURES_DIR" -r json >/dev/null 2>&1
|
|
|
|
# Extract clone pairs (format + sorted file pair) from current run.
|
|
# Normalize source paths to "../fixtures/..." form so the gate is independent
|
|
# of whether the binary emits absolute or relative paths.
|
|
CURRENT="$(jq '[.duplicates[] | {files: ([.fragment_a.source_id, .fragment_b.source_id] | map(sub(".*/fixtures/"; "../fixtures/")) | sort), format: .format}] | sort_by(.format + .files[0] + .files[1])' "$REPORT")"
|
|
|
|
GOLDEN_COUNT="$(jq length "$GOLDEN")"
|
|
CURRENT_COUNT="$(echo "$CURRENT" | jq length)"
|
|
|
|
if [[ "$GOLDEN_COUNT" != "$CURRENT_COUNT" ]]; then
|
|
echo "REGRESSION: clone count changed: golden=$GOLDEN_COUNT current=$CURRENT_COUNT"
|
|
exit 1
|
|
fi
|
|
|
|
# Compare file-pair sets (order-insensitive, format-grouped)
|
|
MATCH="$(jq -n \
|
|
--argjson golden "$(cat "$GOLDEN")" \
|
|
--argjson current "$CURRENT" \
|
|
'($golden | sort_by(.format + .files[0] + .files[1])) == ($current | sort_by(.format + .files[0] + .files[1]))')"
|
|
|
|
if [[ "$MATCH" != "true" ]]; then
|
|
echo "REGRESSION: clone file-pair sets differ from golden baseline"
|
|
echo " Run: diff <(cat '$GOLDEN') <(echo '$CURRENT' | jq .)"
|
|
exit 1
|
|
fi
|
|
|
|
echo "OK: $CURRENT_COUNT clone pairs match golden baseline"
|