Wren Linux

wren-linux / tools / test-retired.sh

#!/bin/bash
# Checks the retired extras whose installers are gone (the RETIRED list below).
# What is left of each is its --remove, for whoever still has one set
# up (update.sh and wrenctl remove offer it). Each is run here with a pretend sudo, systemctl, nft
# and the rest, in a temp home, and has to take out what its installer put in: the firewall rule
# and its service, the sudo rule, the commands, the users (asked about), and keep what holds
# your things. Nothing of this computer changes. Run by test.sh, or:
#   bash tools/test-retired.sh
# shellcheck disable=SC2016  # the pretend programs expand their own variables
HERE=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
T=$(mktemp -d) || { echo "  FAIL  couldn't make a temp folder (is /tmp full?)"; exit 1; }
trap 'rm -rf "$T"' EXIT
fails=0
check() { # DESCRIPTION CONDITION-COMMAND...
    local what=$1
    shift
    if "$@" >/dev/null 2>&1; then printf '  ok    %s\n' "$what"; else printf '  FAIL  %s\n' "$what"; fails=$((fails + 1)); fi
}
not() { ! "$@"; }

RETIRED="wallet-sandbox distro-vm opencode-vm claude-regular claude-code sparrow-wallet hardware-wallet simplex-chat"
R=$T/r
H=$T/home
mkdir -p "$R/extras" "$T/bin" "$H/.local/bin" "$H/.config"
sed 's|^export PATH=.*|export PATH="$RET_TEST_PATH"|' "$HERE/lib.sh" >"$R/lib.sh"
grep -q RET_TEST_PATH "$R/lib.sh" || { echo "  FAIL  lib.sh's PATH line wasn't found"; exit 1; }
for f in packages.sh pins.sh lib data bin docs; do ln -s "$HERE/$f" "$R/$f"; done
for x in $RETIRED; do cp "$HERE/extras/$x.sh" "$R/extras/"; done

# pretend programs: every call is written down; no user exists, no package is installed
for c in sudo systemctl nft udevadm userdel pkill rmdir setfacl visudo apt-get dpkg tor; do
    printf '#!/bin/bash\necho "%s $*" >>"%s/calls"\n' "$c" "$T" >"$T/bin/$c"
done
# sudo runs what it is given, as this user, but only writes down the commands that would change the system
cat >"$T/bin/sudo" <<EOF
#!/bin/bash
while [ "\${1#-}" != "\$1" ]; do shift; done
[ \$# -gt 0 ] || exit 0
echo "sudo \$*" >>"$T/calls"
EOF
# id: you are you; no other user exists (so none is asked about or deleted)
cat >"$T/bin/id" <<'EOF'
#!/bin/sh
case "$*" in "" | -u | -un | -g | -gn | "-u -n" | "-g -n") exec /usr/bin/id "$@" ;; *) exit 1 ;; esac
EOF
printf '#!/bin/sh\nexit 1\n' >"$T/bin/dpkg-query"
chmod +x "$T/bin/"*

run() { # NAME ARGS...: the retired extra, as a normal user
    local name=$1
    shift
    : >"$T/calls"
    env HOME="$H" PATH="$T/bin:$PATH" RET_TEST_PATH="$T/bin:$PATH" WREN_NONINTERACTIVE=1 bash "$R/extras/$name.sh" "$@" </dev/null >"$T/out" 2>&1
}

for x in $RETIRED; do
    f=$HERE/extras/$x.sh
    check "$x: it says why it is retired, in the line update.sh reads" grep -q '^# retired: ' "$f"
    check "...it has a summary of at most 52 characters and a status line" bash -c 's=$(sed -n "s/^# summary: //p" "$1"); [ -n "$s" ] && [ ${#s} -le 52 ] && grep -q "^# status: " "$1"' _ "$f"
    check "...it can no longer be installed (no --remove: it refuses)" bash -c '! env HOME="$2" RET_TEST_PATH="$3" bash "$1" </dev/null >/dev/null 2>&1' _ "$R/extras/$x.sh" "$H" "$T/bin:$PATH"
    check "...--manual says it is retired" grep -q 'Retired' <<<"$(env HOME="$H" RET_TEST_PATH="$T/bin:$PATH" bash "$R/extras/$x.sh" --manual 2>&1)"
    check "...nothing but --remove is left of it (no installer code)" not grep -qE 'apt_install|install_bin|add_claude_repo|add_mullvad|useradd' "$f"
    check "...its --remove runs through" run "$x" --remove
done

