Files
ProxMenux/scripts/post_install/tests/test_zram_profile_lifecycle.sh
T

287 lines
11 KiB
Bash

#!/bin/bash
set -euo pipefail
SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
REPO_ROOT="$(cd "$SCRIPT_ROOT/../.." && pwd)"
TEST_ROOT="$(mktemp -d)"
trap 'rm -rf "$TEST_ROOT"' EXIT
CONFIG="$TEST_ROOT/etc/systemd/zram-generator.conf.d/90-proxmenux.conf"
MARKER="$TEST_ROOT/state/zram-swap.state"
SWAPS="$TEST_ROOT/proc/swaps"
FSTAB="$TEST_ROOT/etc/fstab"
EXPECTED_FSTAB="$TEST_ROOT/fstab.expected"
VERIFY_MODE=0
START_COUNT=0
PURGE_COUNT=0
fail() {
printf 'FAIL: %s\n' "$*" >&2
exit 1
}
load_language() { :; }
initialize_cache() { :; }
translate() { printf '%s' "$1"; }
msg_info() { :; }
msg_info2() { :; }
msg_ok() { :; }
msg_warn() { :; }
msg_error() { printf '%s\n' "$*" >&2; }
msg_success() { :; }
show_proxmenux_logo() { :; }
clear() { :; }
pmx_install_pkg() { return 1; }
pmx_record_uninstall() { :; }
apt-get() {
if [[ "$*" == "purge -y systemd-zram-generator" ]]; then
PURGE_COUNT=$((PURGE_COUNT + 1))
fi
return 0
}
pmx_journal_context() { :; }
dpkg-query() {
case "$*" in
*'${Status}'*) printf 'install ok installed\n' ;;
*'${Version}'*) printf '1.2.0-1\n' ;;
*) return 1 ;;
esac
}
dpkg() {
[[ "$1" == "--compare-versions" && "$3" == "ge" && "$2" == "1.2.0-1" && "$4" == "1.2.0" ]]
}
systemctl() {
case "$1" in
daemon-reload|stop) return 0 ;;
start)
START_COUNT=$((START_COUNT + 1))
if [[ "${2:-}" == "dev-zram0.swap" ]] &&
! awk 'NR > 1 && $1 == "/dev/zram0" { found=1 } END { exit !found }' "$SWAPS"; then
printf '/dev/zram0\tpartition\t3355443\t0\t32767\n' >> "$SWAPS"
fi
return 0
;;
is-active) return 1 ;;
*) return 0 ;;
esac
}
swapoff() {
local target="${1:-}" next="$TEST_ROOT/swaps.next"
[[ -n "$target" ]] || fail "swapoff was called without a target"
awk -v target="$target" 'NR == 1 || $1 != target' "$SWAPS" > "$next"
mv "$next" "$SWAPS"
}
PMX_JOURNAL_ROOT="$TEST_ROOT/journal"
export PMX_JOURNAL_ROOT
source "$REPO_ROOT/scripts/global/pmx_journal.sh"
mkdir -p "$TEST_ROOT/host/scripts/post_install"
cp "$SCRIPT_ROOT/zram_profile_helpers.sh" "$TEST_ROOT/host/scripts/post_install/"
# Isolate only host paths; source the real installer function and helper library.
python3 - "$SCRIPT_ROOT/customizable_post_install.sh" "$TEST_ROOT/customizable.sh" "$TEST_ROOT" <<'PY'
from pathlib import Path
import sys
source_path, output_path, root = map(Path, sys.argv[1:])
text = source_path.read_text(encoding="utf-8")
def replace_exact(old, new, expected=1):
global text
count = text.count(old)
if count != expected:
raise SystemExit(f"expected {expected} path substitutions, found {count}: {old}")
text = text.replace(old, new)
replace_exact(
'LOCAL_SCRIPTS="/usr/local/share/proxmenux/scripts"',
f'LOCAL_SCRIPTS="{root}/host/scripts"',
)
replace_exact(
'BASE_DIR="/usr/local/share/proxmenux"',
f'BASE_DIR="{root}/state"',
)
replace_exact(
'UTILS_FILE="$BASE_DIR/utils.sh"',
f'UTILS_FILE="{root}/missing-utils.sh"',
)
replace_exact(
'TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json"',
f'TOOLS_JSON="{root}/state/installed_tools.json"',
)
replace_exact(
'local config=/etc/systemd/zram-generator.conf.d/90-proxmenux.conf',
f'local config={root}/etc/systemd/zram-generator.conf.d/90-proxmenux.conf',
)
replace_exact(
'if [[ ! -r /proc/swaps || ! -r /etc/fstab ]]; then',
f'if [[ ! -r "{root}/proc/swaps" || ! -r "{root}/etc/fstab" ]]; then',
)
replace_exact(
'zram_list_foreign_active_zram_swap /proc/swaps "$allowed_zram"',
f'zram_list_foreign_active_zram_swap "{root}/proc/swaps" "$allowed_zram"',
)
replace_exact(
'zram_list_foreign_fstab_zram_swap /etc/fstab',
f'zram_list_foreign_fstab_zram_swap "{root}/etc/fstab"',
)
replace_exact(
'zram_list_foreign_systemd_zram_units)',
'zram_list_foreign_systemd_zram_units "$TEST_ROOT")',
)
replace_exact(
'zram_foreign_generator_config "$config"',
'zram_foreign_generator_config "$config" "$TEST_ROOT"',
expected=3,
)
replace_exact(
"awk 'NR > 1 && $1 == \"/dev/zram0\" { found=1 } END { exit !found }' /proc/swaps",
f"awk 'NR > 1 && $1 == \"/dev/zram0\" {{ found=1 }} END {{ exit !found }}' \"{root}/proc/swaps\"",
expected=2,
)
output_path.write_text(text, encoding="utf-8")
PY
# Isolate the real uninstall function and redirect only the paths it inspects.
python3 - "$SCRIPT_ROOT/uninstall-tools.sh" "$TEST_ROOT/uninstall-zram.sh" "$TEST_ROOT" <<'PY'
from pathlib import Path
import sys
source_path, output_path, root = map(Path, sys.argv[1:])
text = source_path.read_text(encoding="utf-8")
start = text.index("uninstall_zram_swap() {")
end = text.index("\n}\n", start) + 3
function = text[start:end]
replacements = {
"local config=/etc/systemd/zram-generator.conf.d/90-proxmenux.conf":
f"local config={root}/etc/systemd/zram-generator.conf.d/90-proxmenux.conf",
'awk \'NR > 1 && $1 == "/dev/zram0" { found=1 } END { exit !found }\' /proc/swaps':
f'awk \'NR > 1 && $1 == "/dev/zram0" {{ found=1 }} END {{ exit !found }}\' "{root}/proc/swaps"',
'zram_foreign_generator_config "$config"':
'zram_foreign_generator_config "$config" "$TEST_ROOT"',
'zram_list_foreign_active_zram_swap /proc/swaps /dev/zram0':
f'zram_list_foreign_active_zram_swap "{root}/proc/swaps" /dev/zram0',
'zram_list_foreign_fstab_zram_swap /etc/fstab':
f'zram_list_foreign_fstab_zram_swap "{root}/etc/fstab"',
'zram_list_foreign_systemd_zram_units)':
'zram_list_foreign_systemd_zram_units "$TEST_ROOT")',
}
for old, new in replacements.items():
if function.count(old) != 1:
raise SystemExit(f"expected one uninstall path to rewrite: {old}")
function = function.replace(old, new)
output_path.write_text(function, encoding="utf-8")
PY
source "$TEST_ROOT/customizable.sh"
source "$TEST_ROOT/uninstall-zram.sh"
BASE_DIR="$TEST_ROOT/state"
TOOLS_JSON="$TEST_ROOT/state/installed_tools.json"
mkdir -p "$BASE_DIR"
register_tool() { printf '%s|%s|%s\n' "$1" "$2" "${3:-}" >> "$TEST_ROOT/registry.log"; }
zram_profile_verify_active() { return "$VERIFY_MODE"; }
reset_fixture() {
rm -rf "$TEST_ROOT/etc" "$TEST_ROOT/run" "$TEST_ROOT/proc" "$BASE_DIR" "$TEST_ROOT/journal"
mkdir -p "$TEST_ROOT/etc/systemd/system" "$TEST_ROOT/proc" "$BASE_DIR" "$TEST_ROOT/run/systemd/system"
printf 'Filename\tType\tSize\tUsed\tPriority\n/dev/nvme0n1p3\tpartition\t1048576\t8\t-2\n' > "$SWAPS"
printf '/dev/nvme0n1p3 none swap defaults 0 0\n/swapfile none swap sw 0 0\n' > "$FSTAB"
cp "$FSTAB" "$EXPECTED_FSTAB"
printf '[Swap]\nWhat=/dev/mapper/pve-swap\n' > "$TEST_ROOT/etc/systemd/system/pve-swap.swap"
PMX_JOURNAL_ROOT="$TEST_ROOT/journal"
START_COUNT=0
PURGE_COUNT=0
VERIFY_MODE=0
: > "$TEST_ROOT/registry.log"
}
assert_disk_swap_unchanged() {
cmp -s "$FSTAB" "$EXPECTED_FSTAB" || fail "installer changed fstab"
grep -Fq '/dev/nvme0n1p3' "$SWAPS" || fail "active disk swap was removed"
}
reset_fixture
configure_zram_swap || fail "disk swap prevented ZRAM installation"
grep -Fq 'swap-priority = 32767' "$CONFIG" || fail "ZRAM priority is not maximal"
grep -Fq 'installed_by_proxmenux=false' "$MARKER" || fail "package ownership was not preserved"
grep -Fq '/dev/zram0' "$SWAPS" || fail "ZRAM did not become active"
assert_disk_swap_unchanged
configure_zram_swap || fail "owned ZRAM profile could not be re-applied with disk swap"
[[ "$START_COUNT" -eq 1 ]] || fail "matching owned profile was not idempotent"
assert_disk_swap_unchanged
printf 'PASS: disk swap coexists and owned profile is idempotent\n'
reset_fixture
printf '/dev/zram1 none swap defaults 0 0\n' >> "$FSTAB"
cp "$FSTAB" "$EXPECTED_FSTAB"
if configure_zram_swap; then
fail "foreign fstab ZRAM entry was accepted"
fi
[[ ! -e "$CONFIG" && ! -e "$MARKER" ]] || fail "foreign fstab ZRAM entry left partial profile state"
assert_disk_swap_unchanged
printf 'PASS: foreign fstab ZRAM setup is refused without changing disk swap\n'
reset_fixture
printf '%s\n' '[Swap]' 'What=/dev/zram1' > "$TEST_ROOT/etc/systemd/system/external-zram.swap"
if configure_zram_swap; then
fail "foreign systemd ZRAM unit was accepted"
fi
[[ ! -e "$CONFIG" && ! -e "$MARKER" ]] || fail "foreign systemd ZRAM unit left partial profile state"
assert_disk_swap_unchanged
printf 'PASS: foreign systemd ZRAM unit is refused without changing disk swap\n'
reset_fixture
VERIFY_MODE=1
if configure_zram_swap; then
fail "activation verification failure was reported as success"
fi
[[ ! -e "$CONFIG" && ! -e "$MARKER" ]] || fail "failed activation left partial profile state"
if awk 'NR > 1 && $1 == "/dev/zram0" { found=1 } END { exit !found }' "$SWAPS"; then
fail "rollback left the failed ZRAM device active"
fi
assert_disk_swap_unchanged
printf 'PASS: verification failure rolls back only the ProxMenux ZRAM state\n'
reset_fixture
mkdir -p "$(dirname "$CONFIG")"
printf '# ProxMenux ZRAM profile\n[zram0]\nzram-size = ram / 10\n' > "$CONFIG"
printf 'installed_by_proxmenux=true\n' > "$MARKER"
printf '/dev/zram1 none swap defaults 0 0\n' >> "$FSTAB"
printf '[Swap]\nWhat=/dev/zram2\n' > "$TEST_ROOT/etc/systemd/system/external-zram.swap"
cp "$FSTAB" "$EXPECTED_FSTAB"
uninstall_zram_swap || fail "profile uninstall failed with foreign ZRAM configuration"
[[ "$PURGE_COUNT" -eq 0 ]] || fail "uninstaller purged generator while foreign ZRAM config exists"
[[ ! -e "$CONFIG" && ! -e "$MARKER" ]] || fail "uninstaller left ProxMenux profile files behind"
assert_disk_swap_unchanged
printf 'PASS: uninstall retains generator when foreign ZRAM config exists\n'
reset_fixture
mkdir -p "$(dirname "$CONFIG")"
printf '# ProxMenux ZRAM profile\n[zram0]\nzram-size = ram / 10\n' > "$CONFIG"
printf 'installed_by_proxmenux=true\n' > "$MARKER"
printf '%s\n' '[Swap]' 'What=/dev/zram2' > "$TEST_ROOT/etc/systemd/system/external-zram.swap"
uninstall_zram_swap || fail "profile uninstall failed with foreign systemd ZRAM unit"
[[ "$PURGE_COUNT" -eq 0 ]] || fail "uninstaller purged generator while foreign systemd ZRAM unit exists"
assert_disk_swap_unchanged
printf 'PASS: uninstall retains generator for foreign systemd ZRAM unit\n'
reset_fixture
mkdir -p "$(dirname "$CONFIG")"
printf '# ProxMenux ZRAM profile\n[zram0]\nzram-size = ram / 10\n' > "$CONFIG"
printf 'installed_by_proxmenux=true\n' > "$MARKER"
printf '/dev/zram0\tpartition\t3355443\t8\t32767\n' >> "$SWAPS"
uninstall_zram_swap || fail "owned profile could not be uninstalled"
[[ "$PURGE_COUNT" -eq 1 ]] || fail "owned generator package was not purged"
if awk 'NR > 1 && $1 == "/dev/zram0" { found=1 } END { exit !found }' "$SWAPS"; then
fail "uninstaller left ProxMenux ZRAM active"
fi
assert_disk_swap_unchanged
printf 'PASS: uninstall removes owned ZRAM and preserves disk swap\n'