CodeRabbit Generated Unit Tests: Add test_apa.bats and test_distro_specific.bats test files

This commit is contained in:
coderabbitai[bot]
2025-06-22 11:34:08 +00:00
committed by GitHub
parent 3844ef919f
commit 9852b3afcf
2 changed files with 1132 additions and 0 deletions

401
tests/test_apa.bats Normal file
View File

@@ -0,0 +1,401 @@
#!/usr/bin/env bats
# Load the apa script for testing
APA_SCRIPT="${BATS_TEST_DIRNAME}/../git/extensions/apa.sh"
setup() {
# Create temporary directory for test isolation
export TEST_TEMP_DIR="$(mktemp -d)"
export ORIGINAL_HOME="$HOME"
export ORIGINAL_APA_CONFIG_DIR="$APA_CONFIG_DIR"
export ORIGINAL_APA_LOG_LEVEL="$APA_LOG_LEVEL"
export ORIGINAL_APA_TIMEOUT="$APA_TIMEOUT"
# Set up test environment
export HOME="$TEST_TEMP_DIR"
export APA_CONFIG_DIR="$TEST_TEMP_DIR/.apa"
export APA_LOG_LEVEL="quiet"
export APA_TIMEOUT="10"
# Make apa script executable and available
chmod +x "$APA_SCRIPT"
export PATH="$(dirname "$APA_SCRIPT"):$PATH"
}
teardown() {
# Restore original environment
export HOME="$ORIGINAL_HOME"
export APA_CONFIG_DIR="$ORIGINAL_APA_CONFIG_DIR"
export APA_LOG_LEVEL="$ORIGINAL_APA_LOG_LEVEL"
export APA_TIMEOUT="$ORIGINAL_APA_TIMEOUT"
# Clean up temporary files
[ -n "$TEST_TEMP_DIR" ] && rm -rf "$TEST_TEMP_DIR"
}
@test "apa script exists and is executable" {
[ -f "$APA_SCRIPT" ]
[ -x "$APA_SCRIPT" ]
}
@test "apa shows help with --help option" {
run bash "$APA_SCRIPT" --help
[ "$status" -eq 0 ]
[[ "$output" =~ "apa - Automated Package Assistant" ]]
[[ "$output" =~ "Usage:" ]]
[[ "$output" =~ "Commands:" ]]
[[ "$output" =~ "install" ]]
[[ "$output" =~ "update" ]]
[[ "$output" =~ "remove" ]]
}
@test "apa shows help with -h option" {
run bash "$APA_SCRIPT" -h
[ "$status" -eq 0 ]
[[ "$output" =~ "apa - Automated Package Assistant" ]]
}
@test "apa shows version with --version option" {
run bash "$APA_SCRIPT" --version
[ "$status" -eq 0 ]
[[ "$output" =~ "apa version 1.2.3" ]]
}
@test "apa shows version with -v option" {
run bash "$APA_SCRIPT" -v
[ "$status" -eq 0 ]
[[ "$output" =~ "apa version 1.2.3" ]]
}
@test "apa shows help when run with no arguments" {
run bash "$APA_SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" =~ "Usage:" ]]
}
@test "apa install succeeds with valid package name" {
run bash "$APA_SCRIPT" install nginx
[ "$status" -eq 0 ]
[[ "$output" =~ "Package nginx installed successfully" ]]
}
@test "apa install creates config directory" {
bash "$APA_SCRIPT" install test-package
[ -d "$APA_CONFIG_DIR" ]
}
@test "apa install fails without package name" {
run bash "$APA_SCRIPT" install
[ "$status" -eq 1 ]
[[ "$output" =~ "Install command requires a package name" ]]
}
@test "apa install fails with empty package name" {
run bash "$APA_SCRIPT" install ""
[ "$status" -eq 1 ]
[[ "$output" =~ "Package name cannot be empty" ]]
}
@test "apa install fails with invalid package name containing spaces" {
run bash "$APA_SCRIPT" install "invalid package"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa install fails with invalid package name containing special chars" {
run bash "$APA_SCRIPT" install "invalid@package#"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa install accepts valid package names with dots, dashes, underscores" {
run bash "$APA_SCRIPT" install "valid-package_name.123"
[ "$status" -eq 0 ]
[[ "$output" =~ "installed successfully" ]]
}
@test "apa update succeeds with valid package name" {
run bash "$APA_SCRIPT" update nginx
[ "$status" -eq 0 ]
[[ "$output" =~ "Package nginx updated successfully" ]]
}
@test "apa update fails without package name" {
run bash "$APA_SCRIPT" update
[ "$status" -eq 1 ]
[[ "$output" =~ "Update command requires a package name" ]]
}
@test "apa update fails with empty package name" {
run bash "$APA_SCRIPT" update ""
[ "$status" -eq 1 ]
[[ "$output" =~ "Package name cannot be empty" ]]
}
@test "apa update fails with invalid package name" {
run bash "$APA_SCRIPT" update "invalid@package"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa remove succeeds with valid package name" {
run bash "$APA_SCRIPT" remove nginx
[ "$status" -eq 0 ]
[[ "$output" =~ "Package nginx removed successfully" ]]
}
@test "apa remove fails without package name" {
run bash "$APA_SCRIPT" remove
[ "$status" -eq 1 ]
[[ "$output" =~ "Remove command requires a package name" ]]
}
@test "apa remove fails with empty package name" {
run bash "$APA_SCRIPT" remove ""
[ "$status" -eq 1 ]
[[ "$output" =~ "Package name cannot be empty" ]]
}
@test "apa remove fails with invalid package name" {
run bash "$APA_SCRIPT" remove "invalid package name"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa list shows installed packages" {
run bash "$APA_SCRIPT" list
[ "$status" -eq 0 ]
[[ "$output" =~ "nginx-1.18.0" ]]
[[ "$output" =~ "curl-7.68.0" ]]
[[ "$output" =~ "git-2.34.1" ]]
}
@test "apa search succeeds with valid query" {
run bash "$APA_SCRIPT" search "web"
[ "$status" -eq 0 ]
[[ "$output" =~ "Found packages matching 'web'" ]]
[[ "$output" =~ "web-server-toolkit" ]]
}
@test "apa search fails without query" {
run bash "$APA_SCRIPT" search
[ "$status" -eq 1 ]
[[ "$output" =~ "Search command requires a query" ]]
}
@test "apa search fails with empty query" {
run bash "$APA_SCRIPT" search ""
[ "$status" -eq 1 ]
[[ "$output" =~ "Search query cannot be empty" ]]
}
@test "apa search handles special characters in query" {
run bash "$APA_SCRIPT" search "web-server"
[ "$status" -eq 0 ]
[[ "$output" =~ "Found packages matching" ]]
}
@test "apa info succeeds with valid package name" {
run bash "$APA_SCRIPT" info nginx
[ "$status" -eq 0 ]
[[ "$output" =~ "Package: nginx" ]]
[[ "$output" =~ "Version:" ]]
[[ "$output" =~ "Description:" ]]
[[ "$output" =~ "Maintainer:" ]]
}
@test "apa info fails without package name" {
run bash "$APA_SCRIPT" info
[ "$status" -eq 1 ]
[[ "$output" =~ "Info command requires a package name" ]]
}
@test "apa info fails with empty package name" {
run bash "$APA_SCRIPT" info ""
[ "$status" -eq 1 ]
[[ "$output" =~ "Package name cannot be empty" ]]
}
@test "apa info fails with invalid package name" {
run bash "$APA_SCRIPT" info "invalid@package"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa handles unknown command gracefully" {
run bash "$APA_SCRIPT" unknown-command
[ "$status" -eq 1 ]
[[ "$output" =~ "Unknown command: unknown-command" ]]
}
@test "apa handles unknown option gracefully" {
run bash "$APA_SCRIPT" --unknown-option
[ "$status" -eq 1 ]
[[ "$output" =~ "Unknown option: --unknown-option" ]]
}
@test "apa quiet option suppresses info output" {
run bash "$APA_SCRIPT" --quiet install test-package
[ "$status" -eq 0 ]
[[ "$output" =~ "installed successfully" ]]
# Info logs should be suppressed in quiet mode
}
@test "apa debug option enables debug output" {
export APA_LOG_LEVEL="debug"
run bash "$APA_SCRIPT" --debug install test-package
[ "$status" -eq 0 ]
}
@test "apa timeout option is accepted" {
run bash "$APA_SCRIPT" --timeout 60 --help
[ "$status" -eq 0 ]
}
@test "apa respects APA_CONFIG_DIR environment variable" {
export APA_CONFIG_DIR="$TEST_TEMP_DIR/custom-config"
bash "$APA_SCRIPT" install test-package
[ -d "$TEST_TEMP_DIR/custom-config" ]
}
@test "apa respects APA_LOG_LEVEL environment variable" {
export APA_LOG_LEVEL="debug"
run bash "$APA_SCRIPT" install test-package
[ "$status" -eq 0 ]
}
@test "apa respects APA_TIMEOUT environment variable" {
export APA_TIMEOUT="120"
run bash "$APA_SCRIPT" install test-package
[ "$status" -eq 0 ]
}
@test "apa handles very long package names gracefully" {
local long_name=$(printf 'a%.0s' {1..1000})
run bash "$APA_SCRIPT" install "$long_name"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa handles package names with only valid characters at boundary" {
# Test exactly valid characters
run bash "$APA_SCRIPT" install "a"
[ "$status" -eq 0 ]
run bash "$APA_SCRIPT" install "a-b_c.123"
[ "$status" -eq 0 ]
run bash "$APA_SCRIPT" install "123"
[ "$status" -eq 0 ]
}
@test "apa rejects command injection attempts" {
run bash "$APA_SCRIPT" install "; rm -rf /"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
run bash "$APA_SCRIPT" install "$(whoami)"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
run bash "$APA_SCRIPT" install "|cat /etc/passwd"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa handles unicode characters in package names" {
run bash "$APA_SCRIPT" install "测试包"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid package name" ]]
}
@test "apa handles null bytes in input" {
printf "test\0package" | run bash "$APA_SCRIPT" install
[ "$status" -eq 1 ]
}
@test "apa handles missing HOME directory" {
unset HOME
run bash "$APA_SCRIPT" install test-package
[ "$status" -eq 0 ]
}
@test "apa handles non-writable config directory parent" {
# This test may need to be skipped in some environments
if [[ "$EUID" -ne 0 ]]; then
export APA_CONFIG_DIR="/root/test-apa-config"
run bash "$APA_SCRIPT" install test-package
# Should handle gracefully, not necessarily succeed
[[ "$status" -eq 0 || "$status" -eq 1 ]]
else
skip "Cannot test non-writable directory as root"
fi
}
@test "apa operations complete within timeout" {
# Test that operations don't hang indefinitely
timeout 30s bash "$APA_SCRIPT" install test-package
[ $? -ne 124 ] # 124 is timeout's exit code
}
@test "apa can handle multiple operations in sequence" {
run bash "$APA_SCRIPT" install package1
[ "$status" -eq 0 ]
run bash "$APA_SCRIPT" update package1
[ "$status" -eq 0 ]
run bash "$APA_SCRIPT" info package1
[ "$status" -eq 0 ]
run bash "$APA_SCRIPT" remove package1
[ "$status" -eq 0 ]
}
@test "apa output format is consistent across commands" {
# Test that all successful operations produce clean output
run bash "$APA_SCRIPT" install test-package
[ "$status" -eq 0 ]
[[ "$output" =~ ^[[:print:][:space:]]*$ ]]
run bash "$APA_SCRIPT" list
[ "$status" -eq 0 ]
[[ "$output" =~ ^[[:print:][:space:]]*$ ]]
}
@test "apa handles concurrent execution" {
# Run multiple instances to test for race conditions
bash "$APA_SCRIPT" install package1 &
bash "$APA_SCRIPT" install package2 &
bash "$APA_SCRIPT" list &
wait
[ $? -eq 0 ]
}
@test "apa config directory creation is idempotent" {
# First run should create directory
bash "$APA_SCRIPT" install test-package
[ -d "$APA_CONFIG_DIR" ]
# Second run should not fail even if directory exists
bash "$APA_SCRIPT" install test-package2
[ -d "$APA_CONFIG_DIR" ]
}
@test "apa validates package names consistently across commands" {
# Test that validation works the same for all commands that take package names
local invalid_name="invalid@package"
run bash "$APA_SCRIPT" install "$invalid_name"
[ "$status" -eq 1 ]
run bash "$APA_SCRIPT" update "$invalid_name"
[ "$status" -eq 1 ]
run bash "$APA_SCRIPT" remove "$invalid_name"
[ "$status" -eq 1 ]
run bash "$APA_SCRIPT" info "$invalid_name"
[ "$status" -eq 1 ]
}

