diff --git a/.gitignore b/.gitignore index ec89e7e..8319b94 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ temp/ *.tmp *.temp *.dmg +tests/tmp-* # Cache .cache/ diff --git a/lib/clean/brew.sh b/lib/clean/brew.sh index 6e683be..eeb69ca 100644 --- a/lib/clean/brew.sh +++ b/lib/clean/brew.sh @@ -43,41 +43,32 @@ clean_homebrew() { MOLE_SPINNER_PREFIX=" " start_inline_spinner "Homebrew cleanup and autoremove..." 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 brew_tmp_file autoremove_tmp_file local brew_pid autoremove_pid + local brew_exit=0 + local autoremove_exit=0 if [[ "$skip_cleanup" == "false" ]]; then 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=$! fi 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=$! - local elapsed=0 - local brew_done=false - local autoremove_done=false - [[ "$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 - [[ -n "$brew_pid" ]] && { kill -0 $brew_pid 2> /dev/null || brew_done=true; } - kill -0 $autoremove_pid 2> /dev/null || autoremove_done=true - sleep 1 - ((elapsed++)) - done + + if [[ -n "$brew_pid" ]]; then + wait "$brew_pid" 2> /dev/null || brew_exit=$? + fi + wait "$autoremove_pid" 2> /dev/null || autoremove_exit=$? + local brew_success=false - if [[ "$skip_cleanup" == "false" && -n "$brew_pid" ]]; then - if wait $brew_pid 2> /dev/null; then - brew_success=true - fi + if [[ "$skip_cleanup" == "false" && $brew_exit -eq 0 ]]; then + brew_success=true fi local autoremove_success=false - if wait $autoremove_pid 2> /dev/null; then + if [[ $autoremove_exit -eq 0 ]]; then autoremove_success=true 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)" 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" fi # Process autoremove output - only show if packages were removed @@ -113,7 +104,7 @@ clean_homebrew() { if [[ $removed_packages -gt 0 ]]; then echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed orphaned dependencies (${removed_packages} packages)" 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" fi # Update cache timestamp on successful completion or when cleanup was intelligently skipped diff --git a/tests/app_caches.bats b/tests/app_caches.bats deleted file mode 100644 index a8c802f..0000000 --- a/tests/app_caches.bats +++ /dev/null @@ -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"* ]] -} diff --git a/tests/app_caches_more.bats b/tests/clean_app_caches.bats similarity index 62% rename from tests/app_caches_more.bats rename to tests/clean_app_caches.bats index 2f03e45..8be5da0 100644 --- a/tests/app_caches_more.bats +++ b/tests/clean_app_caches.bats @@ -7,7 +7,7 @@ setup_file() { ORIGINAL_HOME="${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 mkdir -p "$HOME" @@ -20,6 +20,57 @@ teardown_file() { 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" { run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' set -euo pipefail diff --git a/tests/apps_module.bats b/tests/clean_apps.bats similarity index 100% rename from tests/apps_module.bats rename to tests/clean_apps.bats diff --git a/tests/browser_version_cleanup.bats b/tests/clean_browser_versions.bats similarity index 100% rename from tests/browser_version_cleanup.bats rename to tests/clean_browser_versions.bats diff --git a/tests/clean.bats b/tests/clean_core.bats similarity index 95% rename from tests/clean.bats rename to tests/clean_core.bats index e9c06b8..c039cfa 100644 --- a/tests/clean.bats +++ b/tests/clean_core.bats @@ -74,8 +74,27 @@ EOF skip "Homebrew not installed" 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 ] + [[ "$output" == *"5"* ]] } @test "FINDER_METADATA_SENTINEL in whitelist protects .DS_Store files" { diff --git a/tests/dev_caches.bats b/tests/clean_dev_caches.bats similarity index 100% rename from tests/dev_caches.bats rename to tests/clean_dev_caches.bats diff --git a/tests/clean_extras.bats b/tests/clean_extras.bats deleted file mode 100644 index 25db807..0000000 --- a/tests/clean_extras.bats +++ /dev/null @@ -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 ] -} diff --git a/tests/clean_extras_more.bats b/tests/clean_misc.bats similarity index 60% rename from tests/clean_extras_more.bats rename to tests/clean_misc.bats index 20a2e96..1e7054e 100644 --- a/tests/clean_extras_more.bats +++ b/tests/clean_misc.bats @@ -7,7 +7,7 @@ setup_file() { ORIGINAL_HOME="${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 mkdir -p "$HOME" @@ -20,6 +20,87 @@ teardown_file() { 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" { run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' set -euo pipefail diff --git a/tests/clean_caches.bats b/tests/clean_system_caches.bats similarity index 100% rename from tests/clean_caches.bats rename to tests/clean_system_caches.bats diff --git a/tests/system_maintenance.bats b/tests/clean_system_maintenance.bats similarity index 98% rename from tests/system_maintenance.bats rename to tests/clean_system_maintenance.bats index 9fe4cff..c76c6e1 100644 --- a/tests/system_maintenance.bats +++ b/tests/clean_system_maintenance.bats @@ -234,18 +234,24 @@ source "$PROJECT_ROOT/lib/clean/brew.sh" mkdir -p "$HOME/.cache/mole" 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 + start_inline_spinner(){ :; } + stop_inline_spinner(){ :; } + note_activity(){ :; } + run_with_timeout() { + local duration="$1" + shift + if [[ "$1" == "du" ]]; then + echo "51201 $3" + return 0 + fi + "$@" + } -MO_BREW_TIMEOUT=2 + MO_BREW_TIMEOUT=2 -start_inline_spinner(){ :; } -stop_inline_spinner(){ :; } -note_activity(){ :; } - -brew() { - case "$1" in - cleanup) + brew() { + case "$1" in + cleanup) echo "Removing: package" return 0 ;; @@ -259,9 +265,7 @@ brew() { esac } -clean_homebrew - -rm -rf "$HOME/Library/Caches/Homebrew" + clean_homebrew EOF [ "$status" -eq 0 ] diff --git a/tests/user_clean_core.bats b/tests/clean_user_core.bats similarity index 100% rename from tests/user_clean_core.bats rename to tests/clean_user_core.bats diff --git a/tests/common.bats b/tests/core_common.bats similarity index 100% rename from tests/common.bats rename to tests/core_common.bats diff --git a/tests/performance.bats b/tests/core_performance.bats similarity index 100% rename from tests/performance.bats rename to tests/core_performance.bats diff --git a/tests/safe_functions.bats b/tests/core_safe_functions.bats similarity index 100% rename from tests/safe_functions.bats rename to tests/core_safe_functions.bats diff --git a/tests/timeout_tests.bats b/tests/core_timeout.bats similarity index 100% rename from tests/timeout_tests.bats rename to tests/core_timeout.bats diff --git a/tests/autofix.bats b/tests/manage_autofix.bats similarity index 100% rename from tests/autofix.bats rename to tests/manage_autofix.bats diff --git a/tests/sudo_manager.bats b/tests/manage_sudo.bats similarity index 100% rename from tests/sudo_manager.bats rename to tests/manage_sudo.bats diff --git a/tests/whitelist.bats b/tests/manage_whitelist.bats similarity index 100% rename from tests/whitelist.bats rename to tests/manage_whitelist.bats diff --git a/tests/optimize_tasks.bats b/tests/optimize.bats similarity index 68% rename from tests/optimize_tasks.bats rename to tests/optimize.bats index 8e7a924..a4ef886 100644 --- a/tests/optimize_tasks.bats +++ b/tests/optimize.bats @@ -20,6 +20,73 @@ teardown_file() { 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" { run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" MOLE_DRY_RUN=1 bash --noprofile --norc <<'EOF' set -euo pipefail diff --git a/tests/optimize_core.bats b/tests/optimize_core.bats deleted file mode 100644 index 4f38f75..0000000 --- a/tests/optimize_core.bats +++ /dev/null @@ -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"* ]] -} diff --git a/tests/purge_config.bats b/tests/purge_config_paths.bats similarity index 100% rename from tests/purge_config.bats rename to tests/purge_config_paths.bats diff --git a/tests/regression_bugs.bats b/tests/regression.bats similarity index 100% rename from tests/regression_bugs.bats rename to tests/regression.bats diff --git a/tests/update_manager.bats b/tests/update.bats similarity index 100% rename from tests/update_manager.bats rename to tests/update.bats diff --git a/tests/user_file_handling.bats b/tests/user_file_ops.bats similarity index 100% rename from tests/user_file_handling.bats rename to tests/user_file_ops.bats