1
0
mirror of https://github.com/tw93/Mole.git synced 2026-03-22 18:30:08 +00:00

Harden test mode against auth and uninstall side effects

This commit is contained in:
Tw93
2026-03-15 12:19:50 +08:00
parent 7a0b4cf07e
commit 30c1a95731
4 changed files with 101 additions and 34 deletions

View File

@@ -108,6 +108,11 @@ request_sudo_access() {
return 0
fi
# Tests must never trigger real password or Touch ID prompts.
if [[ "${MOLE_TEST_MODE:-0}" == "1" || "${MOLE_TEST_NO_AUTH:-0}" == "1" ]]; then
return 1
fi
# Detect if running in TTY environment
local tty_path="/dev/tty"
local is_gui_mode=false
@@ -299,6 +304,11 @@ ensure_sudo_session() {
return 0
fi
if [[ "${MOLE_TEST_MODE:-0}" == "1" || "${MOLE_TEST_NO_AUTH:-0}" == "1" ]]; then
MOLE_SUDO_ESTABLISHED="false"
return 1
fi
# Stop old keepalive if exists
if [[ -n "$MOLE_SUDO_KEEPALIVE_PID" ]]; then
_stop_sudo_keepalive "$MOLE_SUDO_KEEPALIVE_PID"

26
mole
View File

@@ -494,6 +494,10 @@ update_mole() {
# Remove flow (Homebrew + manual + config/cache).
remove_mole() {
local dry_run_mode="${1:-false}"
local test_mode=false
if [[ "${MOLE_TEST_MODE:-0}" == "1" ]]; then
test_mode=true
fi
if [[ -t 1 ]]; then
start_inline_spinner "Detecting Mole installations..."
@@ -507,6 +511,7 @@ remove_mole() {
local -a manual_installs=()
local -a alias_installs=()
if [[ "$test_mode" != "true" ]]; then
if command -v brew > /dev/null 2>&1; then
brew_cmd="brew"
elif [[ -x "/opt/homebrew/bin/brew" ]]; then
@@ -524,20 +529,29 @@ remove_mole() {
if [[ "$brew_has_mole" == "true" ]] || is_homebrew_install; then
is_homebrew=true
fi
fi
local found_mole
found_mole=""
if [[ "$test_mode" != "true" ]]; then
found_mole=$(command -v mole 2> /dev/null || true)
if [[ -n "$found_mole" && -f "$found_mole" ]]; then
if [[ ! -L "$found_mole" ]] || ! readlink "$found_mole" | grep -q "Cellar/mole"; then
manual_installs+=("$found_mole")
fi
fi
fi
local -a fallback_paths=(
local -a fallback_paths=()
if [[ "$test_mode" == "true" ]]; then
fallback_paths=("$HOME/.local/bin/mole")
else
fallback_paths=(
"/usr/local/bin/mole"
"$HOME/.local/bin/mole"
"/opt/local/bin/mole"
)
fi
for path in "${fallback_paths[@]}"; do
if [[ -f "$path" && "$path" != "$found_mole" ]]; then
@@ -548,18 +562,26 @@ remove_mole() {
done
local found_mo
found_mo=""
if [[ "$test_mode" != "true" ]]; then
found_mo=$(command -v mo 2> /dev/null || true)
if [[ -n "$found_mo" && -f "$found_mo" ]]; then
if [[ ! -L "$found_mo" ]] || ! readlink "$found_mo" | grep -q "Cellar/mole"; then
alias_installs+=("$found_mo")
fi
fi
fi
local -a alias_fallback=(
local -a alias_fallback=()
if [[ "$test_mode" == "true" ]]; then
alias_fallback=("$HOME/.local/bin/mo")
else
alias_fallback=(
"/usr/local/bin/mo"
"$HOME/.local/bin/mo"
"/opt/local/bin/mo"
)
fi
for alias in "${alias_fallback[@]}"; do
if [[ -f "$alias" && "$alias" != "$found_mo" ]]; then

View File

@@ -10,6 +10,9 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$PROJECT_ROOT"
# Never allow the scripted test run to trigger real sudo or Touch ID prompts.
export MOLE_TEST_NO_AUTH=1
# shellcheck source=lib/core/file_ops.sh
source "$PROJECT_ROOT/lib/core/file_ops.sh"

View File

@@ -362,7 +362,7 @@ EOF
touch "$HOME/.local/bin/mo"
mkdir -p "$HOME/.config/mole" "$HOME/.cache/mole"
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="/usr/bin:/bin" bash --noprofile --norc <<'EOF'
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="/usr/bin:/bin" MOLE_TEST_MODE=1 bash --noprofile --norc <<'EOF'
set -euo pipefail
start_inline_spinner() { :; }
stop_inline_spinner() { :; }
@@ -410,7 +410,7 @@ EOF
touch "$HOME/.local/bin/mo"
mkdir -p "$HOME/.config/mole" "$HOME/.cache/mole"
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="/usr/bin:/bin" bash --noprofile --norc <<'EOF'
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="/usr/bin:/bin" MOLE_TEST_MODE=1 bash --noprofile --norc <<'EOF'
set -euo pipefail
start_inline_spinner() { :; }
stop_inline_spinner() { :; }
@@ -425,3 +425,35 @@ EOF
[ -d "$HOME/.config/mole" ]
[ -d "$HOME/.cache/mole" ]
}
@test "remove_mole test mode ignores PATH installs outside test HOME" {
mkdir -p "$HOME/.local/bin" "$HOME/.config/mole" "$HOME/.cache/mole"
touch "$HOME/.local/bin/mole"
touch "$HOME/.local/bin/mo"
fake_global_bin="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-remove-path.XXXXXX")"
touch "$fake_global_bin/mole"
touch "$fake_global_bin/mo"
cat > "$fake_global_bin/brew" <<'EOF'
#!/bin/bash
exit 0
EOF
chmod +x "$fake_global_bin/brew"
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="$fake_global_bin:/usr/bin:/bin" MOLE_TEST_MODE=1 bash --noprofile --norc <<'EOF'
set -euo pipefail
start_inline_spinner() { :; }
stop_inline_spinner() { :; }
export -f start_inline_spinner stop_inline_spinner
printf '\n' | "$PROJECT_ROOT/mole" remove --dry-run
EOF
rm -rf "$fake_global_bin"
[ "$status" -eq 0 ]
[[ "$output" == *"$HOME/.local/bin/mole"* ]]
[[ "$output" == *"$HOME/.local/bin/mo"* ]]
[[ "$output" != *"$fake_global_bin/mole"* ]]
[[ "$output" != *"$fake_global_bin/mo"* ]]
[[ "$output" != *"brew uninstall --force mole"* ]]
}