View File

@@ -0,0 +1,731 @@
#!/usr/bin/env bats
# Test suite for distribution-specific functionality
# Testing framework: BATS (Bash Automated Testing System)
# Load test helpers if they exist
load test_helper 2>/dev/null || true
setup() {
# Create temporary directory for test fixtures
export BATS_TEST_TMPDIR="$(mktemp -d)"
export ORIGINAL_PATH="$PATH"
export ORIGINAL_ETC="/etc"
# Create mock /etc directory structure
mkdir -p "$BATS_TEST_TMPDIR/etc"
# Mock various distribution release files
create_mock_os_release() {
local distro="$1"
case "$distro" in
"ubuntu")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.3 LTS"
VERSION_ID="20.04"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
EOF
;;
"centos")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="CentOS Linux"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PRETTY_NAME="CentOS Linux 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
EOF
;;
"debian")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
EOF
;;
"rhel")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="Red Hat Enterprise Linux"
VERSION="8.5 (Ootpa)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="8.5"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Red Hat Enterprise Linux 8.5 (Ootpa)"
ANSI_COLOR="0;31"
EOF
;;
"fedora")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="Fedora Linux"
VERSION="35 (Workstation Edition)"
ID=fedora
VERSION_ID=35
VERSION_CODENAME=""
PLATFORM_ID="platform:f35"
PRETTY_NAME="Fedora Linux 35 (Workstation Edition)"
ANSI_COLOR="0;38;2;60;110;180"
EOF
;;
"arch")
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"
EOF
;;
esac
}
# Mock LSB release file
create_mock_lsb_release() {
local distro="$1"
case "$distro" in
"ubuntu")
cat > "$BATS_TEST_TMPDIR/etc/lsb-release" << 'EOF'
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
EOF
;;
esac
}
# Mock system commands
create_mock_commands() {
mkdir -p "$BATS_TEST_TMPDIR/bin"
export PATH="$BATS_TEST_TMPDIR/bin:$PATH"
# Mock which command
cat > "$BATS_TEST_TMPDIR/bin/which" << 'EOF'
#!/bin/bash
case "$1" in
"apt"|"apt-get") echo "/usr/bin/apt" ;;
"yum") echo "/usr/bin/yum" ;;
"dnf") echo "/usr/bin/dnf" ;;
"pacman") echo "/usr/bin/pacman" ;;
"zypper") echo "/usr/bin/zypper" ;;
*) exit 1 ;;
esac
EOF
chmod +x "$BATS_TEST_TMPDIR/bin/which"
}
}
teardown() {
# Clean up test environment
rm -rf "$BATS_TEST_TMPDIR"
export PATH="$ORIGINAL_PATH"
unset BATS_TEST_TMPDIR ORIGINAL_PATH ORIGINAL_ETC
}
@test "should detect Ubuntu distribution correctly from os-release" {
create_mock_os_release "ubuntu"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "ubuntu" ]]
}
@test "should detect CentOS distribution correctly from os-release" {
create_mock_os_release "centos"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "centos" ]]
}
@test "should detect Debian distribution correctly from os-release" {
create_mock_os_release "debian"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "debian" ]]
}
@test "should detect RHEL distribution correctly from os-release" {
create_mock_os_release "rhel"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "rhel" ]]
}
@test "should detect Fedora distribution correctly from os-release" {
create_mock_os_release "fedora"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "fedora" ]]
}
@test "should detect Arch Linux distribution correctly from os-release" {
create_mock_os_release "arch"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 0 ]
[[ "$output" == "arch" ]]
}
@test "should detect apt package manager for Ubuntu" {
create_mock_os_release "ubuntu"
create_mock_commands
get_package_manager() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
case "$ID" in
"ubuntu"|"debian") echo "apt" ;;
"centos"|"rhel") echo "yum" ;;
"fedora") echo "dnf" ;;
"arch") echo "pacman" ;;
"opensuse"|"sles") echo "zypper" ;;
*) echo "unknown" ;;
esac
fi
}
run get_package_manager
[ "$status" -eq 0 ]
[[ "$output" == "apt" ]]
}
@test "should detect yum package manager for CentOS" {
create_mock_os_release "centos"
create_mock_commands
get_package_manager() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
case "$ID" in
"ubuntu"|"debian") echo "apt" ;;
"centos"|"rhel") echo "yum" ;;
"fedora") echo "dnf" ;;
"arch") echo "pacman" ;;
"opensuse"|"sles") echo "zypper" ;;
*) echo "unknown" ;;
esac
fi
}
run get_package_manager
[ "$status" -eq 0 ]
[[ "$output" == "yum" ]]
}
@test "should detect dnf package manager for Fedora" {
create_mock_os_release "fedora"
create_mock_commands
get_package_manager() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
case "$ID" in
"ubuntu"|"debian") echo "apt" ;;
"centos"|"rhel") echo "yum" ;;
"fedora") echo "dnf" ;;
"arch") echo "pacman" ;;
"opensuse"|"sles") echo "zypper" ;;
*) echo "unknown" ;;
esac
fi
}
run get_package_manager
[ "$status" -eq 0 ]
[[ "$output" == "dnf" ]]
}
@test "should detect pacman package manager for Arch Linux" {
create_mock_os_release "arch"
create_mock_commands
get_package_manager() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
case "$ID" in
"ubuntu"|"debian") echo "apt" ;;
"centos"|"rhel") echo "yum" ;;
"fedora") echo "dnf" ;;
"arch") echo "pacman" ;;
"opensuse"|"sles") echo "zypper" ;;
*) echo "unknown" ;;
esac
fi
}
run get_package_manager
[ "$status" -eq 0 ]
[[ "$output" == "pacman" ]]
}
@test "should handle missing os-release file gracefully" {
rm -f "$BATS_TEST_TMPDIR/etc/os-release"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
else
echo "Error: Unable to detect distribution - os-release not found"
return 1
fi
}
run detect_distribution
[ "$status" -eq 1 ]
[[ "$output" =~ "Unable to detect distribution" ]]
}
@test "should handle malformed os-release file" {
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
This is not a valid
os-release file format
ID=
EOF
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
if [[ -z "$ID" ]]; then
echo "Error: Invalid distribution ID"
return 1
fi
echo "$ID"
return 0
fi
return 1
}
run detect_distribution
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid distribution ID" ]]
}
@test "should handle unsupported distribution" {
cat > "$BATS_TEST_TMPDIR/etc/os-release" << 'EOF'
NAME="Exotic Linux"
ID="exotic"
VERSION_ID="1.0"
PRETTY_NAME="Exotic Linux 1.0"
EOF
get_package_manager() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
case "$ID" in
"ubuntu"|"debian") echo "apt" ;;
"centos"|"rhel") echo "yum" ;;
"fedora") echo "dnf" ;;
"arch") echo "pacman" ;;
"opensuse"|"sles") echo "zypper" ;;
*)
echo "Error: Unsupported distribution: $ID"
return 1
;;
esac
fi
}
run get_package_manager
[ "$status" -eq 1 ]
[[ "$output" =~ "Unsupported distribution: exotic" ]]
}
@test "should fall back to lsb-release when os-release is unavailable" {
rm -f "$BATS_TEST_TMPDIR/etc/os-release"
create_mock_lsb_release "ubuntu"
detect_distribution_with_fallback() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
elif [[ -f "$BATS_TEST_TMPDIR/etc/lsb-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/lsb-release"
echo "${DISTRIB_ID,,}"
else
echo "Error: Unable to detect distribution"
return 1
fi
}
run detect_distribution_with_fallback
[ "$status" -eq 0 ]
[[ "$output" == "ubuntu" ]]
}
@test "should handle empty os-release file" {
touch "$BATS_TEST_TMPDIR/etc/os-release"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
if [[ -z "$ID" ]]; then
echo "Error: Distribution ID not found"
return 1
fi
echo "$ID"
fi
}
run detect_distribution
[ "$status" -eq 1 ]
[[ "$output" =~ "Distribution ID not found" ]]
}
@test "should validate distribution name parameter" {
validate_distribution_name() {
local distro="$1"
if [[ -z "$distro" ]]; then
echo "Error: Distribution name parameter is required"
return 1
fi
if [[ "$distro" =~ [^a-zA-Z0-9._-] ]]; then
echo "Error: Invalid characters in distribution name"
return 1
fi
echo "Valid distribution name: $distro"
return 0
}
run validate_distribution_name ""
[ "$status" -eq 1 ]
[[ "$output" =~ "parameter is required" ]]
}
@test "should sanitize distribution names with special characters" {
validate_distribution_name() {
local distro="$1"
if [[ -z "$distro" ]]; then
echo "Error: Distribution name parameter is required"
return 1
fi
if [[ "$distro" =~ [^a-zA-Z0-9._-] ]]; then
echo "Error: Invalid characters in distribution name"
return 1
fi
echo "Valid distribution name: $distro"
return 0
}
run validate_distribution_name "ubuntu; rm -rf /"
[ "$status" -eq 1 ]
[[ "$output" =~ "Invalid characters" ]]
}
@test "should accept valid distribution names with hyphens and dots" {
validate_distribution_name() {
local distro="$1"
if [[ -z "$distro" ]]; then
echo "Error: Distribution name parameter is required"
return 1
fi
if [[ "$distro" =~ [^a-zA-Z0-9._-] ]]; then
echo "Error: Invalid characters in distribution name"
return 1
fi
echo "Valid distribution name: $distro"
return 0
}
run validate_distribution_name "ubuntu-18.04"
[ "$status" -eq 0 ]
[[ "$output" =~ "Valid distribution name: ubuntu-18.04" ]]
}
@test "should accept distribution names with underscores" {
validate_distribution_name() {
local distro="$1"
if [[ -z "$distro" ]]; then
echo "Error: Distribution name parameter is required"
return 1
fi
if [[ "$distro" =~ [^a-zA-Z0-9._-] ]]; then
echo "Error: Invalid characters in distribution name"
return 1
fi
echo "Valid distribution name: $distro"
return 0
}
run validate_distribution_name "centos_stream"
[ "$status" -eq 0 ]
[[ "$output" =~ "Valid distribution name: centos_stream" ]]
}
@test "should complete distribution detection within reasonable time" {
create_mock_os_release "ubuntu"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
run timeout 5s bash -c "detect_distribution"
[ "$status" -eq 0 ]
[[ "$output" == "ubuntu" ]]
}
@test "should handle concurrent distribution detection calls" {
create_mock_os_release "ubuntu"
detect_distribution() {
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
echo "$ID"
return 0
fi
return 1
}
local pids=()
for i in {1..3}; do
detect_distribution &
pids+=($!)
done
local all_success=true
for pid in "${pids[@]}"; do
if ! wait "$pid"; then
all_success=false
fi
done
[ "$all_success" = true ]
}
@test "should execute complete distribution-specific workflow for Ubuntu" {
create_mock_os_release "ubuntu"
create_mock_commands
complete_distro_workflow() {
local distro package_manager
if [[ -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
. "$BATS_TEST_TMPDIR/etc/os-release"
distro="$ID"
else
echo "Error: Cannot detect distribution"
return 1
fi
case "$distro" in
"ubuntu"|"debian") package_manager="apt" ;;
"centos"|"rhel") package_manager="yum" ;;
"fedora") package_manager="dnf" ;;
"arch") package_manager="pacman" ;;
*) package_manager="unknown" ;;
esac
echo "Distribution: $distro, Package Manager: $package_manager"
echo "Ubuntu workflow completed successfully"
return 0
}
run complete_distro_workflow
[ "$status" -eq 0 ]
[[ "$output" =~ "Distribution: ubuntu, Package Manager: apt" ]]
[[ "$output" =~ "Ubuntu workflow completed successfully" ]]
}
@test "should provide helpful error messages for failures" {
rm -f "$BATS_TEST_TMPDIR/etc/os-release"
detect_distribution_with_helpful_errors() {
if [[ ! -f "$BATS_TEST_TMPDIR/etc/os-release" ]]; then
echo "Error: Unable to detect Linux distribution"
echo "Try: Ensure /etc/os-release exists and is readable"
echo "Alternative: Check for /etc/lsb-release or distribution-specific files"
return 1
fi
}
run detect_distribution_with_helpful_errors
[ "$status" -eq 1 ]
[[ "$output" =~ "Error: Unable to detect Linux distribution" ]]
[[ "$output" =~ "Try: Ensure /etc/os-release exists" ]]
[[ "$output" =~ "Alternative: Check for /etc/lsb-release" ]]
}
@test "should provide script version information" {
get_script_version() {
echo "distro_specific_utils v1.2.3"
return 0
}
run get_script_version
[ "$status" -eq 0 ]
[[ "$output" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]
}
@test "should display comprehensive help information" {
display_help() {
cat << 'EOF'
Usage: distro_specific_utils [OPTIONS] [COMMAND]
DESCRIPTION:
Utility for detecting Linux distributions and managing
distribution-specific operations.
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-d, --detect Detect current distribution
-p, --package Show package manager for current distribution
COMMANDS:
detect Detect the current Linux distribution
package-mgr Show the package manager for current distribution
EXAMPLES:
distro_specific_utils --detect
distro_specific_utils package-mgr
SUPPORTED DISTRIBUTIONS:
Ubuntu, Debian, CentOS, RHEL, Fedora, Arch Linux, openSUSE
EOF
}
run display_help
[ "$status" -eq 0 ]
[[ "$output" =~ "Usage:" ]]
[[ "$output" =~ "OPTIONS:" ]]
[[ "$output" =~ "EXAMPLES:" ]]
[[ "$output" =~ "SUPPORTED DISTRIBUTIONS:" ]]
}
@test "should validate system requirements" {
check_system_requirements() {
local missing_commands=()
if [[ ! -r /etc/os-release ]] && [[ ! -r /etc/lsb-release ]]; then
echo "Warning: No distribution identification files found"
fi
for cmd in cat grep sed awk; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing_commands+=("$cmd")
fi
done
if [[ ${#missing_commands[@]} -gt 0 ]]; then
echo "Error: Missing required commands: ${missing_commands[*]}"
return 1
fi
echo "System requirements satisfied"
return 0
}
export PATH="$BATS_TEST_TMPDIR/bin:$PATH"
for cmd in cat grep sed awk; do
echo '#!/bin/bash' > "$BATS_TEST_TMPDIR/bin/$cmd"
echo 'echo "mock $cmd"' >> "$BATS_TEST_TMPDIR/bin/$cmd"
chmod +x "$BATS_TEST_TMPDIR/bin/$cmd"
done
run check_system_requirements
[ "$status" -eq 0 ]
[[ "$output" =~ "System requirements satisfied" ]]
}
@test "should handle insufficient permissions gracefully" {
touch "$BATS_TEST_TMPDIR/etc/os-release"
chmod 000 "$BATS_TEST_TMPDIR/etc/os-release"
handle_permission_error() {
local file="$BATS_TEST_TMPDIR/etc/os-release"
if [[ ! -r "$file" ]]; then
echo "Error: Insufficient permissions to read $file"
echo "Try: Run with appropriate permissions or contact system administrator"
return 1
fi
return 0
}
run handle_permission_error
[ "$status" -eq 1 ]
[[ "$output" =~ "Insufficient permissions" ]]
[[ "$output" =~ "Try: Run with appropriate permissions" ]]
}