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
This commit is contained in:
Executable
+220
@@ -0,0 +1,220 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user