144 lines
5.7 KiB
Bash
Executable File
144 lines
5.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
|
source "$SHELL_TEST_DIR/fixtures/sudo-boundary-test.sh"
|
|
copy_boundary_file bin/omarchy-channel-set
|
|
copy_boundary_file bin/omarchy-refresh-pacman
|
|
copy_boundary_file bin/omarchy-update
|
|
export OMARCHY_UPDATE_LOGGED=1
|
|
|
|
# Relocate the package root into the fixture, including the explicit handoff
|
|
# from the development checkout. All privileged operations remain stand-ins.
|
|
python3 - "$SUDO_TEST_ROOT/bin/omarchy-channel-set" "$SUDO_TEST_ROOT" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
p = Path(sys.argv[1])
|
|
p.write_text(p.read_text().replace('/usr/share/omarchy', sys.argv[2]))
|
|
PY
|
|
|
|
for command in omarchy-dev-link omarchy-dev-unlink omarchy-state gum git; do
|
|
cat >"$SUDO_TEST_ROOT/bin/$command" <<'STUB'
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
step=${0##*/}
|
|
printf 'step:%s %s\n' "$step" "$*" >>"$SUDO_TEST_LOG"
|
|
case "$step" in
|
|
omarchy-dev-link|omarchy-dev-unlink) sudo /usr/bin/true ;;
|
|
git)
|
|
[[ $1 == "clone" ]] || exit 90
|
|
/usr/bin/cp -a "$SUDO_TEST_ROOT" "${@: -1}"
|
|
mkdir -p "${@: -1}/.git" "${@: -1}/shell"
|
|
;;
|
|
esac
|
|
STUB
|
|
chmod +x "$SUDO_TEST_ROOT/bin/$command"
|
|
done
|
|
|
|
assert_scoped_channel() {
|
|
local label=$1
|
|
assert_boundary_cold "$label"
|
|
python3 - "$SUDO_TEST_LOG" <<'PY'
|
|
import sys
|
|
events = open(sys.argv[1]).read().splitlines()
|
|
assert events[0] == 'sudo -k', events
|
|
sudo = [event for event in events if event.startswith('sudo ')]
|
|
assert all(event in ('sudo -h', 'sudo -k') or event.startswith('sudo -N ') for event in sudo), events
|
|
hooks = [i for i, event in enumerate(events) if event.startswith('step:omarchy-hook ')]
|
|
assert len(hooks) == 2, events
|
|
assert events[hooks[-1]] == 'step:omarchy-hook pre-refresh-pacman', events
|
|
assert not any(event.startswith('sudo -N ') for event in events[hooks[0]:]), events
|
|
PY
|
|
}
|
|
|
|
run_channel() {
|
|
"$OMARCHY_PATH/bin/omarchy-channel-set" "$@" >"$boundary_tmp/output" 2>&1
|
|
}
|
|
for channel in stable rc edge dev; do
|
|
reset_boundary
|
|
run_channel "$channel" || fail "$channel failed" "$(<"$boundary_tmp/output")"
|
|
assert_scoped_channel "$channel"
|
|
pass "$channel starts cold, authorizes only individual commands, defers hooks and exits cold"
|
|
done
|
|
|
|
reset_boundary
|
|
wrapper="$SUDO_TEST_HOME/omarchy/default/omarchy/sudo-no-update/sudo"
|
|
mv "$wrapper" "$boundary_tmp/saved-wrapper"
|
|
if run_channel dev; then fail "an old checkout without the wrapper was accepted"; fi
|
|
if grep -Eq '^step:omarchy-(dev-link|state)|^sudo -N ' "$SUDO_TEST_LOG"; then
|
|
fail "an incompatible dev checkout changed the system before rejection"
|
|
fi
|
|
grep -q 'Update the checkout before switching to dev' "$boundary_tmp/output" || fail "stale checkout rejection lacks recovery guidance"
|
|
assert_boundary_cold "stale checkout"
|
|
mv "$boundary_tmp/saved-wrapper" "$wrapper"
|
|
pass "a stale dev checkout is rejected before linking or privileged work"
|
|
|
|
reset_boundary
|
|
OMARCHY_PATH="$SUDO_TEST_HOME/omarchy" run_channel stable || fail "leaving dev failed" "$(<"$boundary_tmp/output")"
|
|
assert_scoped_channel "dev to stable"
|
|
pass "leaving dev preserves no-update sudo through unlink and the packaged update"
|
|
|
|
mkdir "$boundary_tmp/user tools"
|
|
cat >"$boundary_tmp/user tools/channel-user-tool" <<'STUB'
|
|
#!/bin/bash
|
|
printf 'user-tool:%s\n' "$*" >>"$SUDO_TEST_LOG"
|
|
STUB
|
|
chmod +x "$boundary_tmp/user tools/channel-user-tool"
|
|
for command in omarchy-hook omarchy-update-mise; do
|
|
rm "$SUDO_TEST_ROOT/bin/$command"
|
|
cat >"$SUDO_TEST_ROOT/bin/$command" <<'STUB'
|
|
#!/bin/bash
|
|
[[ ! -e $SUDO_TEST_CACHE ]] || exit 91
|
|
[[ $(command -v sudo) == "$OMARCHY_PATH/default/omarchy/sudo-no-update/sudo" ]] || exit 92
|
|
channel-user-tool "${0##*/}" "$@"
|
|
STUB
|
|
chmod +x "$SUDO_TEST_ROOT/bin/$command"
|
|
done
|
|
reset_boundary
|
|
PATH="$boundary_tmp/user tools:$PATH" run_channel stable || fail "channel hooks lost the user's PATH" "$(<"$boundary_tmp/output")"
|
|
for event in 'omarchy-hook post-update' 'omarchy-update-mise' 'omarchy-hook pre-refresh-pacman'; do
|
|
grep -Fxq "user-tool:$event" "$SUDO_TEST_LOG" || fail "user PATH was not preserved for $event"
|
|
done
|
|
assert_boundary_cold "channel user PATH"
|
|
for command in omarchy-hook omarchy-update-mise; do
|
|
ln -sfn test-step "$SUDO_TEST_ROOT/bin/$command"
|
|
done
|
|
pass "channel switching preserves user tools behind the wrapper for both hooks and mise"
|
|
|
|
for step in pacman omarchy-update-system-pkgs omarchy-hook; do
|
|
reset_boundary
|
|
if SUDO_TEST_FAIL_STEP="$step" run_channel stable; then fail "$step failure was ignored"; fi
|
|
assert_boundary_cold "$step failure"
|
|
if grep -q '^step:omarchy-hook pre-refresh-pacman$' "$SUDO_TEST_LOG"; then fail "$step failure reached the deferred hook"; fi
|
|
pass "$step failure exits cold without the deferred hook"
|
|
done
|
|
|
|
for signal in HUP INT TERM; do
|
|
reset_boundary
|
|
cat >"$SUDO_TEST_ROOT/bin/omarchy-dev-unlink" <<'STUB'
|
|
#!/bin/bash
|
|
sudo /usr/bin/true || exit 1
|
|
kill -s "$SUDO_TEST_CHANNEL_SIGNAL" "$PPID"
|
|
STUB
|
|
if SUDO_TEST_CHANNEL_SIGNAL="$signal" run_channel stable; then fail "$signal was ignored"; fi
|
|
assert_boundary_cold "$signal"
|
|
if grep -q '^step:omarchy-hook ' "$SUDO_TEST_LOG"; then fail "$signal reached an update hook"; fi
|
|
pass "$signal stops the channel transition and revokes authorization"
|
|
done
|
|
|
|
for refusal in unsupported-sudo failed-revocation ordinary-bash; do
|
|
reset_boundary
|
|
case "$refusal" in
|
|
unsupported-sudo) export SUDO_TEST_UNSUPPORTED=1 ;;
|
|
failed-revocation) export SUDO_TEST_REVOKE_FAIL=1 ;;
|
|
esac
|
|
if [[ $refusal == "ordinary-bash" ]]; then
|
|
if /usr/bin/bash "$SUDO_TEST_ROOT/bin/omarchy-channel-set" -p >"$boundary_tmp/output" 2>&1; then fail "$refusal was accepted"; fi
|
|
elif run_channel stable; then
|
|
fail "$refusal was accepted"
|
|
fi
|
|
if grep -q '^step:' "$SUDO_TEST_LOG"; then fail "$refusal reached channel work"; fi
|
|
pass "$refusal is rejected before channel work"
|
|
done
|