forked from Shinonome/dots-hyprland
Update the test script
This commit is contained in:
+439
-217
@@ -2,18 +2,20 @@
|
|||||||
#
|
#
|
||||||
# test_update.sh - Test suite for update.sh
|
# test_update.sh - Test suite for update.sh
|
||||||
#
|
#
|
||||||
set -uo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
TESTS_PASSED=0
|
TESTS_PASSED=0
|
||||||
TESTS_FAILED=0
|
TESTS_FAILED=0
|
||||||
TEST_DIR=""
|
TEST_DIR=""
|
||||||
|
ORIGINAL_DIR="$PWD"
|
||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
log_test() {
|
log_test() {
|
||||||
@@ -45,7 +47,9 @@ setup_test_env() {
|
|||||||
git config user.email "test@example.com"
|
git config user.email "test@example.com"
|
||||||
git config user.name "Test User"
|
git config user.name "Test User"
|
||||||
|
|
||||||
# Return only the directory path (no logging here)
|
# Create initial commit
|
||||||
|
git commit --allow-empty -m "Initial commit" -q
|
||||||
|
|
||||||
echo "$temp_dir"
|
echo "$temp_dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +60,21 @@ cleanup_test_env() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Mock functions to avoid side effects
|
||||||
|
mock_git() {
|
||||||
|
if [[ "$1" == "pull" ]]; then
|
||||||
|
echo "Mock: git pull executed"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
# For other git commands, use real git but in test directory
|
||||||
|
command git "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_makepkg() {
|
||||||
|
echo "Mock: makepkg $*"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Test 1: Script exists and is executable
|
# Test 1: Script exists and is executable
|
||||||
test_script_exists() {
|
test_script_exists() {
|
||||||
log_test "Checking if update.sh exists and is executable"
|
log_test "Checking if update.sh exists and is executable"
|
||||||
@@ -77,11 +96,10 @@ test_script_exists() {
|
|||||||
test_syntax() {
|
test_syntax() {
|
||||||
log_test "Checking script syntax"
|
log_test "Checking script syntax"
|
||||||
|
|
||||||
if bash -n update.sh 2>/dev/null; then
|
if bash -n update.sh; then
|
||||||
log_pass "No syntax errors found"
|
log_pass "No syntax errors found"
|
||||||
else
|
else
|
||||||
log_fail "Syntax errors detected"
|
log_fail "Syntax errors detected"
|
||||||
bash -n update.sh
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -90,7 +108,7 @@ test_syntax() {
|
|||||||
test_help_option() {
|
test_help_option() {
|
||||||
log_test "Testing --help option"
|
log_test "Testing --help option"
|
||||||
|
|
||||||
if ./update.sh --help >/dev/null 2>&1; then
|
if ./update.sh --help 2>&1 | grep -q "Usage:"; then
|
||||||
log_pass "Help option works"
|
log_pass "Help option works"
|
||||||
else
|
else
|
||||||
log_fail "Help option failed"
|
log_fail "Help option failed"
|
||||||
@@ -104,54 +122,32 @@ test_dots_structure() {
|
|||||||
|
|
||||||
local test_repo
|
local test_repo
|
||||||
test_repo=$(setup_test_env)
|
test_repo=$(setup_test_env)
|
||||||
TEST_DIR="$test_repo" # Set for cleanup
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
# Create dots/ structure
|
# Create dots/ structure
|
||||||
mkdir -p dots/.config/test
|
mkdir -p dots/.config/test-app
|
||||||
mkdir -p dots/.local/bin
|
mkdir -p dots/.local/bin
|
||||||
echo "test config" > dots/.config/test/config.txt
|
echo "test config" > dots/.config/test-app/config.conf
|
||||||
|
echo "#!/bin/bash" > dots/.local/bin/test-script
|
||||||
|
|
||||||
# Create minimal update.sh
|
# Add and commit
|
||||||
cat > .update-test.sh << 'EOF'
|
git add .
|
||||||
#!/usr/bin/env bash
|
git commit -m "Add dots structure" -q
|
||||||
REPO_DIR="$PWD"
|
|
||||||
detect_repo_structure() {
|
# Source the update.sh to test functions
|
||||||
local found_dirs=()
|
source update.sh >/dev/null 2>&1 || true
|
||||||
if [[ -d "${REPO_DIR}/dots/.config" ]]; then
|
|
||||||
found_dirs+=("dots/.config")
|
# Test the detection function
|
||||||
[[ -d "${REPO_DIR}/dots/.local/bin" ]] && found_dirs+=("dots/.local/bin")
|
if result=$(detect_repo_structure 2>/dev/null); then
|
||||||
[[ -d "${REPO_DIR}/dots/.local/share" ]] && found_dirs+=("dots/.local/share")
|
if [[ "$result" == *"dots/.config"* ]] && [[ "$result" == *"dots/.local/bin"* ]]; then
|
||||||
elif [[ -d "${REPO_DIR}/.config" ]]; then
|
log_pass "Dots structure detected correctly"
|
||||||
found_dirs+=(".config")
|
else
|
||||||
[[ -d "${REPO_DIR}/.local/bin" ]] && found_dirs+=(".local/bin")
|
log_fail "Failed to detect dots structure. Got: $result"
|
||||||
[[ -d "${REPO_DIR}/.local/share" ]] && found_dirs+=(".local/share")
|
fi
|
||||||
else
|
else
|
||||||
for candidate in "dots/.config" ".config" "config" "dots/.local/bin" ".local/bin" "dots/.local/share" ".local/share"; do
|
log_fail "detect_repo_structure failed"
|
||||||
if [[ -d "${REPO_DIR}/${candidate}" ]]; then
|
|
||||||
if [[ ! " ${found_dirs[*]} " =~ " ${candidate} " ]]; then
|
|
||||||
found_dirs+=("${candidate}")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [[ ${#found_dirs[@]} -eq 0 ]]; then
|
|
||||||
echo "ERROR: Could not detect repository structure" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo "${found_dirs[@]}"
|
|
||||||
}
|
|
||||||
detect_repo_structure
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x .update-test.sh
|
|
||||||
result=$(./.update-test.sh)
|
|
||||||
|
|
||||||
if [[ "$result" == *"dots/.config"* ]]; then
|
|
||||||
log_pass "Dots structure detected correctly"
|
|
||||||
else
|
|
||||||
log_fail "Failed to detect dots structure. Got: $result"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ORIGINAL_DIR" || exit 1
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
@@ -164,93 +160,69 @@ test_flat_structure() {
|
|||||||
|
|
||||||
local test_repo
|
local test_repo
|
||||||
test_repo=$(setup_test_env)
|
test_repo=$(setup_test_env)
|
||||||
TEST_DIR="$test_repo" # Set for cleanup
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
# Create flat structure
|
# Create flat structure
|
||||||
mkdir -p .config/test
|
mkdir -p .config/test-app
|
||||||
mkdir -p .local/bin
|
mkdir -p .local/bin
|
||||||
echo "test config" > .config/test/config.txt
|
echo "test config" > .config/test-app/config.conf
|
||||||
|
echo "#!/bin/bash" > .local/bin/test-script
|
||||||
|
|
||||||
cat > .update-test.sh << 'EOF'
|
# Add and commit
|
||||||
#!/usr/bin/env bash
|
git add .
|
||||||
REPO_DIR="$PWD"
|
git commit -m "Add flat structure" -q
|
||||||
detect_repo_structure() {
|
|
||||||
local found_dirs=()
|
# Source the update.sh to test functions
|
||||||
if [[ -d "${REPO_DIR}/dots/.config" ]]; then
|
source update.sh >/dev/null 2>&1 || true
|
||||||
found_dirs+=("dots/.config")
|
|
||||||
[[ -d "${REPO_DIR}/dots/.local/bin" ]] && found_dirs+=("dots/.local/bin")
|
# Test the detection function
|
||||||
[[ -d "${REPO_DIR}/dots/.local/share" ]] && found_dirs+=("dots/.local/share")
|
if result=$(detect_repo_structure 2>/dev/null); then
|
||||||
elif [[ -d "${REPO_DIR}/.config" ]]; then
|
if [[ "$result" == *".config"* ]] && [[ "$result" != *"dots/"* ]]; then
|
||||||
found_dirs+=(".config")
|
log_pass "Flat structure detected correctly"
|
||||||
[[ -d "${REPO_DIR}/.local/bin" ]] && found_dirs+=(".local/bin")
|
else
|
||||||
[[ -d "${REPO_DIR}/.local/share" ]] && found_dirs+=(".local/share")
|
log_fail "Failed to detect flat structure. Got: $result"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
for candidate in "dots/.config" ".config" "config" "dots/.local/bin" ".local/bin" "dots/.local/share" ".local/share"; do
|
log_fail "detect_repo_structure failed"
|
||||||
if [[ -d "${REPO_DIR}/${candidate}" ]]; then
|
|
||||||
if [[ ! " ${found_dirs[*]} " =~ " ${candidate} " ]]; then
|
|
||||||
found_dirs+=("${candidate}")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [[ ${#found_dirs[@]} -eq 0 ]]; then
|
|
||||||
echo "ERROR: Could not detect repository structure" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo "${found_dirs[@]}"
|
|
||||||
}
|
|
||||||
detect_repo_structure
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x .update-test.sh
|
|
||||||
result=$(./.update-test.sh)
|
|
||||||
|
|
||||||
if [[ "$result" == *".config"* ]] && [[ "$result" != *"dots/"* ]]; then
|
|
||||||
log_pass "Flat structure detected correctly"
|
|
||||||
else
|
|
||||||
log_fail "Failed to detect flat structure. Got: $result"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ORIGINAL_DIR" || exit 1
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
cleanup_test_env
|
cleanup_test_env
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test 6: Test package directory detection
|
# Test 6: Test dots prefix mapping to home directory
|
||||||
test_package_detection() {
|
test_dots_mapping() {
|
||||||
log_test "Testing package directory detection"
|
log_test "Testing dots/ prefix home directory mapping"
|
||||||
|
|
||||||
local test_repo
|
local test_repo
|
||||||
test_repo=$(setup_test_env)
|
test_repo=$(setup_test_env)
|
||||||
TEST_DIR="$test_repo" # Set for cleanup
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
# Test dist-arch
|
# Create dots/ structure
|
||||||
mkdir -p dist-arch/test-pkg
|
mkdir -p dots/.config/test-app
|
||||||
cat > .update-test.sh << 'EOF'
|
echo "test config" > dots/.config/test-app/config.conf
|
||||||
#!/usr/bin/env bash
|
|
||||||
REPO_DIR="$PWD"
|
|
||||||
if [[ -d "${REPO_DIR}/dist-arch" ]]; then
|
|
||||||
ARCH_PACKAGES_DIR="${REPO_DIR}/dist-arch"
|
|
||||||
elif [[ -d "${REPO_DIR}/arch-packages" ]]; then
|
|
||||||
ARCH_PACKAGES_DIR="${REPO_DIR}/arch-packages"
|
|
||||||
elif [[ -d "${REPO_DIR}/sdist/arch" ]]; then
|
|
||||||
ARCH_PACKAGES_DIR="${REPO_DIR}/sdist/arch"
|
|
||||||
else
|
|
||||||
ARCH_PACKAGES_DIR="${REPO_DIR}/dist-arch"
|
|
||||||
fi
|
|
||||||
echo "$ARCH_PACKAGES_DIR"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x .update-test.sh
|
# Source the update.sh
|
||||||
result=$(./.update-test.sh)
|
source update.sh >/dev/null 2>&1 || true
|
||||||
|
|
||||||
if [[ "$result" == *"dist-arch"* ]]; then
|
# Test the mapping logic
|
||||||
log_pass "Package directory detection works"
|
dir_name="dots/.config"
|
||||||
|
if [[ "$dir_name" == dots/* ]]; then
|
||||||
|
home_subdir="${dir_name#dots/}"
|
||||||
|
home_dir_path="${HOME}/${home_subdir}"
|
||||||
else
|
else
|
||||||
log_fail "Failed to detect package directory. Got: $result"
|
home_dir_path="${HOME}/${dir_name}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected_path="${HOME}/.config"
|
||||||
|
if [[ "$home_dir_path" == "$expected_path" ]]; then
|
||||||
|
log_pass "Dots prefix mapping correct: $dir_name → $home_dir_path"
|
||||||
|
else
|
||||||
|
log_fail "Dots prefix mapping failed: $dir_name → $home_dir_path (expected: $expected_path)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ORIGINAL_DIR" || exit 1
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
@@ -263,7 +235,7 @@ test_ignore_patterns() {
|
|||||||
|
|
||||||
local test_repo
|
local test_repo
|
||||||
test_repo=$(setup_test_env)
|
test_repo=$(setup_test_env)
|
||||||
TEST_DIR="$test_repo" # Set for cleanup
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
@@ -272,97 +244,283 @@ test_ignore_patterns() {
|
|||||||
# Test ignore patterns
|
# Test ignore patterns
|
||||||
*.log
|
*.log
|
||||||
secrets/
|
secrets/
|
||||||
test-file.txt
|
.config/private*
|
||||||
*private*
|
*backup*
|
||||||
|
/tmp-file
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Test should_ignore function
|
# Create test files
|
||||||
cat > .update-test.sh << 'EOF'
|
mkdir -p .config
|
||||||
#!/usr/bin/env bash
|
touch app.log
|
||||||
REPO_DIR="$PWD"
|
touch secrets/key.txt
|
||||||
UPDATE_IGNORE_FILE="${REPO_DIR}/.updateignore"
|
touch .config/private-config
|
||||||
HOME_UPDATE_IGNORE_FILE="${HOME}/.updateignore"
|
touch .config/backup-file
|
||||||
|
touch normal-config
|
||||||
should_ignore() {
|
|
||||||
local file_path="$1"
|
|
||||||
local relative_path="${file_path#$HOME/}"
|
|
||||||
local repo_relative=""
|
|
||||||
if [[ "$file_path" == "$REPO_DIR"* ]]; then
|
|
||||||
repo_relative="${file_path#$REPO_DIR/}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for ignore_file in "$UPDATE_IGNORE_FILE" "$HOME_UPDATE_IGNORE_FILE"; do
|
# Source the update.sh
|
||||||
if [[ -f "$ignore_file" ]]; then
|
source update.sh >/dev/null 2>&1 || true
|
||||||
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
|
||||||
[[ -z "$pattern" || "$pattern" =~ ^[[:space:]]*# ]] && continue
|
# Test cases
|
||||||
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
local passed=0
|
||||||
[[ -z "$pattern" ]] && continue
|
local total=0
|
||||||
|
|
||||||
if [[ "$relative_path" == "$pattern" ]] || [[ "$repo_relative" == "$pattern" ]]; then
|
# Test patterns
|
||||||
return 0
|
test_cases=(
|
||||||
fi
|
"$test_repo/app.log:0"
|
||||||
|
"$test_repo/secrets/key.txt:0"
|
||||||
if [[ "$pattern" == */ ]]; then
|
"$test_repo/.config/private-config:0"
|
||||||
local dir_pattern="${pattern%/}"
|
"$test_repo/.config/backup-file:0"
|
||||||
if [[ "$relative_path" == "$dir_pattern"/* ]] || [[ "$repo_relative" == "$dir_pattern"/* ]]; then
|
"$test_repo/normal-config:1"
|
||||||
return 0
|
"$test_repo/.config/normal-file:1"
|
||||||
fi
|
)
|
||||||
fi
|
|
||||||
|
for test_case in "${test_cases[@]}"; do
|
||||||
if [[ "$pattern" == *"*"* ]]; then
|
IFS=':' read -r file expected <<< "$test_case"
|
||||||
if [[ "$relative_path" == $pattern ]] || [[ "$repo_relative" == $pattern ]]; then
|
touch "$file" 2>/dev/null || true
|
||||||
return 0
|
((total++))
|
||||||
fi
|
|
||||||
fi
|
if should_ignore "$file"; then
|
||||||
|
result=0
|
||||||
if [[ "$file_path" == *"$pattern"* ]] || [[ "$relative_path" == *"$pattern"* ]]; then
|
else
|
||||||
return 0
|
result=1
|
||||||
fi
|
fi
|
||||||
done <"$ignore_file"
|
|
||||||
|
if [[ $result -eq $expected ]]; then
|
||||||
|
((passed++))
|
||||||
|
else
|
||||||
|
log_fail "Ignore test failed: $file (expected: $expected, got: $result)"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test cases
|
|
||||||
should_ignore "$REPO_DIR/test.log" && echo "PASS: *.log pattern" || echo "FAIL: *.log pattern"
|
|
||||||
should_ignore "$REPO_DIR/secrets/key.txt" && echo "PASS: secrets/ pattern" || echo "FAIL: secrets/ pattern"
|
|
||||||
should_ignore "$REPO_DIR/test-file.txt" && echo "PASS: exact match pattern" || echo "FAIL: exact match pattern"
|
|
||||||
should_ignore "$REPO_DIR/my-private-file.txt" && echo "PASS: *private* pattern" || echo "FAIL: *private* pattern"
|
|
||||||
should_ignore "$REPO_DIR/normal-file.txt" && echo "FAIL: should not ignore" || echo "PASS: normal file not ignored"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x .update-test.sh
|
if [[ $passed -eq $total ]]; then
|
||||||
result=$(./.update-test.sh)
|
log_pass "All ignore pattern tests passed ($passed/$total)"
|
||||||
|
|
||||||
if [[ "$result" == *"PASS: *.log pattern"* ]] && \
|
|
||||||
[[ "$result" == *"PASS: secrets/ pattern"* ]] && \
|
|
||||||
[[ "$result" == *"PASS: exact match pattern"* ]] && \
|
|
||||||
[[ "$result" == *"PASS: *private* pattern"* ]] && \
|
|
||||||
[[ "$result" == *"PASS: normal file not ignored"* ]]; then
|
|
||||||
log_pass "Ignore patterns work correctly"
|
|
||||||
else
|
else
|
||||||
log_fail "Ignore patterns failed"
|
log_fail "Ignore pattern tests failed ($passed/$total passed)"
|
||||||
echo "$result"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ORIGINAL_DIR" || exit 1
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
cleanup_test_env
|
cleanup_test_env
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test 8: Test dry-run mode doesn't modify files
|
# Test 8: Test safe_read security (no eval injection)
|
||||||
test_dry_run() {
|
test_safe_read_security() {
|
||||||
log_test "Testing dry-run mode (manual verification needed)"
|
log_test "Testing safe_read security against injection"
|
||||||
|
|
||||||
log_info "Dry-run mode test requires manual verification:"
|
# Source the update.sh
|
||||||
log_info "1. Run: ./update.sh -n"
|
source update.sh >/dev/null 2>&1 || true
|
||||||
log_info "2. Verify no files are actually modified"
|
|
||||||
log_info "3. Check that it shows what WOULD be done"
|
|
||||||
|
|
||||||
log_pass "Dry-run test added to manual checklist"
|
# Test safe_read with potentially dangerous input
|
||||||
|
dangerous_input="'; echo 'INJECTION'; '"
|
||||||
|
|
||||||
|
# Use a subshell to capture any injection
|
||||||
|
output=$(
|
||||||
|
{
|
||||||
|
echo "$dangerous_input" | safe_read "Test: " test_var "default" 2>/dev/null || true
|
||||||
|
# Check if injection occurred
|
||||||
|
if declare -p test_var 2>/dev/null | grep -q "INJECTION"; then
|
||||||
|
echo "INJECTION_DETECTED"
|
||||||
|
else
|
||||||
|
echo "SAFE"
|
||||||
|
fi
|
||||||
|
} 2>/dev/null
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$output" != *"INJECTION_DETECTED"* ]]; then
|
||||||
|
log_pass "safe_read is secure against injection attacks"
|
||||||
|
else
|
||||||
|
log_fail "safe_read vulnerable to injection attacks"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test 9: Check for common shellcheck issues
|
# Test 9: Test dry-run mode
|
||||||
|
test_dry_run() {
|
||||||
|
log_test "Testing dry-run mode"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Create test structure
|
||||||
|
mkdir -p dots/.config/test-app
|
||||||
|
echo "repo config" > dots/.config/test-app/config.conf
|
||||||
|
|
||||||
|
# Add and commit
|
||||||
|
git add .
|
||||||
|
git commit -m "Add test config" -q
|
||||||
|
|
||||||
|
# Test dry-run execution
|
||||||
|
output=$(./update.sh -n --skip-notice 2>&1 || true)
|
||||||
|
|
||||||
|
if [[ "$output" == *"DRY-RUN"* ]] && [[ "$output" == *"would"* || "$output" == *"Would"* ]]; then
|
||||||
|
log_pass "Dry-run mode detected in output"
|
||||||
|
else
|
||||||
|
log_fail "Dry-run mode not properly indicated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify no files were actually created in home
|
||||||
|
if [[ ! -f "${HOME}/.config/test-app/config.conf" ]]; then
|
||||||
|
log_pass "No files created in home during dry-run"
|
||||||
|
else
|
||||||
|
log_fail "Files were created in home during dry-run"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 10: Test package directory detection
|
||||||
|
test_package_detection() {
|
||||||
|
log_test "Testing package directory detection"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Test different package directory names
|
||||||
|
for dir_name in "dist-arch" "arch-packages" "sdist/arch"; do
|
||||||
|
mkdir -p "$dir_name/test-pkg"
|
||||||
|
echo "pkgbase=test-pkg" > "$dir_name/test-pkg/PKGBUILD"
|
||||||
|
|
||||||
|
# Source to reset ARCH_PACKAGES_DIR
|
||||||
|
source update.sh >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if [[ -d "$dir_name" ]]; then
|
||||||
|
log_info "Found package directory: $dir_name"
|
||||||
|
# The sourcing should have set ARCH_PACKAGES_DIR correctly
|
||||||
|
if [[ -n "$ARCH_PACKAGES_DIR" ]]; then
|
||||||
|
log_pass "Package directory detection works for $dir_name"
|
||||||
|
else
|
||||||
|
log_fail "Package directory not detected for $dir_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "$dir_name"
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 11: Test force check mode
|
||||||
|
test_force_check() {
|
||||||
|
log_test "Testing force check mode"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Create test structure
|
||||||
|
mkdir -p .config/test-app
|
||||||
|
echo "config" > .config/test-app/settings.conf
|
||||||
|
|
||||||
|
# Test with force flag
|
||||||
|
output=$(./update.sh -f --skip-notice --dry-run 2>&1 || true)
|
||||||
|
|
||||||
|
if [[ "$output" == *"Force check"* ]] || [[ "$output" == *"Force mode"* ]]; then
|
||||||
|
log_pass "Force check mode detected"
|
||||||
|
else
|
||||||
|
log_fail "Force check mode not indicated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 12: Test conflict handling simulation
|
||||||
|
test_conflict_handling() {
|
||||||
|
log_test "Testing file conflict detection"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Create repo file
|
||||||
|
mkdir -p .config/test-app
|
||||||
|
echo "repo version" > .config/test-app/config.conf
|
||||||
|
|
||||||
|
# Create different home file
|
||||||
|
mkdir -p "${HOME}/.config/test-app"
|
||||||
|
echo "home version" > "${HOME}/.config/test-app/config.conf"
|
||||||
|
|
||||||
|
# Source the update.sh
|
||||||
|
source update.sh >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Test the comparison logic
|
||||||
|
repo_file="$test_repo/.config/test-app/config.conf"
|
||||||
|
home_file="${HOME}/.config/test-app/config.conf"
|
||||||
|
|
||||||
|
if ! cmp -s "$repo_file" "$home_file"; then
|
||||||
|
log_pass "File conflict correctly detected"
|
||||||
|
else
|
||||||
|
log_fail "File conflict not detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup home file
|
||||||
|
rm -f "$home_file"
|
||||||
|
rmdir "$(dirname "$home_file")" 2>/dev/null || true
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 13: Test all flags are recognized
|
||||||
|
test_flags() {
|
||||||
|
log_test "Testing command-line flags"
|
||||||
|
|
||||||
|
local flags=("-h" "--help" "-n" "--dry-run" "-f" "--force" "-v" "--verbose")
|
||||||
|
local all_passed=true
|
||||||
|
|
||||||
|
for flag in "${flags[@]}"; do
|
||||||
|
if ./update.sh "$flag" 2>&1 | grep -q -E "(Usage|dry-run|force|verbose|help)"; then
|
||||||
|
echo " ✓ $flag recognized"
|
||||||
|
else
|
||||||
|
echo " ✗ $flag not recognized"
|
||||||
|
all_passed=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$all_passed" == true ]]; then
|
||||||
|
log_pass "All tested flags recognized correctly"
|
||||||
|
else
|
||||||
|
log_fail "Some flags not recognized properly"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 14: Test git operations safety
|
||||||
|
test_git_safety() {
|
||||||
|
log_test "Testing git operations safety"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Create uncommitted changes
|
||||||
|
echo "temp" > temp-file.txt
|
||||||
|
|
||||||
|
# Test that script detects uncommitted changes
|
||||||
|
output=$(./update.sh --dry-run --skip-notice 2>&1 || true)
|
||||||
|
|
||||||
|
if [[ "$output" == *"uncommitted changes"* ]]; then
|
||||||
|
log_pass "Uncommitted changes detection works"
|
||||||
|
else
|
||||||
|
log_fail "Uncommitted changes not detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 15: Check for common shellcheck issues
|
||||||
test_shellcheck() {
|
test_shellcheck() {
|
||||||
log_test "Running shellcheck (if available)"
|
log_test "Running shellcheck (if available)"
|
||||||
|
|
||||||
@@ -372,45 +530,102 @@ test_shellcheck() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Run shellcheck with common exclusions
|
# Run shellcheck with common exclusions
|
||||||
if shellcheck -e SC2181,SC2155,SC2162 update.sh 2>&1 | grep -v "^$"; then
|
if shellcheck -e SC1090,SC1091,SC2148,SC2034,SC2155,SC2164 update.sh; then
|
||||||
|
log_pass "shellcheck passed"
|
||||||
|
else
|
||||||
log_fail "shellcheck found issues"
|
log_fail "shellcheck found issues"
|
||||||
return 1
|
return 1
|
||||||
else
|
|
||||||
log_pass "shellcheck passed"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test 10: Test all flags are recognized
|
# Test 16: Test fresh clone scenario (no HEAD@{1})
|
||||||
test_flags() {
|
test_fresh_clone() {
|
||||||
log_test "Testing command-line flags"
|
log_test "Testing fresh clone scenario"
|
||||||
|
|
||||||
local flags=("-h" "--help")
|
local test_repo
|
||||||
local all_passed=true
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
for flag in "${flags[@]}"; do
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
if ./update.sh "$flag" >/dev/null 2>&1; then
|
|
||||||
echo " ✓ $flag works"
|
|
||||||
else
|
|
||||||
echo " ✗ $flag failed"
|
|
||||||
all_passed=false
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$all_passed" == true ]]; then
|
# Create structure
|
||||||
log_pass "All tested flags work correctly"
|
mkdir -p .config/test-app
|
||||||
|
echo "config" > .config/test-app/settings.conf
|
||||||
|
|
||||||
|
# Source the update.sh
|
||||||
|
source update.sh >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Test has_new_commits in fresh clone (no HEAD@{1})
|
||||||
|
if has_new_commits; then
|
||||||
|
log_pass "Fresh clone scenario handled correctly"
|
||||||
else
|
else
|
||||||
log_fail "Some flags failed"
|
log_fail "Fresh clone scenario not handled properly"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 17: Test verbose mode
|
||||||
|
test_verbose_mode() {
|
||||||
|
log_test "Testing verbose mode"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Test verbose flag
|
||||||
|
output=$(./update.sh -v --dry-run --skip-notice 2>&1 || true)
|
||||||
|
|
||||||
|
if [[ "$output" == *"Verbose mode"* ]]; then
|
||||||
|
log_pass "Verbose mode detected"
|
||||||
|
else
|
||||||
|
log_fail "Verbose mode not indicated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 18: Test package checking flag
|
||||||
|
test_package_checking() {
|
||||||
|
log_test "Testing package checking flag"
|
||||||
|
|
||||||
|
local test_repo
|
||||||
|
test_repo=$(setup_test_env)
|
||||||
|
TEST_DIR="$test_repo"
|
||||||
|
|
||||||
|
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||||
|
|
||||||
|
# Test package flag
|
||||||
|
output=$(./update.sh -p --dry-run --skip-notice 2>&1 || true)
|
||||||
|
|
||||||
|
if [[ "$output" == *"Package checking"* ]]; then
|
||||||
|
log_pass "Package checking mode detected"
|
||||||
|
else
|
||||||
|
log_fail "Package checking mode not indicated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$ORIGINAL_DIR" || exit 1
|
||||||
|
cleanup_test_env
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main test runner
|
# Main test runner
|
||||||
main() {
|
main() {
|
||||||
echo -e "${BLUE}================================${NC}"
|
echo -e "${BLUE}================================${NC}"
|
||||||
echo -e "${BLUE} Update.sh Test Suite${NC}"
|
echo -e "${BLUE} Update.sh Comprehensive Test Suite${NC}"
|
||||||
echo -e "${BLUE}================================${NC}\n"
|
echo -e "${BLUE}================================${NC}\n"
|
||||||
|
|
||||||
# Store original directory
|
# Check if we're in the right directory
|
||||||
ORIGINAL_DIR="$PWD"
|
if [[ ! -f "update.sh" ]]; then
|
||||||
|
log_error "Please run this test from the directory containing update.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure update.sh is executable
|
||||||
|
chmod +x update.sh 2>/dev/null || true
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
test_script_exists
|
test_script_exists
|
||||||
@@ -418,14 +633,19 @@ main() {
|
|||||||
test_help_option
|
test_help_option
|
||||||
test_dots_structure
|
test_dots_structure
|
||||||
test_flat_structure
|
test_flat_structure
|
||||||
test_package_detection
|
test_dots_mapping
|
||||||
test_ignore_patterns
|
test_ignore_patterns
|
||||||
|
test_safe_read_security
|
||||||
test_dry_run
|
test_dry_run
|
||||||
test_shellcheck
|
test_package_detection
|
||||||
|
test_force_check
|
||||||
|
test_conflict_handling
|
||||||
test_flags
|
test_flags
|
||||||
|
test_git_safety
|
||||||
# Return to original directory
|
test_shellcheck
|
||||||
cd "$ORIGINAL_DIR" || exit 1
|
test_fresh_clone
|
||||||
|
test_verbose_mode
|
||||||
|
test_package_checking
|
||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
echo -e "\n${BLUE}================================${NC}"
|
echo -e "\n${BLUE}================================${NC}"
|
||||||
@@ -436,22 +656,24 @@ main() {
|
|||||||
echo -e "${BLUE}Total: $((TESTS_PASSED + TESTS_FAILED))${NC}\n"
|
echo -e "${BLUE}Total: $((TESTS_PASSED + TESTS_FAILED))${NC}\n"
|
||||||
|
|
||||||
if [[ $TESTS_FAILED -eq 0 ]]; then
|
if [[ $TESTS_FAILED -eq 0 ]]; then
|
||||||
echo -e "${GREEN}All tests passed!${NC}\n"
|
echo -e "${GREEN}All tests passed! 🎉${NC}\n"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
echo -e "${RED}Some tests failed!${NC}\n"
|
echo -e "${RED}Some tests failed! ❌${NC}\n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Trap cleanup - only cleanup TEST_DIR if it exists
|
# Trap cleanup
|
||||||
cleanup_on_exit() {
|
cleanup_on_exit() {
|
||||||
if [[ -n "${TEST_DIR:-}" && -d "$TEST_DIR" ]]; then
|
if [[ -n "${TEST_DIR:-}" && -d "$TEST_DIR" ]]; then
|
||||||
rm -rf "$TEST_DIR"
|
rm -rf "$TEST_DIR"
|
||||||
fi
|
fi
|
||||||
|
# Cleanup any test files created in home
|
||||||
|
rm -rf "${HOME}/.config/test-app" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
trap cleanup_on_exit EXIT
|
trap cleanup_on_exit EXIT INT TERM
|
||||||
|
|
||||||
# Run if executed directly
|
# Run if executed directly
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user