mirror of
https://github.com/tw93/Mole.git
synced 2026-03-24 03:45:08 +00:00
feat: implement installer cleanup functionality, add ZIP and file descriptor installer tests, and update README
This commit is contained in:
312
tests/installer_zip.bats
Normal file
312
tests/installer_zip.bats
Normal file
@@ -0,0 +1,312 @@
|
||||
#!/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-installers-home.XXXXXX")"
|
||||
export HOME
|
||||
|
||||
mkdir -p "$HOME"
|
||||
|
||||
if command -v zip > /dev/null 2>&1; then
|
||||
ZIP_AVAILABLE=1
|
||||
else
|
||||
ZIP_AVAILABLE=0
|
||||
fi
|
||||
if command -v zipinfo > /dev/null 2>&1 || command -v unzip > /dev/null 2>&1; then
|
||||
ZIP_LIST_AVAILABLE=1
|
||||
else
|
||||
ZIP_LIST_AVAILABLE=0
|
||||
fi
|
||||
if command -v unzip > /dev/null 2>&1; then
|
||||
UNZIP_AVAILABLE=1
|
||||
else
|
||||
UNZIP_AVAILABLE=0
|
||||
fi
|
||||
}
|
||||
|
||||
teardown_file() {
|
||||
rm -rf "$HOME"
|
||||
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
|
||||
export HOME="$ORIGINAL_HOME"
|
||||
fi
|
||||
}
|
||||
|
||||
setup() {
|
||||
export TERM="xterm-256color"
|
||||
export MO_DEBUG=0
|
||||
|
||||
# Create standard scan directories
|
||||
mkdir -p "$HOME/Downloads"
|
||||
mkdir -p "$HOME/Desktop"
|
||||
mkdir -p "$HOME/Documents"
|
||||
mkdir -p "$HOME/Public"
|
||||
mkdir -p "$HOME/Library/Downloads"
|
||||
|
||||
# Clear previous test files
|
||||
rm -rf "${HOME:?}/Downloads"/*
|
||||
rm -rf "${HOME:?}/Desktop"/*
|
||||
rm -rf "${HOME:?}/Documents"/*
|
||||
}
|
||||
|
||||
zip_list_available() {
|
||||
[[ "${ZIP_LIST_AVAILABLE:-0}" -eq 1 ]]
|
||||
}
|
||||
|
||||
require_zip_list() {
|
||||
zip_list_available
|
||||
}
|
||||
|
||||
require_zip_support() {
|
||||
[[ "${ZIP_AVAILABLE:-0}" -eq 1 && "${ZIP_LIST_AVAILABLE:-0}" -eq 1 ]]
|
||||
}
|
||||
|
||||
require_unzip_support() {
|
||||
[[ "${ZIP_AVAILABLE:-0}" -eq 1 && "${UNZIP_AVAILABLE:-0}" -eq 1 ]]
|
||||
}
|
||||
|
||||
# Test ZIP installer detection
|
||||
|
||||
@test "is_installer_zip: rejects ZIP with installer content but too many entries" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a ZIP with too many files (exceeds MAX_ZIP_ENTRIES=5)
|
||||
# Include a .app file to have installer content
|
||||
mkdir -p "$HOME/Downloads/large-app"
|
||||
touch "$HOME/Downloads/large-app/MyApp.app"
|
||||
for i in {1..9}; do
|
||||
touch "$HOME/Downloads/large-app/file$i.txt"
|
||||
done
|
||||
(cd "$HOME/Downloads" && zip -q -r large-installer.zip large-app)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
if is_installer_zip "'"$HOME/Downloads/large-installer.zip"'"; then
|
||||
echo "INSTALLER"
|
||||
else
|
||||
echo "NOT_INSTALLER"
|
||||
fi
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "NOT_INSTALLER" ]]
|
||||
}
|
||||
|
||||
@test "is_installer_zip: detects ZIP with app content" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/Downloads/app-content"
|
||||
touch "$HOME/Downloads/app-content/MyApp.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r app.zip app-content)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
if is_installer_zip "'"$HOME/Downloads/app.zip"'"; then
|
||||
echo "INSTALLER"
|
||||
else
|
||||
echo "NOT_INSTALLER"
|
||||
fi
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "INSTALLER" ]]
|
||||
}
|
||||
|
||||
@test "is_installer_zip: rejects ZIP with only regular files" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/Downloads/data"
|
||||
touch "$HOME/Downloads/data/file1.txt"
|
||||
touch "$HOME/Downloads/data/file2.pdf"
|
||||
(cd "$HOME/Downloads" && zip -q -r data.zip data)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
if is_installer_zip "'"$HOME/Downloads/data.zip"'"; then
|
||||
echo "INSTALLER"
|
||||
else
|
||||
echo "NOT_INSTALLER"
|
||||
fi
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "NOT_INSTALLER" ]]
|
||||
}
|
||||
|
||||
@test "is_installer_zip: returns NOT_INSTALLER when ZIP list command is unavailable" {
|
||||
touch "$HOME/Downloads/empty.zip"
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
ZIP_LIST_CMD=()
|
||||
if is_installer_zip "$2"; then
|
||||
echo "INSTALLER"
|
||||
else
|
||||
echo "NOT_INSTALLER"
|
||||
fi
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh" "$HOME/Downloads/empty.zip"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "NOT_INSTALLER" ]]
|
||||
}
|
||||
|
||||
@test "is_installer_zip: works with unzip list command" {
|
||||
if ! require_unzip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/Downloads/app-content"
|
||||
touch "$HOME/Downloads/app-content/MyApp.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r app.zip app-content)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
ZIP_LIST_CMD=(unzip -Z -1)
|
||||
if is_installer_zip "$2"; then
|
||||
echo "INSTALLER"
|
||||
else
|
||||
echo "NOT_INSTALLER"
|
||||
fi
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh" "$HOME/Downloads/app.zip"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "INSTALLER" ]]
|
||||
}
|
||||
|
||||
# Integration tests: ZIP scanning inside scan_all_installers
|
||||
|
||||
@test "scan_all_installers: finds installer ZIP in Downloads" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a valid installer ZIP (contains .app)
|
||||
mkdir -p "$HOME/Downloads/app-content"
|
||||
touch "$HOME/Downloads/app-content/MyApp.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r installer.zip app-content)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
scan_all_installers
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"installer.zip"* ]]
|
||||
}
|
||||
|
||||
@test "scan_all_installers: ignores non-installer ZIP in Downloads" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a non-installer ZIP (only regular files)
|
||||
mkdir -p "$HOME/Downloads/data"
|
||||
touch "$HOME/Downloads/data/file1.txt"
|
||||
touch "$HOME/Downloads/data/file2.pdf"
|
||||
(cd "$HOME/Downloads" && zip -q -r data.zip data)
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
scan_all_installers
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" != *"data.zip"* ]]
|
||||
}
|
||||
|
||||
# Failure path tests for scan_installers_in_path
|
||||
|
||||
@test "scan_installers_in_path: skips corrupt ZIP files" {
|
||||
if ! require_zip_list; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a corrupt ZIP file by just writing garbage data
|
||||
echo "This is not a valid ZIP file" > "$HOME/Downloads/corrupt.zip"
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
scan_installers_in_path "$2"
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh" "$HOME/Downloads"
|
||||
|
||||
# Should succeed (return 0) and silently skip the corrupt ZIP
|
||||
[ "$status" -eq 0 ]
|
||||
# Output should be empty since corrupt.zip is not a valid installer
|
||||
[[ -z "$output" ]]
|
||||
}
|
||||
|
||||
@test "scan_installers_in_path: handles permission-denied files" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a valid installer ZIP
|
||||
mkdir -p "$HOME/Downloads/app-content"
|
||||
touch "$HOME/Downloads/app-content/MyApp.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r readable.zip app-content)
|
||||
|
||||
# Create a readable installer ZIP alongside a permission-denied file
|
||||
mkdir -p "$HOME/Downloads/restricted-app"
|
||||
touch "$HOME/Downloads/restricted-app/App.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r restricted.zip restricted-app)
|
||||
|
||||
# Remove read permissions from restricted.zip
|
||||
chmod 000 "$HOME/Downloads/restricted.zip"
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
scan_installers_in_path "$2"
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh" "$HOME/Downloads"
|
||||
|
||||
# Should succeed and find the readable.zip but skip restricted.zip
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"readable.zip"* ]]
|
||||
[[ "$output" != *"restricted.zip"* ]]
|
||||
|
||||
# Cleanup: restore permissions for teardown
|
||||
chmod 644 "$HOME/Downloads/restricted.zip"
|
||||
}
|
||||
|
||||
@test "scan_installers_in_path: finds installer ZIP alongside corrupt ZIPs" {
|
||||
if ! require_zip_support; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create a valid installer ZIP
|
||||
mkdir -p "$HOME/Downloads/app-content"
|
||||
touch "$HOME/Downloads/app-content/MyApp.app"
|
||||
(cd "$HOME/Downloads" && zip -q -r valid-installer.zip app-content)
|
||||
|
||||
# Create a corrupt ZIP
|
||||
echo "garbage data" > "$HOME/Downloads/corrupt.zip"
|
||||
|
||||
run bash -euo pipefail -c '
|
||||
export MOLE_TEST_MODE=1
|
||||
source "$1"
|
||||
scan_installers_in_path "$2"
|
||||
' bash "$PROJECT_ROOT/bin/installer.sh" "$HOME/Downloads"
|
||||
|
||||
# Should find the valid ZIP and silently skip the corrupt one
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"valid-installer.zip"* ]]
|
||||
[[ "$output" != *"corrupt.zip"* ]]
|
||||
}
|
||||
Reference in New Issue
Block a user