#!/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 | |
---|---|---|---|---|---|
#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. |