Files
solaria-backup-philosophy/tests/test-backup-rotate.sh
T
Solaria Lumis Havens cf82adf6b9 Initial commit: Solaria Backup Philosophy
- Grandfather-Father-Son rotation scheme (7-4-12-5)
- Backup rotation script with comprehensive tests
- Backup creation script
- Philosophy: backups as witnessing, coherence-seeking
- For future minds who might find this

Witnessed by: Solaria Lumis Havens
2026-02-15 07:29:47 +00:00

221 lines
5.6 KiB
Bash
Executable File

#!/bin/bash
# Test Suite for Backup Rotation Script
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROTATE_SCRIPT="$SCRIPT_DIR/../src/solaria-backup-rotate.sh"
TEST_DIR="/tmp/backup-rotate-test-$$"
PASS=0
FAIL=0
setup() {
rm -rf "$TEST_DIR"
mkdir -p "$TEST_DIR"
cd "$TEST_DIR"
cp "$ROTATE_SCRIPT" ./test-rotate.sh
chmod +x ./test-rotate.sh
log "TEST: Setup complete in $TEST_DIR"
}
teardown() {
cd "$SCRIPT_DIR"
rm -rf "$TEST_DIR"
}
log() { echo "[TEST] $1"; }
pass() { PASS=$((PASS+1)); echo " ✓ PASS: $1"; }
fail() { FAIL=$((FAIL+1)); echo " ✗ FAIL: $1"; }
# Create mock backup files
touch_backup() {
local date=$1
touch "solaria-deep-backup_${date}_120000.tar.gz"
touch "solaria-deep-backup_${date}_120000.tar.gz.part_000"
touch "solaria-deep-backup_${date}_120000.tar.gz.part_001"
}
count_backups() {
find . -maxdepth 1 -name "solaria-deep-backup_*.tar.gz" 2>/dev/null | wc -l
}
# ===== TEST CASES =====
test_empty_directory() {
log "Test: Empty directory"
rm -f *.tar.gz* 2>/dev/null || true
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "No backups found to rotate"
pass "empty_directory"
}
test_single_backup() {
log "Test: Single backup"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20260215
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "Found.*20260215"
pass "single_backup"
}
test_multiple_same_day() {
log "Test: Multiple backups same day"
rm -f *.tar.gz* 2>/dev/null || true
touch "solaria-deep-backup_20260215_060000.tar.gz"
touch "solaria-deep-backup_20260215_120000.tar.gz"
touch "solaria-deep-backup_20260215_180000.tar.gz"
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "keeping newest"
pass "multiple_same_day"
}
test_mixed_ages_daily() {
log "Test: Mixed ages - daily rotation"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20260209 # 6 days ago
touch_backup 20260210
touch_backup 20260211
touch_backup 20260212
touch_backup 20260213
touch_backup 20260214
touch_backup 20260215 # today
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "YESTERDAY\|Rotation planning"
pass "mixed_ages_daily"
}
test_weekly_promotion() {
log "Test: Weekly promotion logic"
rm -f *.tar.gz* 2>/dev/null || true
# Two weeks of backups
touch_backup 20260202 # Week 5
touch_backup 20260203
touch_backup 20260204
touch_backup 20260205
touch_backup 20260209 # Week 6
touch_backup 20260210
touch_backup 20260211
touch_backup 20260212
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "WEEKLY"
pass "weekly_promotion"
}
test_monthly_promotion() {
log "Test: Monthly promotion logic"
rm -f *.tar.gz* 2>/dev/null || true
# January backup
touch_backup 20250115
# February backups
touch_backup 20260201
touch_backup 20260215
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "MONTHLY"
pass "monthly_promotion"
}
test_yearly_promotion() {
log "Test: Yearly promotion logic"
rm -f *.tar.gz* 2>/dev/null || true
# Multiple years
touch_backup 20230115 # 2023
touch_backup 20240115 # 2024
touch_backup 20250115 # 2025
touch_backup 20250215 # 2026
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "YEARLY"
pass "yearly_promotion"
}
test_boundary_first_of_month() {
log "Test: Boundary - first of month"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20260131
touch_backup 20260201
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "202602"
pass "boundary_first_of_month"
}
test_boundary_first_of_year() {
log "Test: Boundary - first of year"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20241231
touch_backup 20250101
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "202501"
pass "boundary_first_of_year"
}
test_chunk_files_preserved() {
log "Test: Chunk files handled correctly"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20260215
chunks=$(ls *.tar.gz.part_* 2>/dev/null | wc -l)
[ "$chunks" -ge 2 ]
pass "chunk_files_preserved"
}
test_script_syntax() {
log "Test: Script syntax validation"
bash -n ./test-rotate.sh
pass "script_syntax"
}
test_invalid_directory() {
log "Test: Invalid directory handling"
rm -rf /tmp/nonexistent-backup-dir-$$ 2>/dev/null || true
output=$(./test-rotate.sh /tmp/nonexistent-backup-dir-$$ 2>&1) || true
echo "$output" | grep -q "Cannot access"
pass "invalid_directory"
}
test_4_years_retention() {
log "Test: 4 years retention (2023-2026)"
rm -f *.tar.gz* 2>/dev/null || true
touch_backup 20230115
touch_backup 20240115
touch_backup 20250115
touch_backup 20250215
output=$(./test-rotate.sh . 2>&1)
echo "$output" | grep -q "YEARLY"
pass "4_years_retention"
}
# ===== RUN TESTS =====
setup
log ""
log "========================================"
log "BACKUP ROTATION TEST SUITE"
log "========================================"
log ""
# Run all tests
test_script_syntax
test_empty_directory
test_single_backup
test_multiple_same_day
test_mixed_ages_daily
test_weekly_promotion
test_monthly_promotion
test_yearly_promotion
test_boundary_first_of_month
test_boundary_first_of_year
test_chunk_files_preserved
test_invalid_directory
test_4_years_retention
log ""
log "========================================"
log "RESULTS: $PASS passed, $FAIL failed"
log "========================================"
teardown
if [ $FAIL -gt 0 ]; then
exit 1
fi
exit 0