mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 13:16:47 +00:00
refactor: improve brew cleanup timeout handling and remove app_caches, clean_extras, and optimize_core tests.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,6 +25,7 @@ temp/
|
|||||||
*.tmp
|
*.tmp
|
||||||
*.temp
|
*.temp
|
||||||
*.dmg
|
*.dmg
|
||||||
|
tests/tmp-*
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
.cache/
|
.cache/
|
||||||
|
|||||||
@@ -43,41 +43,32 @@ clean_homebrew() {
|
|||||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Homebrew cleanup and autoremove..."
|
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Homebrew cleanup and autoremove..."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# Run cleanup/autoremove in parallel with a timeout guard.
|
# Run cleanup/autoremove in parallel with timeout guard per command.
|
||||||
local timeout_seconds=${MO_BREW_TIMEOUT:-120}
|
local timeout_seconds=${MO_BREW_TIMEOUT:-120}
|
||||||
local brew_tmp_file autoremove_tmp_file
|
local brew_tmp_file autoremove_tmp_file
|
||||||
local brew_pid autoremove_pid
|
local brew_pid autoremove_pid
|
||||||
|
local brew_exit=0
|
||||||
|
local autoremove_exit=0
|
||||||
if [[ "$skip_cleanup" == "false" ]]; then
|
if [[ "$skip_cleanup" == "false" ]]; then
|
||||||
brew_tmp_file=$(create_temp_file)
|
brew_tmp_file=$(create_temp_file)
|
||||||
(brew cleanup > "$brew_tmp_file" 2>&1) &
|
run_with_timeout "$timeout_seconds" brew cleanup > "$brew_tmp_file" 2>&1 &
|
||||||
brew_pid=$!
|
brew_pid=$!
|
||||||
fi
|
fi
|
||||||
autoremove_tmp_file=$(create_temp_file)
|
autoremove_tmp_file=$(create_temp_file)
|
||||||
(brew autoremove > "$autoremove_tmp_file" 2>&1) &
|
run_with_timeout "$timeout_seconds" brew autoremove > "$autoremove_tmp_file" 2>&1 &
|
||||||
autoremove_pid=$!
|
autoremove_pid=$!
|
||||||
local elapsed=0
|
|
||||||
local brew_done=false
|
if [[ -n "$brew_pid" ]]; then
|
||||||
local autoremove_done=false
|
wait "$brew_pid" 2> /dev/null || brew_exit=$?
|
||||||
[[ "$skip_cleanup" == "true" ]] && brew_done=true
|
|
||||||
while [[ "$brew_done" == "false" ]] || [[ "$autoremove_done" == "false" ]]; do
|
|
||||||
if [[ $elapsed -ge $timeout_seconds ]]; then
|
|
||||||
[[ -n "$brew_pid" ]] && kill -TERM $brew_pid 2> /dev/null || true
|
|
||||||
kill -TERM $autoremove_pid 2> /dev/null || true
|
|
||||||
break
|
|
||||||
fi
|
fi
|
||||||
[[ -n "$brew_pid" ]] && { kill -0 $brew_pid 2> /dev/null || brew_done=true; }
|
wait "$autoremove_pid" 2> /dev/null || autoremove_exit=$?
|
||||||
kill -0 $autoremove_pid 2> /dev/null || autoremove_done=true
|
|
||||||
sleep 1
|
|
||||||
((elapsed++))
|
|
||||||
done
|
|
||||||
local brew_success=false
|
local brew_success=false
|
||||||
if [[ "$skip_cleanup" == "false" && -n "$brew_pid" ]]; then
|
if [[ "$skip_cleanup" == "false" && $brew_exit -eq 0 ]]; then
|
||||||
if wait $brew_pid 2> /dev/null; then
|
|
||||||
brew_success=true
|
brew_success=true
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
local autoremove_success=false
|
local autoremove_success=false
|
||||||
if wait $autoremove_pid 2> /dev/null; then
|
if [[ $autoremove_exit -eq 0 ]]; then
|
||||||
autoremove_success=true
|
autoremove_success=true
|
||||||
fi
|
fi
|
||||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||||
@@ -100,7 +91,7 @@ clean_homebrew() {
|
|||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Homebrew cleanup (${removed_count} items)"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Homebrew cleanup (${removed_count} items)"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
elif [[ $elapsed -ge $timeout_seconds ]]; then
|
elif [[ $brew_exit -eq 124 ]]; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Homebrew cleanup timed out · run ${GRAY}brew cleanup${NC} manually"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Homebrew cleanup timed out · run ${GRAY}brew cleanup${NC} manually"
|
||||||
fi
|
fi
|
||||||
# Process autoremove output - only show if packages were removed
|
# Process autoremove output - only show if packages were removed
|
||||||
@@ -113,7 +104,7 @@ clean_homebrew() {
|
|||||||
if [[ $removed_packages -gt 0 ]]; then
|
if [[ $removed_packages -gt 0 ]]; then
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed orphaned dependencies (${removed_packages} packages)"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed orphaned dependencies (${removed_packages} packages)"
|
||||||
fi
|
fi
|
||||||
elif [[ $elapsed -ge $timeout_seconds ]]; then
|
elif [[ $autoremove_exit -eq 124 ]]; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Autoremove timed out · run ${GRAY}brew autoremove${NC} manually"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Autoremove timed out · run ${GRAY}brew autoremove${NC} manually"
|
||||||
fi
|
fi
|
||||||
# Update cache timestamp on successful completion or when cleanup was intelligently skipped
|
# Update cache timestamp on successful completion or when cleanup was intelligently skipped
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
setup_file() {
|
|
||||||
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
|
|
||||||
export PROJECT_ROOT
|
|
||||||
|
|
||||||
ORIGINAL_HOME="${HOME:-}"
|
|
||||||
export ORIGINAL_HOME
|
|
||||||
|
|
||||||
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-app-caches.XXXXXX")"
|
|
||||||
export HOME
|
|
||||||
|
|
||||||
mkdir -p "$HOME"
|
|
||||||
}
|
|
||||||
|
|
||||||
teardown_file() {
|
|
||||||
rm -rf "$HOME"
|
|
||||||
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
|
|
||||||
export HOME="$ORIGINAL_HOME"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_xcode_tools skips derived data when Xcode running" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
pgrep() { return 0; }
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_xcode_tools
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Xcode is running"* ]]
|
|
||||||
[[ "$output" != *"derived data"* ]]
|
|
||||||
[[ "$output" != *"archives"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_media_players protects spotify offline cache" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
mkdir -p "$HOME/Library/Application Support/Spotify/PersistentCache/Storage"
|
|
||||||
touch "$HOME/Library/Application Support/Spotify/PersistentCache/Storage/offline.bnk"
|
|
||||||
safe_clean() { echo "CLEAN:$2"; }
|
|
||||||
clean_media_players
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Spotify cache protected"* ]]
|
|
||||||
[[ "$output" != *"CLEAN: Spotify cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_user_gui_applications calls all sections" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
stop_section_spinner() { :; }
|
|
||||||
safe_clean() { :; }
|
|
||||||
clean_xcode_tools() { echo "xcode"; }
|
|
||||||
clean_code_editors() { echo "editors"; }
|
|
||||||
clean_communication_apps() { echo "comm"; }
|
|
||||||
clean_user_gui_applications
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"xcode"* ]]
|
|
||||||
[[ "$output" == *"editors"* ]]
|
|
||||||
[[ "$output" == *"comm"* ]]
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ setup_file() {
|
|||||||
ORIGINAL_HOME="${HOME:-}"
|
ORIGINAL_HOME="${HOME:-}"
|
||||||
export ORIGINAL_HOME
|
export ORIGINAL_HOME
|
||||||
|
|
||||||
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-app-caches-more.XXXXXX")"
|
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-app-caches.XXXXXX")"
|
||||||
export HOME
|
export HOME
|
||||||
|
|
||||||
mkdir -p "$HOME"
|
mkdir -p "$HOME"
|
||||||
@@ -20,6 +20,57 @@ teardown_file() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "clean_xcode_tools skips derived data when Xcode running" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
pgrep() { return 0; }
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_xcode_tools
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Xcode is running"* ]]
|
||||||
|
[[ "$output" != *"derived data"* ]]
|
||||||
|
[[ "$output" != *"archives"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_media_players protects spotify offline cache" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
mkdir -p "$HOME/Library/Application Support/Spotify/PersistentCache/Storage"
|
||||||
|
touch "$HOME/Library/Application Support/Spotify/PersistentCache/Storage/offline.bnk"
|
||||||
|
safe_clean() { echo "CLEAN:$2"; }
|
||||||
|
clean_media_players
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Spotify cache protected"* ]]
|
||||||
|
[[ "$output" != *"CLEAN: Spotify cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_user_gui_applications calls all sections" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" /bin/bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
stop_section_spinner() { :; }
|
||||||
|
safe_clean() { :; }
|
||||||
|
clean_xcode_tools() { echo "xcode"; }
|
||||||
|
clean_code_editors() { echo "editors"; }
|
||||||
|
clean_communication_apps() { echo "comm"; }
|
||||||
|
clean_user_gui_applications
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"xcode"* ]]
|
||||||
|
[[ "$output" == *"editors"* ]]
|
||||||
|
[[ "$output" == *"comm"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
@test "clean_ai_apps calls expected caches" {
|
@test "clean_ai_apps calls expected caches" {
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -74,8 +74,27 @@ EOF
|
|||||||
skip "Homebrew not installed"
|
skip "Homebrew not installed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
run env HOME="$HOME" MO_BREW_TIMEOUT=5 "$PROJECT_ROOT/bin/clean.sh" --dry-run
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/brew.sh"
|
||||||
|
|
||||||
|
MO_BREW_TIMEOUT=5
|
||||||
|
CALL_LOG="$HOME/timeout.log"
|
||||||
|
|
||||||
|
run_with_timeout() {
|
||||||
|
echo "$1" >> "$CALL_LOG"
|
||||||
|
shift
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
brew() { return 0; }
|
||||||
|
|
||||||
|
clean_homebrew
|
||||||
|
cat "$CALL_LOG"
|
||||||
|
EOF
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"5"* ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "FINDER_METADATA_SENTINEL in whitelist protects .DS_Store files" {
|
@test "FINDER_METADATA_SENTINEL in whitelist protects .DS_Store files" {
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
setup_file() {
|
|
||||||
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
|
|
||||||
export PROJECT_ROOT
|
|
||||||
|
|
||||||
ORIGINAL_HOME="${HOME:-}"
|
|
||||||
export ORIGINAL_HOME
|
|
||||||
|
|
||||||
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-clean-extras.XXXXXX")"
|
|
||||||
export HOME
|
|
||||||
|
|
||||||
mkdir -p "$HOME"
|
|
||||||
}
|
|
||||||
|
|
||||||
teardown_file() {
|
|
||||||
rm -rf "$HOME"
|
|
||||||
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
|
|
||||||
export HOME="$ORIGINAL_HOME"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_cloud_storage calls expected caches" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/user.sh"
|
|
||||||
stop_section_spinner() { :; }
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_cloud_storage
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Dropbox cache"* ]]
|
|
||||||
[[ "$output" == *"Google Drive cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_virtualization_tools hits cache paths" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/user.sh"
|
|
||||||
stop_section_spinner() { :; }
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_virtualization_tools
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"VMware Fusion cache"* ]]
|
|
||||||
[[ "$output" == *"Parallels cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_email_clients calls expected caches" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_email_clients
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Spark cache"* ]]
|
|
||||||
[[ "$output" == *"Airmail cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_note_apps calls expected caches" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_note_apps
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Notion cache"* ]]
|
|
||||||
[[ "$output" == *"Obsidian cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "clean_task_apps calls expected caches" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
|
||||||
safe_clean() { echo "$2"; }
|
|
||||||
clean_task_apps
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"Todoist cache"* ]]
|
|
||||||
[[ "$output" == *"Any.do cache"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "scan_external_volumes skips when no volumes" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/clean/user.sh"
|
|
||||||
run_with_timeout() { return 1; }
|
|
||||||
scan_external_volumes
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ setup_file() {
|
|||||||
ORIGINAL_HOME="${HOME:-}"
|
ORIGINAL_HOME="${HOME:-}"
|
||||||
export ORIGINAL_HOME
|
export ORIGINAL_HOME
|
||||||
|
|
||||||
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-clean-extras-more.XXXXXX")"
|
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-clean-extras.XXXXXX")"
|
||||||
export HOME
|
export HOME
|
||||||
|
|
||||||
mkdir -p "$HOME"
|
mkdir -p "$HOME"
|
||||||
@@ -20,6 +20,87 @@ teardown_file() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "clean_cloud_storage calls expected caches" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/user.sh"
|
||||||
|
stop_section_spinner() { :; }
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_cloud_storage
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Dropbox cache"* ]]
|
||||||
|
[[ "$output" == *"Google Drive cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_virtualization_tools hits cache paths" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/user.sh"
|
||||||
|
stop_section_spinner() { :; }
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_virtualization_tools
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"VMware Fusion cache"* ]]
|
||||||
|
[[ "$output" == *"Parallels cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_email_clients calls expected caches" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_email_clients
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Spark cache"* ]]
|
||||||
|
[[ "$output" == *"Airmail cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_note_apps calls expected caches" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_note_apps
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Notion cache"* ]]
|
||||||
|
[[ "$output" == *"Obsidian cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_task_apps calls expected caches" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/clean/app_caches.sh"
|
||||||
|
safe_clean() { echo "$2"; }
|
||||||
|
clean_task_apps
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Todoist cache"* ]]
|
||||||
|
[[ "$output" == *"Any.do cache"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "scan_external_volumes skips when no volumes" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/user.sh"
|
||||||
|
run_with_timeout() { return 1; }
|
||||||
|
scan_external_volumes
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
@test "clean_video_tools calls expected caches" {
|
@test "clean_video_tools calls expected caches" {
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -234,14 +234,20 @@ source "$PROJECT_ROOT/lib/clean/brew.sh"
|
|||||||
mkdir -p "$HOME/.cache/mole"
|
mkdir -p "$HOME/.cache/mole"
|
||||||
rm -f "$HOME/.cache/mole/brew_last_cleanup"
|
rm -f "$HOME/.cache/mole/brew_last_cleanup"
|
||||||
|
|
||||||
mkdir -p "$HOME/Library/Caches/Homebrew"
|
|
||||||
dd if=/dev/zero of="$HOME/Library/Caches/Homebrew/test.tar.gz" bs=1024 count=51200 2>/dev/null
|
|
||||||
|
|
||||||
MO_BREW_TIMEOUT=2
|
|
||||||
|
|
||||||
start_inline_spinner(){ :; }
|
start_inline_spinner(){ :; }
|
||||||
stop_inline_spinner(){ :; }
|
stop_inline_spinner(){ :; }
|
||||||
note_activity(){ :; }
|
note_activity(){ :; }
|
||||||
|
run_with_timeout() {
|
||||||
|
local duration="$1"
|
||||||
|
shift
|
||||||
|
if [[ "$1" == "du" ]]; then
|
||||||
|
echo "51201 $3"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
MO_BREW_TIMEOUT=2
|
||||||
|
|
||||||
brew() {
|
brew() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -260,8 +266,6 @@ brew() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clean_homebrew
|
clean_homebrew
|
||||||
|
|
||||||
rm -rf "$HOME/Library/Caches/Homebrew"
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
@@ -20,6 +20,73 @@ teardown_file() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "needs_permissions_repair returns true when home not writable" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" USER="tester" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
||||||
|
stat() { echo "root"; }
|
||||||
|
export -f stat
|
||||||
|
if needs_permissions_repair; then
|
||||||
|
echo "needs"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"needs"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "has_bluetooth_hid_connected detects HID" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
||||||
|
system_profiler() {
|
||||||
|
cat << 'OUT'
|
||||||
|
Bluetooth:
|
||||||
|
Apple Magic Mouse:
|
||||||
|
Connected: Yes
|
||||||
|
Type: Mouse
|
||||||
|
OUT
|
||||||
|
}
|
||||||
|
export -f system_profiler
|
||||||
|
if has_bluetooth_hid_connected; then
|
||||||
|
echo "hid"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"hid"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "is_ac_power detects AC power" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
||||||
|
pmset() { echo "AC Power"; }
|
||||||
|
export -f pmset
|
||||||
|
if is_ac_power; then
|
||||||
|
echo "ac"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"ac"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "is_memory_pressure_high detects warning" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
||||||
|
memory_pressure() { echo "warning"; }
|
||||||
|
export -f memory_pressure
|
||||||
|
if is_memory_pressure_high; then
|
||||||
|
echo "high"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"high"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
@test "opt_system_maintenance reports DNS and Spotlight" {
|
@test "opt_system_maintenance reports DNS and Spotlight" {
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF'
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
setup_file() {
|
|
||||||
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
|
|
||||||
export PROJECT_ROOT
|
|
||||||
|
|
||||||
ORIGINAL_HOME="${HOME:-}"
|
|
||||||
export ORIGINAL_HOME
|
|
||||||
|
|
||||||
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-optimize-core.XXXXXX")"
|
|
||||||
export HOME
|
|
||||||
|
|
||||||
mkdir -p "$HOME"
|
|
||||||
}
|
|
||||||
|
|
||||||
teardown_file() {
|
|
||||||
rm -rf "$HOME"
|
|
||||||
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
|
|
||||||
export HOME="$ORIGINAL_HOME"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "needs_permissions_repair returns true when home not writable" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" USER="tester" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
stat() { echo "root"; }
|
|
||||||
export -f stat
|
|
||||||
if needs_permissions_repair; then
|
|
||||||
echo "needs"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"needs"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "has_bluetooth_hid_connected detects HID" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
system_profiler() {
|
|
||||||
cat << 'OUT'
|
|
||||||
Bluetooth:
|
|
||||||
Apple Magic Mouse:
|
|
||||||
Connected: Yes
|
|
||||||
Type: Mouse
|
|
||||||
OUT
|
|
||||||
}
|
|
||||||
export -f system_profiler
|
|
||||||
if has_bluetooth_hid_connected; then
|
|
||||||
echo "hid"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"hid"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "is_ac_power detects AC power" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
pmset() { echo "AC Power"; }
|
|
||||||
export -f pmset
|
|
||||||
if is_ac_power; then
|
|
||||||
echo "ac"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"ac"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "is_memory_pressure_high detects warning" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
memory_pressure() { echo "warning"; }
|
|
||||||
export -f memory_pressure
|
|
||||||
if is_memory_pressure_high; then
|
|
||||||
echo "high"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"high"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "opt_launch_services_rebuild handles missing lsregister" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
opt_launch_services_rebuild
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"LaunchServices repaired"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "opt_msg uses dry-run output" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
opt_msg "dry"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" == *"dry"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "run_launchctl_unload skips in dry-run" {
|
|
||||||
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF'
|
|
||||||
set -euo pipefail
|
|
||||||
source "$PROJECT_ROOT/lib/optimize/tasks.sh"
|
|
||||||
launchctl() { echo "called"; }
|
|
||||||
export -f launchctl
|
|
||||||
run_launchctl_unload "/tmp/test.plist" false
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
[[ "$output" != *"called"* ]]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user