1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-05 21:58:01 +00:00

Automated test synchronous update

This commit is contained in:
Tw93
2025-11-29 23:14:46 +09:00
parent a184094f45
commit 3f9d1205fd
10 changed files with 20 additions and 175 deletions

View File

@@ -426,7 +426,6 @@ safe_clean() {
return 0
}
start_cleanup() {
clear
printf '\n'
@@ -833,7 +832,6 @@ perform_cleanup() {
clean_time_machine_failed_backups
end_section
# ===== Final summary =====
echo ""

View File

@@ -40,7 +40,8 @@ clean_deep_system() {
local updates_cleaned=0
while IFS= read -r -d '' item; do
# Skip system-protected files (restricted flag)
local item_flags=$(ls -lO "$item" 2> /dev/null | awk '{print $5}')
local item_flags
item_flags=$(stat -f%Sf "$item" 2> /dev/null || echo "")
if [[ "$item_flags" == *"restricted"* ]]; then
continue
fi

View File

@@ -234,7 +234,7 @@ clean_application_support_logs() {
# Clean stale update downloads (older than 7 days)
if [[ -d "$app_dir/update" ]] && ls "$app_dir/update" > /dev/null 2>&1; then
while IFS= read -r update_dir; do
local dir_age_days=$(( ($(date +%s) - $(get_file_mtime "$update_dir")) / 86400 ))
local dir_age_days=$((($(date +%s) - $(get_file_mtime "$update_dir")) / 86400))
if [[ $dir_age_days -ge $MOLE_TEMP_FILE_AGE_DAYS ]]; then
safe_clean "$update_dir" "Stale update: $app_name"
fi

View File

@@ -36,14 +36,14 @@ readonly ICON_NAV_LEFT="←"
readonly ICON_NAV_RIGHT="→"
# Global configuration constants
readonly MOLE_TEMP_FILE_AGE_DAYS=7 # Temp file cleanup threshold
readonly MOLE_ORPHAN_AGE_DAYS=60 # Orphaned data threshold
readonly MOLE_MAX_PARALLEL_JOBS=15 # Parallel job limit
readonly MOLE_MAIL_DOWNLOADS_MIN_KB=5120 # Mail attachments size threshold (~5MB)
readonly MOLE_LOG_AGE_DAYS=30 # System log retention
readonly MOLE_CRASH_REPORT_AGE_DAYS=30 # Crash report retention
readonly MOLE_SAVED_STATE_AGE_DAYS=7 # App saved state retention
readonly MOLE_TM_BACKUP_SAFE_HOURS=48 # Time Machine failed backup safety window
readonly MOLE_TEMP_FILE_AGE_DAYS=7 # Temp file cleanup threshold
readonly MOLE_ORPHAN_AGE_DAYS=60 # Orphaned data threshold
readonly MOLE_MAX_PARALLEL_JOBS=15 # Parallel job limit
readonly MOLE_MAIL_DOWNLOADS_MIN_KB=5120 # Mail attachments size threshold (~5MB)
readonly MOLE_LOG_AGE_DAYS=30 # System log retention
readonly MOLE_CRASH_REPORT_AGE_DAYS=30 # Crash report retention
readonly MOLE_SAVED_STATE_AGE_DAYS=7 # App saved state retention
readonly MOLE_TM_BACKUP_SAFE_HOURS=48 # Time Machine failed backup safety window
# Get spinner characters (overridable via MO_SPINNER_CHARS)
mo_spinner_chars() {
@@ -91,6 +91,12 @@ validate_path_for_deletion() {
return 1
fi
# Check for path traversal attempts
if [[ "$path" =~ \.\. ]]; then
log_error "Path validation failed: path traversal not allowed: $path"
return 1
fi
# Check path doesn't contain dangerous characters
if [[ "$path" =~ [[:cntrl:]] ]] || [[ "$path" =~ $'\n' ]]; then
log_error "Path validation failed: contains control characters: $path"
@@ -99,7 +105,7 @@ validate_path_for_deletion() {
# Check path isn't critical system directory
case "$path" in
/ | /bin | /sbin | /usr | /usr/bin | /usr/sbin | /etc | /var | /System | /Library/Extensions)
/ | /bin | /sbin | /usr | /usr/bin | /usr/sbin | /etc | /var | /System | /System/* | /Library/Extensions)
log_error "Path validation failed: critical system directory: $path"
return 1
;;

View File

@@ -177,24 +177,3 @@ setup() {
rm -rf "$HOME/projects"
}
# Test permission flag creation
@test "check_tcc_permissions creates permission flag after check" {
# Remove flag if exists
rm -f "$HOME/.cache/mole/permissions_granted"
# Simulate accessible Library/Caches (skip TCC dialog)
function ls() {
return 0 # Simulate accessible
}
export -f ls
run bash -c "
source '$PROJECT_ROOT/lib/common.sh'
source '$PROJECT_ROOT/lib/clean_caches.sh'
check_tcc_permissions < /dev/null
"
[ "$status" -eq 0 ]
# Permission flag should be created
[[ -f "$HOME/.cache/mole/permissions_granted" ]]
}

View File

@@ -148,29 +148,6 @@ EOF
rm -f "$HOME/temp_file_path.txt" "$HOME/temp_dir_path.txt"
}
@test "parallel_execute runs worker across all items" {
output_file="$HOME/parallel_output.txt"
HOME="$HOME" bash --noprofile --norc << 'EOF'
source "$PROJECT_ROOT/lib/common.sh"
worker() {
echo "$1" >> "$HOME/parallel_output.txt"
}
parallel_execute 2 worker "first" "second" "third"
EOF
sort "$output_file" > "$output_file.sorted"
results=()
while IFS= read -r line; do
results+=("$line")
done < "$output_file.sorted"
[ "${#results[@]}" -eq 3 ]
joined=" ${results[*]} "
[[ "$joined" == *" first "* ]]
[[ "$joined" == *" second "* ]]
[[ "$joined" == *" third "* ]]
rm -f "$output_file" "$output_file.sorted"
}
@test "should_protect_data protects system and critical apps" {
# System apps should be protected

View File

@@ -100,19 +100,6 @@ teardown() {
# Should not output error in silent mode
}
# Test safe_sudo_remove
@test "safe_sudo_remove rejects symlinks" {
local test_file="$TEST_DIR/real_file"
local test_link="$TEST_DIR/symlink"
touch "$test_file"
ln -s "$test_file" "$test_link"
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; safe_sudo_remove '$test_link' 2>&1"
[ "$status" -eq 1 ]
[[ "$output" == *"symlink"* ]]
rm -f "$test_link" "$test_file"
}
# Test safe_find_delete
@test "safe_find_delete validates base directory" {

View File

@@ -70,42 +70,7 @@ setup() {
[ "$status" -eq 0 ]
}
# Test request_sudo function structure
@test "request_sudo accepts prompt parameter" {
# Mock request_sudo_access to avoid actual prompting
function request_sudo_access() {
return 1 # Simulate denied
}
export -f request_sudo_access
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/sudo_manager.sh'; request_sudo 'Test prompt'"
[ "$status" -eq 1 ] # Expected: denied
}
# Test start_sudo_session integration
@test "start_sudo_session handles success and failure paths" {
# Mock request_sudo to simulate denied access
function request_sudo() {
return 1
}
export -f request_sudo
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/sudo_manager.sh'; start_sudo_session 'Test'"
[ "$status" -eq 1 ]
# Mock request_sudo to simulate granted access
function request_sudo() {
return 0
}
function _start_sudo_keepalive() {
echo "12345"
}
export -f request_sudo
export -f _start_sudo_keepalive
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/sudo_manager.sh'; start_sudo_session 'Test'"
[ "$status" -eq 0 ]
}
# Test stop_sudo_session cleanup
@test "stop_sudo_session cleans up keepalive process" {

View File

@@ -0,0 +1 @@
dependency

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bats
# shellcheck disable=SC2030,SC2031
setup_file() {
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
@@ -123,75 +124,5 @@ setup() {
[ "$status" -eq 1 ] # ESC cancels
}
# Test perform_updates function structure
@test "perform_updates handles brew formula updates" {
# Mock brew to avoid actual updates
function brew() {
case "$1" in
outdated)
if [[ "${2:-}" == "--cask" ]]; then
return 1 # No cask updates
else
echo "test-package"
return 0 # Has formula updates
fi
;;
upgrade)
echo "Upgrading test-package..."
return 0
;;
*)
return 1
;;
esac
}
export -f brew
export BREW_OUTDATED_COUNT=1
export BREW_FORMULA_OUTDATED_COUNT=1
export BREW_CASK_OUTDATED_COUNT=0
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/update_manager.sh'; perform_updates"
[ "$status" -eq 0 ]
}
# Test update_homebrew function
@test "update_homebrew returns early when no updates" {
function brew() {
case "$1" in
outdated)
return 1 # No updates
;;
*)
return 1
;;
esac
}
export -f brew
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/update_manager.sh'; update_homebrew"
[ "$status" -eq 0 ]
}
@test "update_homebrew handles network failures gracefully" {
function brew() {
case "$1" in
outdated)
if [[ "${2:-}" == "--quiet" ]]; then
echo "test-package"
return 0
fi
;;
upgrade)
return 1 # Simulate failure
;;
*)
return 1
;;
esac
}
export -f brew
run bash -c "source '$PROJECT_ROOT/lib/common.sh'; source '$PROJECT_ROOT/lib/update_manager.sh'; update_homebrew"
# Should handle failure without crashing
[ "$status" -eq 0 ] || [ "$status" -eq 1 ]
}