#!/bin/bash # Self-contained unit test for the storage-location primitives in # scripts/source/paths.sh. Runs against a throwaway tree in $TMPDIR — never # touches a real install. No arguments; exits non-zero on the first failure. # # scripts/dev/lp-storage-test # # The case worth keeping honest is the last one: an app whose drive is not # mounted must resolve to the sentinel, NOT to the primary root. Silently # falling back is how an app gets rebuilt empty on the wrong disk. REPO="$(cd "$(dirname "$0")/../.." && pwd)" BASE="$(mktemp -d "${TMPDIR:-/tmp}/lp-storage-test-XXXXXX")" trap 'rm -rf "$BASE"' EXIT export LP_SYSTEM_DIR="$BASE/sys" export LP_CONTAINERS_DIR="$BASE/primary" export LP_BACKUPS_DIR="$BASE/bk" export LP_STORAGE_REGISTRY="$BASE/storage.roots" mkdir -p "$BASE/primary" "$BASE/disk2" "$BASE/sys/configs" source "$REPO/scripts/source/paths.sh" fail=0 chk(){ if [[ "$2" == "$3" ]]; then echo " ok $1"; else echo " FAIL $1: got '$2' want '$3'"; fail=1; fi; } echo "--- no registry (behaves exactly like the old single-root code) ---" chk "primaryRoot" "$(primaryRoot)" "$BASE/primary" chk "webuiDir" "$(webuiDir)" "$BASE/primary/libreportal" chk "roots" "$(storageRoots)" "$BASE/primary" chk "appDir new" "$(appDir bookstack)" "$BASE/primary/bookstack" pathIsContainerData "$BASE/primary/bookstack/x" && echo " ok pathIsContainerData inside" || { echo " FAIL inside"; fail=1; } pathIsContainerData "$BASE/sys/configs" && { echo " FAIL outside matched"; fail=1; } || echo " ok pathIsContainerData outside" echo "--- discovery: app deployed on the primary root ---" mkdir -p "$BASE/primary/bookstack" && : > "$BASE/primary/bookstack/bookstack.config" storageCacheReset chk "appDir found" "$(appDir bookstack)" "$BASE/primary/bookstack" echo "--- second root, mounted (marker present) ---" printf '2\t%s\t0:0\tuuid-2\n' "$BASE/disk2" > "$BASE/storage.roots" : > "$BASE/disk2/.libreportal-storage" mkdir -p "$BASE/disk2/nextcloud" && : > "$BASE/disk2/nextcloud/nextcloud.config" storageCacheReset chk "roots both" "$(storageRoots | tr '\n' ' ')" "$BASE/primary $BASE/disk2 " chk "appDir disk2" "$(appDir nextcloud)" "$BASE/disk2/nextcloud" chk "appDir primary still" "$(appDir bookstack)" "$BASE/primary/bookstack" pathIsContainerData "$BASE/disk2/nextcloud" && echo " ok pathIsContainerData disk2" || { echo " FAIL disk2"; fail=1; } chk "locName disk2" "$(storageLocationName "$BASE/disk2")" "2" chk "locPath by id" "$(storageLocationPath 2)" "$BASE/disk2" CFG_STORAGE_LOC_2_NAME="bigdisk" chk "locPath by name" "$(storageLocationPath bigdisk)" "$BASE/disk2" chk "locName friendly" "$(storageLocationName "$BASE/disk2")" "bigdisk" echo "--- intent for an app not yet deployed ---" CFG_JELLYFIN_STORAGE="bigdisk" storageCacheReset chk "appDir intent" "$(appDir jellyfin)" "$BASE/disk2/jellyfin" echo "--- drive unmounted: marker gone ---" rm -f "$BASE/disk2/.libreportal-storage" storageCacheReset out=$(appDir nextcloud); rc=$? chk "appDir sentinel" "$out" "/nonexistent-libreportal-unavailable/nextcloud" chk "appDir rc" "$rc" "1" appStorageAvailable nextcloud && { echo " FAIL available"; fail=1; } || echo " ok appStorageAvailable false" appStorageAvailable bookstack && echo " ok primary still available" || { echo " FAIL primary"; fail=1; } storageRootAvailable "$BASE/disk2" && { echo " FAIL root available"; fail=1; } || echo " ok storageRootAvailable false" echo; [[ $fail -eq 0 ]] && echo "ALL PASS" || echo "FAILURES"; exit $fail