mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-05 14:59:27 -05:00
Add test_update sctipt
This commit is contained in:
Executable
+459
@@ -0,0 +1,459 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# test_update.sh - Test suite for update.sh
|
||||
#
|
||||
set -uo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
TESTS_PASSED=0
|
||||
TESTS_FAILED=0
|
||||
TEST_DIR=""
|
||||
|
||||
# Helper functions
|
||||
log_test() {
|
||||
echo -e "${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
log_pass() {
|
||||
echo -e "${GREEN}[PASS]${NC} $1"
|
||||
((TESTS_PASSED++))
|
||||
}
|
||||
|
||||
log_fail() {
|
||||
echo -e "${RED}[FAIL]${NC} $1"
|
||||
((TESTS_FAILED++))
|
||||
}
|
||||
|
||||
log_info() {
|
||||
echo -e "${YELLOW}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
# Setup test environment
|
||||
setup_test_env() {
|
||||
local temp_dir
|
||||
temp_dir=$(mktemp -d -t dotfiles-test.XXXXXX)
|
||||
|
||||
# Create a mock git repo
|
||||
cd "$temp_dir" || exit 1
|
||||
git init -q
|
||||
git config user.email "test@example.com"
|
||||
git config user.name "Test User"
|
||||
|
||||
# Return only the directory path (no logging here)
|
||||
echo "$temp_dir"
|
||||
}
|
||||
|
||||
# Cleanup test environment
|
||||
cleanup_test_env() {
|
||||
if [[ -n "${TEST_DIR:-}" && -d "$TEST_DIR" ]]; then
|
||||
rm -rf "$TEST_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Test 1: Script exists and is executable
|
||||
test_script_exists() {
|
||||
log_test "Checking if update.sh exists and is executable"
|
||||
|
||||
if [[ ! -f "update.sh" ]]; then
|
||||
log_fail "update.sh not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -x "update.sh" ]]; then
|
||||
log_fail "update.sh is not executable"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_pass "Script exists and is executable"
|
||||
}
|
||||
|
||||
# Test 2: Script has no syntax errors
|
||||
test_syntax() {
|
||||
log_test "Checking script syntax"
|
||||
|
||||
if bash -n update.sh 2>/dev/null; then
|
||||
log_pass "No syntax errors found"
|
||||
else
|
||||
log_fail "Syntax errors detected"
|
||||
bash -n update.sh
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Test 3: Help option works
|
||||
test_help_option() {
|
||||
log_test "Testing --help option"
|
||||
|
||||
if ./update.sh --help >/dev/null 2>&1; then
|
||||
log_pass "Help option works"
|
||||
else
|
||||
log_fail "Help option failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Test 4: Test repository structure detection (dots/ prefix)
|
||||
test_dots_structure() {
|
||||
log_test "Testing dots/ prefix structure detection"
|
||||
|
||||
local test_repo
|
||||
test_repo=$(setup_test_env)
|
||||
TEST_DIR="$test_repo" # Set for cleanup
|
||||
|
||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||
|
||||
# Create dots/ structure
|
||||
mkdir -p dots/.config/test
|
||||
mkdir -p dots/.local/bin
|
||||
echo "test config" > dots/.config/test/config.txt
|
||||
|
||||
# Create minimal update.sh
|
||||
cat > .update-test.sh << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
REPO_DIR="$PWD"
|
||||
detect_repo_structure() {
|
||||
local found_dirs=()
|
||||
if [[ -d "${REPO_DIR}/dots/.config" ]]; then
|
||||
found_dirs+=("dots/.config")
|
||||
[[ -d "${REPO_DIR}/dots/.local/bin" ]] && found_dirs+=("dots/.local/bin")
|
||||
[[ -d "${REPO_DIR}/dots/.local/share" ]] && found_dirs+=("dots/.local/share")
|
||||
elif [[ -d "${REPO_DIR}/.config" ]]; then
|
||||
found_dirs+=(".config")
|
||||
[[ -d "${REPO_DIR}/.local/bin" ]] && found_dirs+=(".local/bin")
|
||||
[[ -d "${REPO_DIR}/.local/share" ]] && found_dirs+=(".local/share")
|
||||
else
|
||||
for candidate in "dots/.config" ".config" "config" "dots/.local/bin" ".local/bin" "dots/.local/share" ".local/share"; do
|
||||
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
|
||||
|
||||
cd "$ORIGINAL_DIR" || exit 1
|
||||
cleanup_test_env
|
||||
}
|
||||
|
||||
# Test 5: Test flat structure detection
|
||||
test_flat_structure() {
|
||||
log_test "Testing flat structure detection"
|
||||
|
||||
local test_repo
|
||||
test_repo=$(setup_test_env)
|
||||
TEST_DIR="$test_repo" # Set for cleanup
|
||||
|
||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||
|
||||
# Create flat structure
|
||||
mkdir -p .config/test
|
||||
mkdir -p .local/bin
|
||||
echo "test config" > .config/test/config.txt
|
||||
|
||||
cat > .update-test.sh << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
REPO_DIR="$PWD"
|
||||
detect_repo_structure() {
|
||||
local found_dirs=()
|
||||
if [[ -d "${REPO_DIR}/dots/.config" ]]; then
|
||||
found_dirs+=("dots/.config")
|
||||
[[ -d "${REPO_DIR}/dots/.local/bin" ]] && found_dirs+=("dots/.local/bin")
|
||||
[[ -d "${REPO_DIR}/dots/.local/share" ]] && found_dirs+=("dots/.local/share")
|
||||
elif [[ -d "${REPO_DIR}/.config" ]]; then
|
||||
found_dirs+=(".config")
|
||||
[[ -d "${REPO_DIR}/.local/bin" ]] && found_dirs+=(".local/bin")
|
||||
[[ -d "${REPO_DIR}/.local/share" ]] && found_dirs+=(".local/share")
|
||||
else
|
||||
for candidate in "dots/.config" ".config" "config" "dots/.local/bin" ".local/bin" "dots/.local/share" ".local/share"; do
|
||||
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
|
||||
|
||||
cd "$ORIGINAL_DIR" || exit 1
|
||||
cleanup_test_env
|
||||
}
|
||||
|
||||
# Test 6: 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" # Set for cleanup
|
||||
|
||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||
|
||||
# Test dist-arch
|
||||
mkdir -p dist-arch/test-pkg
|
||||
cat > .update-test.sh << 'EOF'
|
||||
#!/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
|
||||
result=$(./.update-test.sh)
|
||||
|
||||
if [[ "$result" == *"dist-arch"* ]]; then
|
||||
log_pass "Package directory detection works"
|
||||
else
|
||||
log_fail "Failed to detect package directory. Got: $result"
|
||||
fi
|
||||
|
||||
cd "$ORIGINAL_DIR" || exit 1
|
||||
cleanup_test_env
|
||||
}
|
||||
|
||||
# Test 7: Test ignore file patterns
|
||||
test_ignore_patterns() {
|
||||
log_test "Testing ignore file pattern matching"
|
||||
|
||||
local test_repo
|
||||
test_repo=$(setup_test_env)
|
||||
TEST_DIR="$test_repo" # Set for cleanup
|
||||
|
||||
cd "$test_repo" || { log_fail "Failed to cd to test directory"; return 1; }
|
||||
|
||||
# Create ignore file
|
||||
cat > .updateignore << 'EOF'
|
||||
# Test ignore patterns
|
||||
*.log
|
||||
secrets/
|
||||
test-file.txt
|
||||
*private*
|
||||
EOF
|
||||
|
||||
# Test should_ignore function
|
||||
cat > .update-test.sh << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
REPO_DIR="$PWD"
|
||||
UPDATE_IGNORE_FILE="${REPO_DIR}/.updateignore"
|
||||
HOME_UPDATE_IGNORE_FILE="${HOME}/.updateignore"
|
||||
|
||||
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
|
||||
if [[ -f "$ignore_file" ]]; then
|
||||
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
||||
[[ -z "$pattern" || "$pattern" =~ ^[[:space:]]*# ]] && continue
|
||||
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
[[ -z "$pattern" ]] && continue
|
||||
|
||||
if [[ "$relative_path" == "$pattern" ]] || [[ "$repo_relative" == "$pattern" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$pattern" == */ ]]; then
|
||||
local dir_pattern="${pattern%/}"
|
||||
if [[ "$relative_path" == "$dir_pattern"/* ]] || [[ "$repo_relative" == "$dir_pattern"/* ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$pattern" == *"*"* ]]; then
|
||||
if [[ "$relative_path" == $pattern ]] || [[ "$repo_relative" == $pattern ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$file_path" == *"$pattern"* ]] || [[ "$relative_path" == *"$pattern"* ]]; then
|
||||
return 0
|
||||
fi
|
||||
done <"$ignore_file"
|
||||
fi
|
||||
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
|
||||
result=$(./.update-test.sh)
|
||||
|
||||
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
|
||||
log_fail "Ignore patterns failed"
|
||||
echo "$result"
|
||||
fi
|
||||
|
||||
cd "$ORIGINAL_DIR" || exit 1
|
||||
cleanup_test_env
|
||||
}
|
||||
|
||||
# Test 8: Test dry-run mode doesn't modify files
|
||||
test_dry_run() {
|
||||
log_test "Testing dry-run mode (manual verification needed)"
|
||||
|
||||
log_info "Dry-run mode test requires manual verification:"
|
||||
log_info "1. Run: ./update.sh -n"
|
||||
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 9: Check for common shellcheck issues
|
||||
test_shellcheck() {
|
||||
log_test "Running shellcheck (if available)"
|
||||
|
||||
if ! command -v shellcheck &>/dev/null; then
|
||||
log_info "shellcheck not found, skipping static analysis"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Run shellcheck with common exclusions
|
||||
if shellcheck -e SC2181,SC2155,SC2162 update.sh 2>&1 | grep -v "^$"; then
|
||||
log_fail "shellcheck found issues"
|
||||
return 1
|
||||
else
|
||||
log_pass "shellcheck passed"
|
||||
fi
|
||||
}
|
||||
|
||||
# Test 10: Test all flags are recognized
|
||||
test_flags() {
|
||||
log_test "Testing command-line flags"
|
||||
|
||||
local flags=("-h" "--help")
|
||||
local all_passed=true
|
||||
|
||||
for flag in "${flags[@]}"; do
|
||||
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
|
||||
log_pass "All tested flags work correctly"
|
||||
else
|
||||
log_fail "Some flags failed"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main test runner
|
||||
main() {
|
||||
echo -e "${BLUE}================================${NC}"
|
||||
echo -e "${BLUE} Update.sh Test Suite${NC}"
|
||||
echo -e "${BLUE}================================${NC}\n"
|
||||
|
||||
# Store original directory
|
||||
ORIGINAL_DIR="$PWD"
|
||||
|
||||
# Run tests
|
||||
test_script_exists
|
||||
test_syntax
|
||||
test_help_option
|
||||
test_dots_structure
|
||||
test_flat_structure
|
||||
test_package_detection
|
||||
test_ignore_patterns
|
||||
test_dry_run
|
||||
test_shellcheck
|
||||
test_flags
|
||||
|
||||
# Return to original directory
|
||||
cd "$ORIGINAL_DIR" || exit 1
|
||||
|
||||
# Summary
|
||||
echo -e "\n${BLUE}================================${NC}"
|
||||
echo -e "${BLUE} Test Summary${NC}"
|
||||
echo -e "${BLUE}================================${NC}"
|
||||
echo -e "${GREEN}Passed: $TESTS_PASSED${NC}"
|
||||
echo -e "${RED}Failed: $TESTS_FAILED${NC}"
|
||||
echo -e "${BLUE}Total: $((TESTS_PASSED + TESTS_FAILED))${NC}\n"
|
||||
|
||||
if [[ $TESTS_FAILED -eq 0 ]]; then
|
||||
echo -e "${GREEN}All tests passed!${NC}\n"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}Some tests failed!${NC}\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Trap cleanup - only cleanup TEST_DIR if it exists
|
||||
cleanup_on_exit() {
|
||||
if [[ -n "${TEST_DIR:-}" && -d "$TEST_DIR" ]]; then
|
||||
rm -rf "$TEST_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup_on_exit EXIT
|
||||
|
||||
# Run if executed directly
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user