#!/usr/bin/env bash
# cross_test.sh — confirm Rust/Go/C++ implementations produce byte-identical pages.
set -euo pipefail

LAB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
RUST_BIN="$LAB_DIR/src/rust/target/release/pagealloc"
GO_BIN="$LAB_DIR/src/go/bin/pagealloc"
CPP_BIN="$LAB_DIR/src/cpp/build/pagealloc"

echo "building all three implementations..."
(cd "$LAB_DIR/src/rust" && cargo build --release >/dev/null)
mkdir -p "$LAB_DIR/src/go/bin"
(cd "$LAB_DIR/src/go" && go build -o "$GO_BIN" ./cmd/pagealloc)
if [[ ! -d "$LAB_DIR/src/cpp/build" ]]; then
    (cd "$LAB_DIR/src/cpp" && cmake -S . -B build >/dev/null)
fi
(cd "$LAB_DIR/src/cpp" && cmake --build build >/dev/null)

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

write_and_dump() {
    local label="$1" bin="$2" file="$3"
    "$bin" write "$file" 0 "cross-language-test"
    "$bin" write "$file" 1 "second-page"
    "$bin" write "$file" 4 "sparse-five"
    "$bin" hexdump "$file" > "$TMP/$label.hex"
}

write_and_dump rust "$RUST_BIN" "$TMP/rust.bin"
write_and_dump go   "$GO_BIN"   "$TMP/go.bin"
write_and_dump cpp  "$CPP_BIN"  "$TMP/cpp.bin"

echo
echo "comparing raw bytes..."
diff -q "$TMP/rust.bin" "$TMP/go.bin"  || { echo "FAIL rust vs go binary"; exit 1; }
diff -q "$TMP/rust.bin" "$TMP/cpp.bin" || { echo "FAIL rust vs cpp binary"; exit 1; }

echo "comparing hex dumps..."
diff -q "$TMP/rust.hex" "$TMP/go.hex"  || { echo "FAIL rust vs go hex"; exit 1; }
diff -q "$TMP/rust.hex" "$TMP/cpp.hex" || { echo "FAIL rust vs cpp hex"; exit 1; }

echo
echo "cross-reading: rust writes -> go reads -> cpp reads"
[[ "$("$GO_BIN"  read "$TMP/rust.bin" 0)" == "cross-language-test" ]] || { echo "FAIL go reads rust"; exit 1; }
[[ "$("$CPP_BIN" read "$TMP/rust.bin" 4)" == "sparse-five"          ]] || { echo "FAIL cpp reads rust"; exit 1; }
[[ "$("$RUST_BIN" read "$TMP/go.bin" 1)" == "second-page"           ]] || { echo "FAIL rust reads go"; exit 1; }

echo
echo "All three implementations are byte-compatible."
