diff options
Diffstat (limited to 'tests/cases')
| -rwxr-xr-x | tests/cases/test_backup.sh | 239 | ||||
| -rwxr-xr-x | tests/cases/test_cron.sh | 138 | ||||
| -rwxr-xr-x | tests/cases/test_dryrun.sh | 120 | ||||
| -rwxr-xr-x | tests/cases/test_includes.sh | 161 | ||||
| -rwxr-xr-x | tests/cases/test_validation.sh | 106 |
5 files changed, 764 insertions, 0 deletions
diff --git a/tests/cases/test_backup.sh b/tests/cases/test_backup.sh new file mode 100755 index 0000000..1ab4fbd --- /dev/null +++ b/tests/cases/test_backup.sh @@ -0,0 +1,239 @@ +#!/usr/bin/env bash +# ============================================================================== +# Backup and Rotation Tests +# ============================================================================== + +source "$(dirname "${BASH_SOURCE[0]}")/../lib/test_helpers.sh" + +# ------------------------------------------------------------------------------ +# Test: Creates backup directory structure +# ------------------------------------------------------------------------------ +test_creates_backup_structure() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 1 2>&1) + local exit_code=$? + + # Check directory structure + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME" "should create hostname dir" || { + teardown_test_env + return 1 + } + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest" "should create latest dir" || { + teardown_test_env + return 1 + } + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.0" "should create MANUAL.0 snapshot" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Copies files to backup +# ------------------------------------------------------------------------------ +test_copies_files() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 1 2>&1) + + # Check files were copied + assert_file_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest/home/testuser/file1.txt" "should copy file1.txt" || { + teardown_test_env + return 1 + } + assert_file_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest/etc/test.conf" "should copy test.conf" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Snapshot is read-only +# ------------------------------------------------------------------------------ +test_snapshot_readonly() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 1 2>&1) + + # Check snapshot directory has no write permission + # Note: We use stat to check actual permissions because -w always returns true for root + local perms + perms=$(stat -c '%A' "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.0" 2>/dev/null) + if [[ "$perms" == *w* ]]; then + echo "FAIL: Snapshot should be read-only (perms: $perms)" + teardown_test_env + return 1 + fi + + teardown_test_env + return 0 +} + +# ------------------------------------------------------------------------------ +# Test: Rotation works correctly +# ------------------------------------------------------------------------------ +test_rotation() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + # Run backup twice + sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 3 2>&1 >/dev/null + sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 3 2>&1 >/dev/null + + # Should have MANUAL.0 and MANUAL.1 + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.0" "should have MANUAL.0" || { + teardown_test_env + return 1 + } + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.1" "should have MANUAL.1 after rotation" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Deletes oldest snapshot beyond retention +# ------------------------------------------------------------------------------ +test_retention_limit() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + # Run backup 4 times with retention of 3 + for i in 1 2 3 4; do + sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 3 2>&1 >/dev/null + done + + # Should have MANUAL.0, MANUAL.1, MANUAL.2 but NOT MANUAL.3 + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.0" "should have MANUAL.0" || { + teardown_test_env + return 1 + } + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.1" "should have MANUAL.1" || { + teardown_test_env + return 1 + } + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.2" "should have MANUAL.2" || { + teardown_test_env + return 1 + } + assert_dir_not_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.3" "should NOT have MANUAL.3 (beyond retention)" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Backup command works as alias +# ------------------------------------------------------------------------------ +test_backup_command() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" backup 2>&1) + local exit_code=$? + + # Should create MANUAL.0 (backup is alias for manual 1) + assert_dir_exists "$TEST_BACKUP_DIR/$HOSTNAME/MANUAL.0" "backup should create MANUAL.0" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Excludes files matching patterns +# ------------------------------------------------------------------------------ +test_excludes_patterns() { + setup_test_env + + create_test_config + create_test_includes + + # Create exclude file + cat > "$TEST_CONFIG_DIR/exclude.txt" << 'EOF' +*.tmp +*.log +EOF + + # Create files that should be excluded + echo "temp" > "$TEST_SOURCE_DIR/home/testuser/temp.tmp" + echo "log" > "$TEST_SOURCE_DIR/home/testuser/app.log" + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" manual 1 2>&1) + + # Excluded files should not exist in backup + assert_file_not_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest/home/testuser/temp.tmp" "should exclude .tmp files" || { + teardown_test_env + return 1 + } + assert_file_not_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest/home/testuser/app.log" "should exclude .log files" || { + teardown_test_env + return 1 + } + # Regular files should still exist + assert_file_exists "$TEST_BACKUP_DIR/$HOSTNAME/latest/home/testuser/file1.txt" "should include regular files" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Run tests +# ------------------------------------------------------------------------------ +run_backup_tests() { + echo "" + echo "Running backup tests..." + echo "------------------------------------------------------------" + + run_test "creates backup directory structure" test_creates_backup_structure + run_test "copies files to backup" test_copies_files + run_test "snapshot is read-only" test_snapshot_readonly + run_test "rotation works correctly" test_rotation + run_test "respects retention limit" test_retention_limit + run_test "backup command works as alias" test_backup_command + run_test "excludes files matching patterns" test_excludes_patterns +} + +# Run if executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_backup_tests + print_summary +fi diff --git a/tests/cases/test_cron.sh b/tests/cases/test_cron.sh new file mode 100755 index 0000000..2fdb6f5 --- /dev/null +++ b/tests/cases/test_cron.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +# ============================================================================== +# Cron Job Management Tests +# ============================================================================== + +source "$(dirname "${BASH_SOURCE[0]}")/../lib/test_helpers.sh" + +# Save original crontab to restore later +ORIGINAL_CRONTAB="" + +save_crontab() { + ORIGINAL_CRONTAB=$(crontab -l 2>/dev/null || true) +} + +restore_crontab() { + if [ -n "$ORIGINAL_CRONTAB" ]; then + echo "$ORIGINAL_CRONTAB" | crontab - + else + crontab -r 2>/dev/null || true + fi +} + +# ------------------------------------------------------------------------------ +# Test: Setup adds cron jobs +# ------------------------------------------------------------------------------ +test_setup_adds_cron_jobs() { + setup_test_env + save_crontab + + # Clear existing crontab + crontab -r 2>/dev/null || true + + # Create minimal config + cat > "$TEST_CONFIG_DIR/config" << EOF +REMOTE_HOST="" +MOUNTDIR="$TEST_BACKUP_DIR" +EOF + create_test_includes + create_test_excludes + + # Run setup (will fail on some checks but should still add cron) + sudo INSTALLHOME="$TEST_CONFIG_DIR" SCRIPTLOC="/tmp/rsyncshot-test" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" setup 2>&1 >/dev/null || true + + # Check crontab contains rsyncshot entries + local crontab_content + crontab_content=$(crontab -l 2>/dev/null) + + restore_crontab + teardown_test_env + + assert_contains "$crontab_content" "rsyncshot" "crontab should contain rsyncshot" || return 1 + assert_contains "$crontab_content" "hourly" "crontab should contain hourly job" || return 1 + assert_contains "$crontab_content" "daily" "crontab should contain daily job" || return 1 + assert_contains "$crontab_content" "weekly" "crontab should contain weekly job" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Repeated setup doesn't duplicate entries +# ------------------------------------------------------------------------------ +test_no_duplicate_cron_entries() { + setup_test_env + save_crontab + + # Clear existing crontab + crontab -r 2>/dev/null || true + + cat > "$TEST_CONFIG_DIR/config" << EOF +REMOTE_HOST="" +MOUNTDIR="$TEST_BACKUP_DIR" +EOF + create_test_includes + create_test_excludes + + # Run setup twice + sudo INSTALLHOME="$TEST_CONFIG_DIR" SCRIPTLOC="/tmp/rsyncshot-test" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" setup 2>&1 >/dev/null || true + sudo INSTALLHOME="$TEST_CONFIG_DIR" SCRIPTLOC="/tmp/rsyncshot-test" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" setup 2>&1 >/dev/null || true + + # Count rsyncshot entries + local crontab_content hourly_count + crontab_content=$(crontab -l 2>/dev/null) + hourly_count=$(echo "$crontab_content" | grep -c "hourly" || echo 0) + + restore_crontab + teardown_test_env + + # Should only have 1 hourly entry, not 2 + assert_equals "1" "$hourly_count" "should have exactly 1 hourly entry after repeated setup" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Setup preserves existing cron jobs +# ------------------------------------------------------------------------------ +test_preserves_existing_cron() { + setup_test_env + save_crontab + + # Add a custom cron job + (crontab -l 2>/dev/null || true; echo "0 5 * * * /custom/job.sh") | crontab - + + cat > "$TEST_CONFIG_DIR/config" << EOF +REMOTE_HOST="" +MOUNTDIR="$TEST_BACKUP_DIR" +EOF + create_test_includes + create_test_excludes + + # Run setup + sudo INSTALLHOME="$TEST_CONFIG_DIR" SCRIPTLOC="/tmp/rsyncshot-test" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" setup 2>&1 >/dev/null || true + + # Check custom job still exists + local crontab_content + crontab_content=$(crontab -l 2>/dev/null) + + restore_crontab + teardown_test_env + + assert_contains "$crontab_content" "/custom/job.sh" "should preserve existing cron jobs" || return 1 + assert_contains "$crontab_content" "rsyncshot" "should also have rsyncshot jobs" || return 1 +} + +# ------------------------------------------------------------------------------ +# Run tests +# ------------------------------------------------------------------------------ +run_cron_tests() { + echo "" + echo "Running cron tests..." + echo "------------------------------------------------------------" + + run_test "setup adds cron jobs" test_setup_adds_cron_jobs + run_test "repeated setup doesn't duplicate entries" test_no_duplicate_cron_entries + run_test "setup preserves existing cron jobs" test_preserves_existing_cron +} + +# Run if executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_cron_tests + print_summary +fi diff --git a/tests/cases/test_dryrun.sh b/tests/cases/test_dryrun.sh new file mode 100755 index 0000000..bff45e1 --- /dev/null +++ b/tests/cases/test_dryrun.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# ============================================================================== +# Dry-Run Mode Tests +# ============================================================================== + +source "$(dirname "${BASH_SOURCE[0]}")/../lib/test_helpers.sh" + +# ------------------------------------------------------------------------------ +# Test: Dry-run doesn't create backup directory +# ------------------------------------------------------------------------------ +test_dryrun_no_directory_creation() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + # Remove backup dir to verify it's not created + rmdir "$TEST_BACKUP_DIR" + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + # Backup directory should NOT be created in dry-run mode + assert_dir_not_exists "$TEST_BACKUP_DIR/$HOSTNAME" "backup dir should not be created in dryrun" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Test: Dry-run shows what would be transferred +# ------------------------------------------------------------------------------ +test_dryrun_shows_transfer_info() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + # Create the backup directory structure for dryrun to work + mkdir -p "$TEST_BACKUP_DIR/$HOSTNAME/latest" + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + teardown_test_env + + # Should show syncing messages + assert_contains "$output" "Syncing" "should show syncing info" || return 1 + # Should show dry run message + assert_contains "$output" "Dry run complete" "should show dryrun complete message" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Dry-run shows command to run actual backup +# ------------------------------------------------------------------------------ +test_dryrun_shows_actual_command() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + mkdir -p "$TEST_BACKUP_DIR/$HOSTNAME/latest" + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + teardown_test_env + + # Should show how to run actual backup + assert_contains "$output" "sudo rsyncshot manual 1" "should show actual command" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Dry-run doesn't create snapshots +# ------------------------------------------------------------------------------ +test_dryrun_no_snapshot_creation() { + setup_test_env + + create_test_config + create_test_includes + create_test_excludes + + mkdir -p "$TEST_BACKUP_DIR/$HOSTNAME/latest" + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + # Should not create manual.0 snapshot + assert_dir_not_exists "$TEST_BACKUP_DIR/$HOSTNAME/manual.0" "snapshot should not be created in dryrun" || { + teardown_test_env + return 1 + } + + teardown_test_env +} + +# ------------------------------------------------------------------------------ +# Run tests +# ------------------------------------------------------------------------------ +run_dryrun_tests() { + echo "" + echo "Running dry-run tests..." + echo "------------------------------------------------------------" + + run_test "dry-run doesn't create backup directory" test_dryrun_no_directory_creation + run_test "dry-run shows transfer info" test_dryrun_shows_transfer_info + run_test "dry-run shows actual command" test_dryrun_shows_actual_command + run_test "dry-run doesn't create snapshots" test_dryrun_no_snapshot_creation +} + +# Run if executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_dryrun_tests + print_summary +fi diff --git a/tests/cases/test_includes.sh b/tests/cases/test_includes.sh new file mode 100755 index 0000000..8f556e3 --- /dev/null +++ b/tests/cases/test_includes.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash +# ============================================================================== +# Include File Parsing Tests +# ============================================================================== + +source "$(dirname "${BASH_SOURCE[0]}")/../lib/test_helpers.sh" + +# ------------------------------------------------------------------------------ +# Test: Reads newline-separated paths +# ------------------------------------------------------------------------------ +test_reads_newline_paths() { + setup_test_env + + # Create config and include files + create_test_config + create_test_excludes + + # Create include file with newline-separated paths + cat > "$TEST_CONFIG_DIR/include.txt" << EOF +$TEST_SOURCE_DIR/home +$TEST_SOURCE_DIR/etc +EOF + + # Run dryrun to test parsing + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + local exit_code=$? + + teardown_test_env + + # Should process both directories + assert_contains "$output" "Syncing $TEST_SOURCE_DIR/home" "should sync home" || return 1 + assert_contains "$output" "Syncing $TEST_SOURCE_DIR/etc" "should sync etc" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Skips comment lines +# ------------------------------------------------------------------------------ +test_skips_comments() { + setup_test_env + + create_test_config + create_test_excludes + + # Create include file with comments + cat > "$TEST_CONFIG_DIR/include.txt" << EOF +# This is a comment +$TEST_SOURCE_DIR/home +# Another comment +$TEST_SOURCE_DIR/etc +EOF + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + teardown_test_env + + # Should not try to sync comment lines + assert_not_contains "$output" "Syncing # This" "should skip comments" || return 1 + assert_contains "$output" "Syncing $TEST_SOURCE_DIR/home" "should sync home" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Skips empty lines +# ------------------------------------------------------------------------------ +test_skips_empty_lines() { + setup_test_env + + create_test_config + create_test_excludes + + # Create include file with empty lines + cat > "$TEST_CONFIG_DIR/include.txt" << EOF +$TEST_SOURCE_DIR/home + +$TEST_SOURCE_DIR/etc + +EOF + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + teardown_test_env + + # Should process both directories without errors + assert_contains "$output" "Syncing $TEST_SOURCE_DIR/home" "should sync home" || return 1 + assert_contains "$output" "Syncing $TEST_SOURCE_DIR/etc" "should sync etc" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Handles paths with spaces +# ------------------------------------------------------------------------------ +test_handles_paths_with_spaces() { + setup_test_env + + create_test_config + create_test_excludes + + # Create a directory with spaces + mkdir -p "$TEST_SOURCE_DIR/path with spaces" + echo "test" > "$TEST_SOURCE_DIR/path with spaces/file.txt" + + # Create include file with path containing spaces + cat > "$TEST_CONFIG_DIR/include.txt" << EOF +$TEST_SOURCE_DIR/path with spaces +EOF + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + + teardown_test_env + + # Should handle the path with spaces + assert_contains "$output" "path with spaces" "should handle spaces in path" || return 1 + assert_not_contains "$output" "not found" "should not report path not found" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Reports missing directory +# ------------------------------------------------------------------------------ +test_reports_missing_directory() { + setup_test_env + + create_test_config + create_test_excludes + + # Create include file with non-existent path + cat > "$TEST_CONFIG_DIR/include.txt" << EOF +/nonexistent/path/that/does/not/exist +EOF + + local output + output=$(sudo INSTALLHOME="$TEST_CONFIG_DIR" RSYNCSHOT_SKIP_MOUNT_CHECK=1 "$SCRIPT_PATH" dryrun manual 1 2>&1) + local exit_code=$? + + teardown_test_env + + assert_exit_code 1 "$exit_code" "should fail for missing directory" || return 1 + assert_contains "$output" "not found" "should report directory not found" || return 1 +} + +# ------------------------------------------------------------------------------ +# Run tests +# ------------------------------------------------------------------------------ +run_includes_tests() { + echo "" + echo "Running include file tests..." + echo "------------------------------------------------------------" + + run_test "reads newline-separated paths" test_reads_newline_paths + run_test "skips comment lines" test_skips_comments + run_test "skips empty lines" test_skips_empty_lines + run_test "handles paths with spaces" test_handles_paths_with_spaces + run_test "reports missing directory" test_reports_missing_directory +} + +# Run if executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_includes_tests + print_summary +fi diff --git a/tests/cases/test_validation.sh b/tests/cases/test_validation.sh new file mode 100755 index 0000000..03da676 --- /dev/null +++ b/tests/cases/test_validation.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# ============================================================================== +# Input Validation Tests +# ============================================================================== + +source "$(dirname "${BASH_SOURCE[0]}")/../lib/test_helpers.sh" + +# ------------------------------------------------------------------------------ +# Test: Help works without root +# ------------------------------------------------------------------------------ +test_help_without_root() { + local output + output=$("$SCRIPT_PATH" help 2>&1) + local exit_code=$? + + assert_exit_code 0 "$exit_code" "help should exit with 0" || return 1 + assert_contains "$output" "rsyncshot" "help should mention rsyncshot" || return 1 + assert_contains "$output" "Usage" "help should show usage" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Rejects non-alphabetic snapshot type +# ------------------------------------------------------------------------------ +test_rejects_numeric_snapshot_type() { + local output + output=$(sudo "$SCRIPT_PATH" "123" "5" 2>&1) + local exit_code=$? + + assert_exit_code 1 "$exit_code" "should reject numeric snapshot type" || return 1 + assert_contains "$output" "must be alphabetic" "should show alphabetic error" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Rejects mixed alphanumeric snapshot type +# ------------------------------------------------------------------------------ +test_rejects_mixed_snapshot_type() { + local output + output=$(sudo "$SCRIPT_PATH" "hourly123" "5" 2>&1) + local exit_code=$? + + assert_exit_code 1 "$exit_code" "should reject mixed snapshot type" || return 1 + assert_contains "$output" "must be alphabetic" "should show alphabetic error" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Rejects non-numeric retention count +# ------------------------------------------------------------------------------ +test_rejects_alpha_retention_count() { + local output + output=$(sudo "$SCRIPT_PATH" "manual" "abc" 2>&1) + local exit_code=$? + + assert_exit_code 1 "$exit_code" "should reject alphabetic count" || return 1 + assert_contains "$output" "must be a number" "should show number error" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Rejects mixed alphanumeric retention count +# ------------------------------------------------------------------------------ +test_rejects_mixed_retention_count() { + local output + output=$(sudo "$SCRIPT_PATH" "manual" "5abc" 2>&1) + local exit_code=$? + + assert_exit_code 1 "$exit_code" "should reject mixed count" || return 1 + assert_contains "$output" "must be a number" "should show number error" || return 1 +} + +# ------------------------------------------------------------------------------ +# Test: Accepts valid alphabetic snapshot types +# ------------------------------------------------------------------------------ +test_accepts_valid_snapshot_types() { + # We use dryrun to avoid actual backup, and expect it to fail on missing config + # but it should get past the validation stage + local output + output=$(sudo "$SCRIPT_PATH" dryrun "hourly" "24" 2>&1) + + # Should not contain the validation error (might fail for other reasons like missing config) + assert_not_contains "$output" "must be alphabetic" "should accept valid type" || return 1 +} + +# ------------------------------------------------------------------------------ +# Run tests +# ------------------------------------------------------------------------------ +run_validation_tests() { + echo "" + echo "Running validation tests..." + echo "------------------------------------------------------------" + + setup_test_env + + run_test "help works without root" test_help_without_root + run_test "rejects numeric snapshot type" test_rejects_numeric_snapshot_type + run_test "rejects mixed alphanumeric snapshot type" test_rejects_mixed_snapshot_type + run_test "rejects alphabetic retention count" test_rejects_alpha_retention_count + run_test "rejects mixed retention count" test_rejects_mixed_retention_count + run_test "accepts valid snapshot types" test_accepts_valid_snapshot_types + + teardown_test_env +} + +# Run if executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + run_validation_tests + print_summary +fi |
