#!/usr/bin/env bash # test-gc.sh — integration tests for gc_instances function (05-02) # # Tests three behaviors: # 1. Stale instance dir (project root gone) is removed # 2. Valid instance dir (project root exists) is preserved # 3. Empty projects/ dir produces "GC complete: 0 instance(s) removed." # # Usage: bash test-gc.sh set -euo pipefail PASS=0 FAIL=0 pass() { echo "PASS: $1"; (( PASS++ )) || true; } fail() { echo "FAIL: $1"; (( FAIL++ )) || true; } # Verify claudebox.sh exists and contains gc_instances SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CLAUDEBOX_SH="$SCRIPT_DIR/claudebox.sh" if [[ ! -f "$CLAUDEBOX_SH" ]]; then echo "ERROR: claudebox.sh not found at $CLAUDEBOX_SH" >&2 exit 1 fi # Verify gc_instances is present in the source file (canary check) if ! cat "$CLAUDEBOX_SH" | tr '\n' '|' | cat > /dev/null 2>&1; then echo "ERROR: claudebox.sh is not readable" >&2 exit 1 fi found_gc=false while IFS= read -r line; do [[ "$line" == "gc_instances()"* ]] && { found_gc=true; break; } done < "$CLAUDEBOX_SH" if [[ "$found_gc" != true ]]; then echo "ERROR: gc_instances() not found in claudebox.sh" >&2 exit 1 fi # Inline definition of gc_instances for isolated testing. # This mirrors the exact implementation in claudebox.sh. gc_instances() { local removed=0 local projects_dir="$HOME/.claudebox/projects" if [[ ! -d "$projects_dir" ]]; then echo "No projects directory found at $projects_dir" >&2 return fi for dir in "$projects_dir"/*/; do [[ -d "$dir" ]] || continue local root_file="$dir/project-root" [[ -f "$root_file" ]] || continue local root_path root_path=$(< "$root_file") if [[ ! -d "$root_path" ]]; then rm -rf "$dir" echo "Removed: $dir (project root gone: $root_path)" >&2 (( removed++ )) || true fi done echo "GC complete: $removed instance(s) removed." >&2 } # ============================================================ # Test setup: temporary home directory # ============================================================ TMPDIR_TEST=$(mktemp -d) trap 'rm -rf "$TMPDIR_TEST"' EXIT # ============================================================ # Test 1: Stale instance directory is removed # ============================================================ HOME="$TMPDIR_TEST" mkdir -p "$HOME/.claudebox/projects/stale1234567890ab" echo "/nonexistent/path/that/does/not/exist/$$" > "$HOME/.claudebox/projects/stale1234567890ab/project-root" GC_OUTPUT=$(gc_instances 2>&1) if [[ ! -d "$HOME/.claudebox/projects/stale1234567890ab" ]]; then pass "Test 1: stale instance dir removed" else fail "Test 1: stale instance dir NOT removed" fi if [[ "$GC_OUTPUT" == *"Removed:"* ]]; then pass "Test 1: 'Removed:' message printed" else fail "Test 1: 'Removed:' not found in output: $GC_OUTPUT" fi if [[ "$GC_OUTPUT" == *"GC complete: 1 instance(s) removed."* ]]; then pass "Test 1: GC summary shows 1 removed" else fail "Test 1: GC summary wrong: $GC_OUTPUT" fi # ============================================================ # Test 2: Valid instance directory is preserved # ============================================================ mkdir -p "$HOME/.claudebox/projects/valid123456789012" # Point project-root at a path that actually exists (TMPDIR_TEST itself) echo "$TMPDIR_TEST" > "$HOME/.claudebox/projects/valid123456789012/project-root" GC_OUTPUT2=$(gc_instances 2>&1) if [[ -d "$HOME/.claudebox/projects/valid123456789012" ]]; then pass "Test 2: valid instance dir preserved" else fail "Test 2: valid instance dir was removed (should not be)" fi if [[ "$GC_OUTPUT2" == *"GC complete: 0 instance(s) removed."* ]]; then pass "Test 2: GC summary shows 0 removed" else fail "Test 2: GC summary wrong: $GC_OUTPUT2" fi # Clean up for Test 3 rm -rf "$HOME/.claudebox/projects/valid123456789012" # ============================================================ # Test 3: Empty projects/ dir produces "GC complete: 0 instance(s) removed." # ============================================================ # Ensure projects/ dir is empty of instance subdirs for d in "$HOME/.claudebox/projects"/*/; do [[ -d "$d" ]] && rm -rf "$d" done GC_OUTPUT3=$(gc_instances 2>&1) if [[ "$GC_OUTPUT3" == *"GC complete: 0 instance(s) removed."* ]]; then pass "Test 3: empty projects/ produces 0 removed summary" else fail "Test 3: empty projects/ output wrong: $GC_OUTPUT3" fi # Verify exits 0 if gc_instances > /dev/null 2>&1; then pass "Test 3: gc_instances exits 0 on empty projects/" else fail "Test 3: gc_instances returned non-zero on empty projects/" fi # ============================================================ # Results # ============================================================ echo "" echo "Results: $PASS passed, $FAIL failed" if (( FAIL > 0 )); then exit 1 fi exit 0