#!/usr/bin/env bash # Self-contained build + test for src/mars/vfs (plain g++, no CMake needed). # # tests/mars_vfs/build_and_run.sh # # Always runs the unit tests (the deflated fixture is generated with Python's # zipfile if python3 is available). When SOTS_GOB_DIR points at a directory # holding sots.gob + sots_local_en.gob it also runs the oracle-backed # real-data test and byte-compares a few entries against `unzip -p`. # # Env: CXX (g++), CC (gcc), PYTHON (python3), BUILD_DIR (tests/mars_vfs/build), # SOTS_GOB_DIR, SOTS_GOB_ORACLE_DIR (defaults to SOTS_GOB_DIR), SOTS_GOB_FULL=1. set -euo pipefail HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ROOT=$(cd "$HERE/../.." && pwd) BUILD=${BUILD_DIR:-$HERE/build} CXX=${CXX:-g++} CC=${CC:-gcc} PYTHON=${PYTHON:-python3} MINIZ="$ROOT/third_party/miniz" MINIZ_DEFS=(-DMINIZ_NO_ARCHIVE_APIS -DMINIZ_NO_ARCHIVE_WRITING_APIS -DMINIZ_NO_STDIO -DMINIZ_NO_TIME -DMINIZ_NO_ZLIB_COMPATIBLE_NAMES) FLAGS=(-std=c++17 -O2 -Wall -Wextra -Werror -I"$ROOT/src" -I"$HERE" -I"$MINIZ" "${MINIZ_DEFS[@]}") VFS=("$ROOT/src/mars/vfs/path.cpp" "$ROOT/src/mars/vfs/zip_archive.cpp" "$ROOT/src/mars/vfs/vfs.cpp") PARSE=("$ROOT/src/mars/parse/blocks.cpp" "$ROOT/src/mars/parse/effect.cpp" "$ROOT/src/mars/parse/value.cpp") TEXT=("$ROOT/src/mars/text/value.cpp" "$ROOT/src/mars/text/flat_kv.cpp" "$ROOT/src/mars/text/manifest.cpp" "$ROOT/src/mars/text/csv.cpp") mkdir -p "$BUILD" echo "== building (miniz as C, module + tests as C++17 -Werror)" "$CC" -std=c11 -O2 -w "${MINIZ_DEFS[@]}" -c "$MINIZ/miniz.c" -o "$BUILD/miniz.o" "$CXX" "${FLAGS[@]}" "${VFS[@]}" "$BUILD/miniz.o" "$HERE/test_main.cpp" "$HERE/unit_tests.cpp" -o "$BUILD/unit_tests" "$CXX" "${FLAGS[@]}" "${VFS[@]}" "$BUILD/miniz.o" "$HERE/vfs_cat.cpp" -o "$BUILD/vfs_cat" "$CXX" "${FLAGS[@]}" "${VFS[@]}" "${PARSE[@]}" "${TEXT[@]}" "$BUILD/miniz.o" "$HERE/realdata_test.cpp" -o "$BUILD/realdata_test" echo "== deflated fixture" FIXTURE="$BUILD/deflated.zip" if command -v "$PYTHON" >/dev/null 2>&1 && "$PYTHON" "$HERE/make_fixture.py" "$FIXTURE"; then export MARS_VFS_FIXTURE="$FIXTURE" echo "generated $FIXTURE" else echo "python3 unavailable: deflate test will SKIP" unset MARS_VFS_FIXTURE fi echo "== unit tests" "$BUILD/unit_tests" if [ -z "${SOTS_GOB_DIR:-}" ]; then echo "== SOTS_GOB_DIR not set: skipping real-data tests" exit 0 fi if [ ! -f "$SOTS_GOB_DIR/sots.gob" ] || [ ! -f "$SOTS_GOB_DIR/sots_local_en.gob" ]; then echo "== SOTS_GOB_DIR=$SOTS_GOB_DIR does not hold sots.gob + sots_local_en.gob" >&2 exit 1 fi echo "== real-data test" "$BUILD/realdata_test" echo "== byte-equality spot check against unzip -p" if ! command -v unzip >/dev/null 2>&1; then echo "unzip not installed: SKIP" exit 0 fi check() { # archive rel -- unzip is the oracle; the VFS is asked with a different spelling local gob="$1" rel="$2" exp="$BUILD/spot.expected" got="$BUILD/spot.got" local spelled spelled=$(echo "$rel" | tr '/a-z' '\\A-Z') # backslashes + upper case unzip -p "$gob" "$rel" > "$exp" || { echo "unzip cannot extract $rel" >&2; return 1; } [ -s "$exp" ] || { echo "empty oracle output for $rel" >&2; return 1; } "$BUILD/vfs_cat" --zip "$SOTS_GOB_DIR/sots.gob" --zip "$SOTS_GOB_DIR/sots_local_en.gob" "$spelled" > "$got" \ || { echo "vfs_cat cannot read $spelled" >&2; return 1; } if cmp -s "$exp" "$got"; then echo "same: $rel ($(wc -c < "$exp") bytes)" else echo "DIFFER: $rel" >&2 return 1 fi } check "$SOTS_GOB_DIR/sots.gob" "TechTree/MasterTechList.tech" check "$SOTS_GOB_DIR/sots.gob" "Weapons/_weapons.txt" check "$SOTS_GOB_DIR/sots.gob" "Data/globals.txt" check "$SOTS_GOB_DIR/sots.gob" "Avatars/AI_AV.tga" check "$SOTS_GOB_DIR/sots.gob" "Species/Human/sections/CRAIC.shipsection" check "$SOTS_GOB_DIR/sots_local_en.gob" "Locale/EN/Strings.csv" rm -f "$BUILD/spot.expected" "$BUILD/spot.got" echo "== all good"