diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c79b9ed..6632b92 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,3 +5,4 @@ # project CMakeLists.txt does not grow with each test group. add_subdirectory(afp) +add_subdirectory(salvage) diff --git a/tests/salvage/CMakeLists.txt b/tests/salvage/CMakeLists.txt new file mode 100644 index 0000000..919cb0e --- /dev/null +++ b/tests/salvage/CMakeLists.txt @@ -0,0 +1,28 @@ +# Optional NetWare salvage/deleted-entry smoke-test helpers. +# +# The first helper is a layout contract test for the upcoming recycle-backed +# nwsalvage backend. It has no ncpfs dependency and does not require a running +# mars_nwe server. + +set(SALVAGE_LAYOUT_SMOKE_SCRIPT + ${CMAKE_CURRENT_BINARY_DIR}/salvage_layout_smoke.sh +) + +add_custom_command( + OUTPUT ${SALVAGE_LAYOUT_SMOKE_SCRIPT} + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/salvage_layout_smoke.sh + ${SALVAGE_LAYOUT_SMOKE_SCRIPT} + COMMAND ${CMAKE_COMMAND} -E env chmod +x ${SALVAGE_LAYOUT_SMOKE_SCRIPT} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/salvage_layout_smoke.sh + COMMENT "Copying salvage layout smoke helper" + VERBATIM +) + +add_custom_target(salvage_layout_smoke ALL + DEPENDS ${SALVAGE_LAYOUT_SMOKE_SCRIPT} +) + +set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES + ${SALVAGE_LAYOUT_SMOKE_SCRIPT} +) diff --git a/tests/salvage/README.md b/tests/salvage/README.md new file mode 100644 index 0000000..8c1b4b9 --- /dev/null +++ b/tests/salvage/README.md @@ -0,0 +1,36 @@ +# Salvage smoke tests + +This directory is reserved for NetWare salvage/deleted-entry coverage. The +backend is intentionally shared by NCP salvage calls and the later AFP `0x13` +`Get Macintosh Info On Deleted Files` adapter; AFP must not grow a parallel +local deleted-file scanner. + +The first executable coverage is layout-only. It records the repository +contract before `src/nwsalvage.c` exists: + +- deleted file payloads live below the recycle repository, +- per-object JSON metadata lives below the salvage repository, +- there is no large per-directory index file, +- stale JSON metadata is detectable when the matching recycle payload is gone. + +Default repository names come from the `nwserv.conf`/`nw.ini` template options: + +```text +48 1 +49 .recycle .salvage +``` + +Expected layout for a deleted `SYS:PUBLIC/PMDFLTS.INI` owned by `SUPERVISOR`: + +```text +SYS/.recycle/SUPERVISOR/PUBLIC/PMDFLTS.INI +SYS/.salvage/SUPERVISOR/PUBLIC/PMDFLTS.INI.json +``` + +Future runtime tests should add direct coverage for: + +- `NCP 0x2222 / 22 / 27` Scan Salvageable Files (old), +- `NCP 0x2222 / 87 / 16` Scan Salvageable Files, +- `NCP 0x2222 / 87 / 17` Recover Salvageable File, +- `NCP 0x2222 / 87 / 18` Purge Salvageable File, +- AFP `0x13` as a thin adapter over the shared salvage backend. diff --git a/tests/salvage/salvage_layout_smoke.sh b/tests/salvage/salvage_layout_smoke.sh new file mode 100755 index 0000000..b3d023e --- /dev/null +++ b/tests/salvage/salvage_layout_smoke.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# Validate the planned recycle-backed salvage metadata layout without requiring +# a running mars_nwe server. This is a contract test for the upcoming +# nwsalvage backend, not an implementation of the backend itself. + +set -u + +ROOT="" +RECYCLE_NAME=".recycle" +SALVAGE_NAME=".salvage" +KEEP_ROOT=0 + +usage() { + cat <&2 + exit 1 +} + +while [ $# -gt 0 ]; do + case "$1" in + --root) + ROOT=$2; shift 2 ;; + --repo-names) + RECYCLE_NAME=$2; SALVAGE_NAME=$3; shift 3 ;; + --keep-root) + KEEP_ROOT=1; shift ;; + -h|--help) + usage; exit 0 ;; + *) + usage >&2; fail "unknown option: $1" ;; + esac +done + +if [ -z "$ROOT" ]; then + ROOT=$(mktemp -d "${TMPDIR:-/tmp}/mars-salvage-layout.XXXXXX") || exit 1 +else + mkdir -p "$ROOT" || exit 1 +fi + +cleanup() { + if [ "$KEEP_ROOT" -eq 0 ]; then + rm -rf "$ROOT" + else + echo "kept test root: $ROOT" + fi +} +trap cleanup EXIT + +SYS="$ROOT/SYS" +LIVE_FILE="$SYS/PUBLIC/PMDFLTS.INI" +RECYCLE_FILE="$SYS/$RECYCLE_NAME/SUPERVISOR/PUBLIC/PMDFLTS.INI" +SALVAGE_JSON="$SYS/$SALVAGE_NAME/SUPERVISOR/PUBLIC/PMDFLTS.INI.json" +FLAT_INDEX="$SYS/$SALVAGE_NAME/SUPERVISOR/PUBLIC/.index.json" + +mkdir -p "$(dirname "$LIVE_FILE")" || exit 1 +printf 'sample payload\n' > "$LIVE_FILE" || exit 1 + +mkdir -p "$(dirname "$RECYCLE_FILE")" "$(dirname "$SALVAGE_JSON")" || exit 1 +mv "$LIVE_FILE" "$RECYCLE_FILE" || exit 1 +cat > "$SALVAGE_JSON" < missing $RECYCLE_FILE" +echo "salvage layout smoke passed"