#!/usr/bin/env bash
set -euo pipefail
# Tests SDP mount-point detection functions in utils.lib using tmpfs (no fstab edits).
declare -i ErrorCount=0
declare -i TestCount=0
declare -i PassCount=0
declare -i FailCount=0
declare ThisUser=
SDPBackupScript="/p4/common/bin/opt_perforce_sdp_backup.sh"
function msg() { printf '%b\n' "$*"; }
function errmsg() { printf '\nError: %s\n' "${1:-Unknown Error}"; ErrorCount=$((ErrorCount+1)); }
function bail() { errmsg "${1:-Unknown Error}"; exit "${ErrorCount}"; }
function record_ok() { TestCount=$((TestCount+1)); PassCount=$((PassCount+1)); printf 'PASS: %s\n' "$1"; }
function record_fail() { TestCount=$((TestCount+1)); FailCount=$((FailCount+1)); printf 'FAIL: %s\n' "$1"; }
# shellcheck disable=SC1091
source /p4/common/lib/utils.lib
ThisUser=$(id -u -n)
[[ -r "$SDPBackupScript" ]] || bail "Missing expected SDP Backup Script: $SDPBackupScript"
[[ "$ThisUser" == root ]] || bail "Run as user 'root', not '$ThisUser'."
# Verify functions exist
for fn in get_mount_point find_p4depots_probe_path; do
type -t "$fn" >/dev/null || { echo "FATAL: function '$fn' not found after sourcing $SDPBackupScript" >&2; exit 3; }
done
# --- Test bookkeeping ---------------------------------------------------------
PassCount=0
FailCount=0
TestCount=0
function assert_eq() {
local got="$1" exp="$2" label="${3:-}"
TestCount=$((TestCount+1))
if [[ "$got" == "$exp" ]]; then
PassCount=$((PassCount+1)); printf 'PASS: %s\n' "${label:-ok}"
else
FailCount=$((FailCount+1)); printf 'FAIL: %s\n got: %s\n exp: %s\n' "${label:-mismatch}" "$got" "$exp"
fi
}
# --- Sandbox & cleanup --------------------------------------------------------
WORKDIR="$(mktemp -d -t sdp-mounttest.XXXXXXXX)"
TMPFILE=$(mktemp)
cleanup() {
set +e
# msg "Cleanup: Unmount everything under WORKDIR [$WORKDIR] (deepest-first)."
if command -v findmnt >/dev/null 2>&1; then
rm -f "$TMPFILE"
for mnt in $MNT_A $MNT_B; do
if findmnt -Rno TARGET "$mnt" > /dev/null 2>&1; then
echo "$mnt" >> "$TMPFILE"
fi
done
# msg "Mounts Detected:\\n$(cat "$TMPFILE")\\n"
while read -r mnt; do
[[ -n "$mnt" ]] || continue
umount "$mnt" >/dev/null 2>&1 || true
done < "$TMPFILE"
fi
rm -rf "$WORKDIR"
}
trap cleanup EXIT INT TERM
SDPRoot="$WORKDIR/p4"
mkdir -p "$SDPRoot"
# Mount points for simulation
MNT_A="$WORKDIR/mntA" # tmpfs
MNT_B="$WORKDIR/mntB" # tmpfs
mkdir -p "$MNT_A" "$MNT_B"
# Mount tmpfs (no fstab)
mount -t tmpfs -o size=32M tmpfs "$MNT_A"
mount -t tmpfs -o size=32M tmpfs "$MNT_B"
# Ground truth via findmnt
expected_mp() { findmnt -no TARGET -T "$1"; }
# Helper: create an instance dir and selected links
mk_instance() {
local inst="$1"; shift
local base="$SDPRoot/$inst"
mkdir -p "$base/bin"
local kv
for kv in "$@"; do
local key="${kv%%=*}" val="${kv#*=}"
case "$key" in
depots) ln -s "$val" "$base/depots" ;;
cache) ln -s "$val" "$base/cache" ;;
checkpoints) ln -s "$val" "$base/checkpoints" ;;
checkpoints.*) ln -s "$val" "$base/$key" ;;
*) echo "FATAL: unknown mk_instance arg: $kv" >&2; exit 10 ;;
esac
done
}
# Build scenarios
echo "Building scenarios under: $WORKDIR"
# Instance "1": server w/ depots on MNT_A (mounted)
mk_instance "1" "depots=$MNT_A"
# Instance "px": proxy w/ cache on MNT_B (mounted)
mk_instance "px" "cache=$MNT_B"
# Instance "2": checkpoints.* variant on regular dir (not a mount)
CP_DIR="$WORKDIR/cpdir"; mkdir -p "$CP_DIR"
mk_instance "2" "checkpoints.aa=$CP_DIR"
# Instance "zzz": depots on regular dir (not a mount)
DEPOTS_NM="$WORKDIR/depots_nm"; mkdir -p "$DEPOTS_NM"
mk_instance "zzz" "depots=$DEPOTS_NM"
echo
echo "Running tests..."
# T1: No instance arg -> prefer '1' among many, resolve depots -> MNT_A
if probe=$(find_p4depots_probe_path "$SDPRoot"); then
if [[ "${probe: -1}" == "/" ]]; then
record_ok "T1: probe has trailing slash"
else
record_fail "T1: probe missing trailing slash"
fi
if mp=$(get_mount_point "$probe"); then
exp=$(expected_mp "$MNT_A")
assert_eq "$mp" "$exp" "T1: prefer '1' -> MNT_A"
else
record_fail "T1: get_mount_point failed"
fi
else
record_fail "T1: probe failed"
fi
# T2: Explicit instance 'px' (proxy) -> cache -> MNT_B
if probe=$(find_p4depots_probe_path "$SDPRoot" "px"); then
if [[ "${probe: -1}" == "/" ]]; then
record_ok "T2: probe has trailing slash"
else
record_fail "T2: probe missing trailing slash"
fi
if mp=$(get_mount_point "$probe"); then
exp=$(expected_mp "$MNT_B")
assert_eq "$mp" "$exp" "T2: proxy cache -> MNT_B"
else
record_fail "T2: get_mount_point failed"
fi
else
record_fail "T2: probe failed"
fi
# T3: checkpoints.* variant on instance '2' (not mounted)
if probe=$(find_p4depots_probe_path "$SDPRoot" "2"); then
if mp=$(get_mount_point "$probe"); then
exp=$(expected_mp "$CP_DIR")
assert_eq "$mp" "$exp" "T3: checkpoints.* resolves correctly"
else
record_fail "T3: get_mount_point failed"
fi
else
record_fail "T3: probe failed"
fi
# T4: depots on non-mounted dir (instance 'zzz')
if probe=$(find_p4depots_probe_path "$SDPRoot" "zzz"); then
if mp=$(get_mount_point "$probe"); then
exp=$(expected_mp "$DEPOTS_NM")
assert_eq "$mp" "$exp" "T4: depots non-mounted resolves to base mount"
else
record_fail "T4: get_mount_point failed"
fi
else
record_fail "T4: probe failed"
fi
# T5: Error when instance exists but has no depots/cache/checkpoints*
mkdir -p "$SDPRoot/empty/bin"
if probe=$(find_p4depots_probe_path "$SDPRoot" "empty"); then
record_fail "T5: expected failure but got probe: $probe"
else
record_ok "T5: expected failure occurred (no depots/cache/checkpoints*)"
fi
# T6: Error when SDPRoot has no instances
EMPTYROOT="$WORKDIR/emptyroot"; mkdir -p "$EMPTYROOT"
if probe=$(find_p4depots_probe_path "$EMPTYROOT"); then
record_fail "T6: expected failure with empty SDPRoot but got probe: $probe"
else
record_ok "T6: expected failure with empty SDPRoot"
fi
# T7: Trailing slash check (explicit '1')
if probe=$(find_p4depots_probe_path "$SDPRoot" "1"); then
if [[ "${probe: -1}" == "/" ]]; then
record_ok "T7: trailing slash present"
else
record_fail "T7: trailing slash missing"
fi
else
record_fail "T7: probe failed"
fi
msg "\\n--------------------------------------------
Total tests: $TestCount
Passed: $PassCount
Failed: $FailCount"
if [[ "$FailCount" -eq 0 ]]; then
msg "PASS: ALL TESTS PASSED"
else
msg "FAIL: Some tests did not pass."
fi
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 32135 | C. Thomas Tyler |
Released SDP 2025.1.32133 (2025/10/29). Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'. |
||
| //guest/perforce_software/sdp/dev/test/bsw/test_sdp-mount-probe_1.sh | |||||
| #2 | 31886 | C. Thomas Tyler |
Refactoring non-trivial functions into a library utils.lib. Added test script. |
||
| #1 | 31883 | C. Thomas Tyler |
Enhanced backup script to be all-inclusive. Added first cut at a test script. |
||