|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Tests for migrate_orphaned_supervisor() (GH#5147) |
| 3 | +# Verifies cleanup of orphaned supervisor-helper.sh and supervisor/ modules |
| 4 | + |
| 5 | +set -euo pipefail |
| 6 | + |
| 7 | +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 8 | +MIGRATIONS_SCRIPT="$REPO_DIR/setup-modules/migrations.sh" |
| 9 | + |
| 10 | +PASS_COUNT=0 |
| 11 | +FAIL_COUNT=0 |
| 12 | +TOTAL_COUNT=0 |
| 13 | + |
| 14 | +pass() { |
| 15 | + local name="$1" |
| 16 | + PASS_COUNT=$((PASS_COUNT + 1)) |
| 17 | + TOTAL_COUNT=$((TOTAL_COUNT + 1)) |
| 18 | + printf "\033[0;32mPASS\033[0m %s\n" "$name" |
| 19 | + return 0 |
| 20 | +} |
| 21 | + |
| 22 | +fail() { |
| 23 | + local name="$1" |
| 24 | + local detail="${2:-}" |
| 25 | + FAIL_COUNT=$((FAIL_COUNT + 1)) |
| 26 | + TOTAL_COUNT=$((TOTAL_COUNT + 1)) |
| 27 | + printf "\033[0;31mFAIL\033[0m %s\n" "$name" |
| 28 | + if [[ -n "$detail" ]]; then |
| 29 | + printf " %s\n" "$detail" |
| 30 | + fi |
| 31 | + return 0 |
| 32 | +} |
| 33 | + |
| 34 | +section() { |
| 35 | + echo "" |
| 36 | + echo "=== $1 ===" |
| 37 | + return 0 |
| 38 | +} |
| 39 | + |
| 40 | +# Create a temporary HOME to isolate tests from the real system |
| 41 | +TEST_HOME=$(mktemp -d) |
| 42 | +# shellcheck disable=SC2064 |
| 43 | +trap "rm -rf '$TEST_HOME'" EXIT |
| 44 | + |
| 45 | +# Override HOME for the duration of the test |
| 46 | +export HOME="$TEST_HOME" |
| 47 | + |
| 48 | +# Create the deployed agents directory structure (simulating pre-migration state) |
| 49 | +AGENTS_DIR="$TEST_HOME/.aidevops/agents" |
| 50 | +SCRIPTS_DIR="$AGENTS_DIR/scripts" |
| 51 | +mkdir -p "$SCRIPTS_DIR" |
| 52 | + |
| 53 | +# Stub functions that migrations.sh expects from setup.sh |
| 54 | +print_info() { echo "[INFO] $1"; } |
| 55 | +print_success() { echo "[SUCCESS] $1"; } |
| 56 | +print_warning() { echo "[WARNING] $1"; } |
| 57 | +print_error() { echo "[ERROR] $1"; } |
| 58 | +# _launchd_has_agent is defined in setup.sh; stub it for Linux tests |
| 59 | +_launchd_has_agent() { return 1; } |
| 60 | +# Stubs for other functions referenced by migrations.sh |
| 61 | +find_opencode_config() { return 1; } |
| 62 | +create_backup_with_rotation() { return 0; } |
| 63 | +should_overwrite_user_file() { return 0; } |
| 64 | +resolve_mcp_binary_path() { |
| 65 | + echo "" |
| 66 | + return 1 |
| 67 | +} |
| 68 | +update_mcp_paths_in_opencode() { return 0; } |
| 69 | +sanitize_plugin_namespace() { |
| 70 | + echo "$1" |
| 71 | + return 0 |
| 72 | +} |
| 73 | +# Export stubs so sourced script can find them |
| 74 | +export -f print_info print_success print_warning print_error _launchd_has_agent |
| 75 | +export -f find_opencode_config create_backup_with_rotation should_overwrite_user_file |
| 76 | +export -f resolve_mcp_binary_path update_mcp_paths_in_opencode sanitize_plugin_namespace |
| 77 | + |
| 78 | +# Source the migrations script to get the function |
| 79 | +# shellcheck disable=SC1090 |
| 80 | +source "$MIGRATIONS_SCRIPT" |
| 81 | + |
| 82 | +# ============================================================================ |
| 83 | +section "Test: removes orphaned supervisor-helper.sh" |
| 84 | +# ============================================================================ |
| 85 | + |
| 86 | +# Create orphaned file |
| 87 | +echo '#!/usr/bin/env bash' >"$SCRIPTS_DIR/supervisor-helper.sh" |
| 88 | + |
| 89 | +if [[ -f "$SCRIPTS_DIR/supervisor-helper.sh" ]]; then |
| 90 | + pass "Setup: orphaned supervisor-helper.sh exists before migration" |
| 91 | +else |
| 92 | + fail "Setup: orphaned supervisor-helper.sh should exist" |
| 93 | +fi |
| 94 | + |
| 95 | +migrate_orphaned_supervisor >/dev/null 2>&1 |
| 96 | + |
| 97 | +if [[ ! -f "$SCRIPTS_DIR/supervisor-helper.sh" ]]; then |
| 98 | + pass "supervisor-helper.sh removed after migration" |
| 99 | +else |
| 100 | + fail "supervisor-helper.sh should have been removed" |
| 101 | +fi |
| 102 | + |
| 103 | +# ============================================================================ |
| 104 | +section "Test: removes orphaned supervisor/ module directory" |
| 105 | +# ============================================================================ |
| 106 | + |
| 107 | +# Create orphaned module directory with recognizable files |
| 108 | +mkdir -p "$SCRIPTS_DIR/supervisor" |
| 109 | +echo '#!/usr/bin/env bash' >"$SCRIPTS_DIR/supervisor/pulse.sh" |
| 110 | +echo '#!/usr/bin/env bash' >"$SCRIPTS_DIR/supervisor/dispatch.sh" |
| 111 | +echo '#!/usr/bin/env bash' >"$SCRIPTS_DIR/supervisor/_common.sh" |
| 112 | + |
| 113 | +if [[ -d "$SCRIPTS_DIR/supervisor" ]]; then |
| 114 | + pass "Setup: orphaned supervisor/ directory exists before migration" |
| 115 | +else |
| 116 | + fail "Setup: orphaned supervisor/ directory should exist" |
| 117 | +fi |
| 118 | + |
| 119 | +migrate_orphaned_supervisor >/dev/null 2>&1 |
| 120 | + |
| 121 | +if [[ ! -d "$SCRIPTS_DIR/supervisor" ]]; then |
| 122 | + pass "supervisor/ directory removed after migration" |
| 123 | +else |
| 124 | + fail "supervisor/ directory should have been removed" |
| 125 | +fi |
| 126 | + |
| 127 | +# ============================================================================ |
| 128 | +section "Test: does NOT remove supervisor-archived/" |
| 129 | +# ============================================================================ |
| 130 | + |
| 131 | +mkdir -p "$SCRIPTS_DIR/supervisor-archived" |
| 132 | +echo '#!/usr/bin/env bash' >"$SCRIPTS_DIR/supervisor-archived/supervisor-helper.sh" |
| 133 | + |
| 134 | +migrate_orphaned_supervisor >/dev/null 2>&1 |
| 135 | + |
| 136 | +if [[ -d "$SCRIPTS_DIR/supervisor-archived" ]]; then |
| 137 | + pass "supervisor-archived/ preserved after migration" |
| 138 | +else |
| 139 | + fail "supervisor-archived/ should NOT have been removed" |
| 140 | +fi |
| 141 | + |
| 142 | +# ============================================================================ |
| 143 | +section "Test: does NOT remove unrelated supervisor/ directory" |
| 144 | +# ============================================================================ |
| 145 | + |
| 146 | +# Create a supervisor/ directory without the expected module files |
| 147 | +mkdir -p "$SCRIPTS_DIR/supervisor" |
| 148 | +echo 'custom content' >"$SCRIPTS_DIR/supervisor/my-custom-file.txt" |
| 149 | + |
| 150 | +migrate_orphaned_supervisor >/dev/null 2>&1 |
| 151 | + |
| 152 | +if [[ -d "$SCRIPTS_DIR/supervisor" ]]; then |
| 153 | + pass "Unrelated supervisor/ directory preserved (no module files)" |
| 154 | +else |
| 155 | + fail "Unrelated supervisor/ directory should NOT have been removed" |
| 156 | +fi |
| 157 | + |
| 158 | +# Clean up for next test |
| 159 | +rm -rf "$SCRIPTS_DIR/supervisor" |
| 160 | + |
| 161 | +# ============================================================================ |
| 162 | +section "Test: idempotent — no errors when nothing to clean" |
| 163 | +# ============================================================================ |
| 164 | + |
| 165 | +# Run migration when there's nothing to clean |
| 166 | +output=$(migrate_orphaned_supervisor 2>&1) |
| 167 | +exit_code=$? |
| 168 | + |
| 169 | +if [[ $exit_code -eq 0 ]]; then |
| 170 | + pass "Migration succeeds when nothing to clean (exit 0)" |
| 171 | +else |
| 172 | + fail "Migration should succeed when nothing to clean" "exit code: $exit_code" |
| 173 | +fi |
| 174 | + |
| 175 | +# Should NOT print the success message when nothing was cleaned |
| 176 | +if [[ "$output" != *"Cleaned up"* ]]; then |
| 177 | + pass "No 'Cleaned up' message when nothing to clean" |
| 178 | +else |
| 179 | + fail "Should not print 'Cleaned up' when nothing was cleaned" "$output" |
| 180 | +fi |
| 181 | + |
| 182 | +# ============================================================================ |
| 183 | +section "Test: removes cron entries referencing supervisor-helper.sh" |
| 184 | +# ============================================================================ |
| 185 | + |
| 186 | +# Install a fake cron entry (only if crontab is available) |
| 187 | +if command -v crontab &>/dev/null; then |
| 188 | + # Save current crontab |
| 189 | + original_crontab=$(crontab -l 2>/dev/null) || original_crontab="" |
| 190 | + |
| 191 | + # Install test crontab with supervisor-helper.sh entry |
| 192 | + { |
| 193 | + echo "# aidevops: test-keep-this" |
| 194 | + echo "*/5 * * * * echo keep-this # aidevops: test-keep" |
| 195 | + echo "*/2 * * * * /bin/bash /home/test/.aidevops/agents/scripts/supervisor-helper.sh pulse >> /tmp/test.log 2>&1 # aidevops: supervisor-pulse" |
| 196 | + } | crontab - 2>/dev/null |
| 197 | + |
| 198 | + migrate_orphaned_supervisor >/dev/null 2>&1 |
| 199 | + |
| 200 | + new_crontab=$(crontab -l 2>/dev/null) || new_crontab="" |
| 201 | + |
| 202 | + if echo "$new_crontab" | grep -qF "supervisor-helper.sh"; then |
| 203 | + fail "Cron entry referencing supervisor-helper.sh should have been removed" |
| 204 | + else |
| 205 | + pass "Cron entry referencing supervisor-helper.sh removed" |
| 206 | + fi |
| 207 | + |
| 208 | + if echo "$new_crontab" | grep -qF "keep-this"; then |
| 209 | + pass "Non-supervisor cron entries preserved" |
| 210 | + else |
| 211 | + fail "Non-supervisor cron entries should have been preserved" |
| 212 | + fi |
| 213 | + |
| 214 | + # Restore original crontab |
| 215 | + if [[ -n "$original_crontab" ]]; then |
| 216 | + printf '%s\n' "$original_crontab" | crontab - 2>/dev/null || true |
| 217 | + else |
| 218 | + crontab -r 2>/dev/null || true |
| 219 | + fi |
| 220 | +else |
| 221 | + pass "Cron test skipped (crontab not available)" |
| 222 | +fi |
| 223 | + |
| 224 | +# ============================================================================ |
| 225 | +# Summary |
| 226 | +# ============================================================================ |
| 227 | +echo "" |
| 228 | +echo "================================" |
| 229 | +echo "Results: $PASS_COUNT passed, $FAIL_COUNT failed, $TOTAL_COUNT total" |
| 230 | +echo "================================" |
| 231 | + |
| 232 | +if [[ $FAIL_COUNT -gt 0 ]]; then |
| 233 | + exit 1 |
| 234 | +fi |
| 235 | +exit 0 |
0 commit comments