run wallet-sandbox --remove
check "wallet-sandbox --remove: the firewall rule and its service go" bash -c 'grep -q "nft delete table inet wren_wallet" "$1" && grep -q "disable --now wren-wallet-firewall.service" "$1"' _ "$T/calls"
check "...the sudo rule goes" grep -q 'rm -f /etc/sudoers.d/wren-wallet ' "$T/calls"
check "...but the wallets are never deleted, and it says where they are" bash -c '! grep -q "rm -rf /var/lib/wren-wallet" "$1" && grep -q "Your wallets are kept in /var/lib/wren-wallet" "$2"' _ "$T/calls" "$T/out"
run distro-vm --remove
check "distro-vm --remove: the firewall rule, its service and the sudo rule go" bash -c 'grep -q "nft delete table inet wren_distro_vm" "$1" && grep -q "disable --now wren-distro-vm-firewall.service" "$1" && grep -q "/etc/sudoers.d/wren-distro-vm" "$1"' _ "$T/calls"
run opencode-vm --remove
check "opencode-vm --remove: the firewall rule, its service and the sudo rule go" bash -c 'grep -q "nft delete table inet wren_opencode_vm" "$1" && grep -q "disable --now wren-opencode-vm-firewall.service" "$1" && grep -q "/etc/sudoers.d/wren-opencode-vm" "$1"' _ "$T/calls"
printf '#!/bin/sh\n# Written by Wren Linux extras/claude-regular.sh\n' >"$H/.local/bin/claude-regular"
printf '#!/bin/sh\n# Written by Wren Linux extras/claude-regular.sh\n' >"$H/.local/bin/claude-open-link"
printf '#!/bin/sh\necho mine\n' >"$H/.local/bin/claude-sandbox"
run claude-regular --remove
check "claude-regular --remove: its two commands go" bash -c '[ ! -e "$1/claude-regular" ] && [ ! -e "$1/claude-open-link" ]' _ "$H/.local/bin"
check "...and a command of yours that merely has a nearby name stays" test -e "$H/.local/bin/claude-sandbox"
printf '#!/bin/sh\n# Written by Wren Linux extras/claude-code.sh\n' >"$H/.local/bin/git"
printf '#!/bin/sh\n# Written by Wren Linux extras/claude-code.sh\n' >"$H/.local/bin/claude-sandbox"
run claude-code --remove
check "claude-code --remove: the firewall rule, its service and the sudo rule go" bash -c 'grep -q "nft delete table inet wren_claude" "$1" && grep -q "disable --now wren-claude-firewall.service" "$1" && grep -q "/etc/sudoers.d/wren-claude " "$1"' _ "$T/calls"
check "...the git guard and the sandboxed command go" bash -c '[ ! -e "$1/git" ] && [ ! -e "$1/claude-sandbox" ]' _ "$H/.local/bin"
check "...and what it was given is taken back, nothing in ~/projects is deleted" bash -c '! grep -q "rm -rf.*projects" "$1"' _ "$T/calls"
run sparrow-wallet --remove
check "sparrow-wallet --remove: nothing touches ~/.sparrow, and it says the wallets are kept there" bash -c '
    ! grep -q "\.sparrow" "$1" && grep -q "Your wallets are kept in ~/.sparrow" "$2"' _ "$T/calls" "$T/out"
run hardware-wallet --remove
check "hardware-wallet --remove: the udev rule goes, and udev is told" bash -c '
    grep -q "sudo rm -f /etc/udev/rules.d/60-wren-hardware-wallets.rules" "$1" && grep -q "udevadm control --reload-rules" "$1"' _ "$T/calls"
mkdir -p "$H/.local/opt/simplex" "$H/.local/share/simplex"
printf '#!/bin/sh\n# simplex: written by Wren Linux extras/simplex-chat.sh\n' >"$H/.local/bin/simplex"
run simplex-chat --remove
check "simplex-chat --remove: the unpacked AppImage and its command go, the chats never do, and it says so" bash -c '
    [ ! -e "$1/.local/opt/simplex" ] && [ ! -e "$1/.local/bin/simplex" ] && [ -d "$1/.local/share/simplex" ] && grep -q "chats and profile data are left in place" "$2"' _ "$H" "$T/out"
check "update.sh offers each by its status line: a computer that has one is asked" bash -c '
    for x in $2; do
        grep -q "^# status: " "$1/extras/$x.sh" || exit 1
    done' _ "$HERE" "$RETIRED"
check "they are all passed by shellcheck" bash -c '
    command -v shellcheck >/dev/null || exit 0
    files=(); for x in $2; do files+=("extras/$x.sh"); done
    cd "$1" && shellcheck -x "${files[@]}"' _ "$HERE" "$RETIRED"

[ "$fails" -eq 0 ]