|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# run-worker-cwd.sh — SI-9 unit tests for claude-worker.sh's |
| 4 | +# resolve_worker_cwd precedence helper. |
| 5 | +# |
| 6 | +# Sources claude-worker.sh with CLAUDE_WORKER_SOURCE_ONLY=1 in a subshell |
| 7 | +# so the function is defined without firing the main loop, then exercises |
| 8 | +# four scenarios: |
| 9 | +# |
| 10 | +# 1. CODEX_FLEET_WORKER_CWD set + writable → echoes that path. |
| 11 | +# 2. CODEX_FLEET_WORKER_CWD unset, active-plan-meta.json points at a |
| 12 | +# writable dir → echoes that dir. |
| 13 | +# 3. Both unset → echoes $REPO. |
| 14 | +# 4. CODEX_FLEET_WORKER_CWD points at non-existent path → falls |
| 15 | +# through to plan-meta (if usable) or $REPO. |
| 16 | + |
| 17 | +set -euo pipefail |
| 18 | + |
| 19 | +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" |
| 20 | +WORKER_SH="$ROOT/scripts/codex-fleet/claude-worker.sh" |
| 21 | + |
| 22 | +[ -f "$WORKER_SH" ] || { echo "FAIL: missing $WORKER_SH" >&2; exit 1; } |
| 23 | + |
| 24 | +TMP="$(mktemp -d -t si9-worker-cwd-XXXXXX)" |
| 25 | +trap 'rm -rf "$TMP"' EXIT |
| 26 | + |
| 27 | +PASS=0 |
| 28 | +FAIL=0 |
| 29 | + |
| 30 | +fail() { |
| 31 | + printf 'FAIL %s\n' "$1" >&2 |
| 32 | + FAIL=$((FAIL + 1)) |
| 33 | +} |
| 34 | + |
| 35 | +pass() { |
| 36 | + printf 'PASS %s\n' "$1" |
| 37 | + PASS=$((PASS + 1)) |
| 38 | +} |
| 39 | + |
| 40 | +assert_eq() { |
| 41 | + local label="$1" expected="$2" actual="$3" |
| 42 | + if [ "$expected" = "$actual" ]; then |
| 43 | + pass "$label" |
| 44 | + else |
| 45 | + fail "$label (expected='$expected' actual='$actual')" |
| 46 | + fi |
| 47 | +} |
| 48 | + |
| 49 | +# Helper: invoke resolve_worker_cwd in a clean subshell with a forced |
| 50 | +# REPO and a chosen $HOME-like sandbox so each test is isolated. |
| 51 | +# |
| 52 | +# Args: |
| 53 | +# $1 fake REPO root (must exist; we control whether |
| 54 | +# .codex-fleet/active-plan-meta.json sits inside it) |
| 55 | +# env: CODEX_FLEET_WORKER_CWD optional pass-through |
| 56 | +run_resolver() { |
| 57 | + local fake_repo="$1" |
| 58 | + CLAUDE_WORKER_SOURCE_ONLY=1 \ |
| 59 | + CODEX_FLEET_REPO_ROOT="$fake_repo" \ |
| 60 | + CODEX_FLEET_WORKER_CWD="${CODEX_FLEET_WORKER_CWD:-}" \ |
| 61 | + bash -c " |
| 62 | + set -u |
| 63 | + # shellcheck disable=SC1090 |
| 64 | + source '$WORKER_SH' |
| 65 | + resolve_worker_cwd |
| 66 | + " |
| 67 | +} |
| 68 | + |
| 69 | +# Scenario 1: CODEX_FLEET_WORKER_CWD set + writable → echoes it. |
| 70 | +foo="$TMP/foo" |
| 71 | +mkdir -p "$foo" |
| 72 | +fake_repo_1="$TMP/repo1" |
| 73 | +mkdir -p "$fake_repo_1" |
| 74 | +got="$(CODEX_FLEET_WORKER_CWD="$foo" run_resolver "$fake_repo_1")" |
| 75 | +assert_eq "1 env override returns explicit path" "$foo" "$got" |
| 76 | + |
| 77 | +# Scenario 2: env unset, active-plan-meta points at /tmp/bar. |
| 78 | +bar="$TMP/bar" |
| 79 | +mkdir -p "$bar" |
| 80 | +fake_repo_2="$TMP/repo2" |
| 81 | +mkdir -p "$fake_repo_2/.codex-fleet" |
| 82 | +cat >"$fake_repo_2/.codex-fleet/active-plan-meta.json" <<JSON |
| 83 | +{ "metadata": { "writable_roots": ["$bar", "/should/not/use"] } } |
| 84 | +JSON |
| 85 | +unset CODEX_FLEET_WORKER_CWD |
| 86 | +if command -v jq >/dev/null 2>&1; then |
| 87 | + got="$(run_resolver "$fake_repo_2")" |
| 88 | + assert_eq "2 plan-meta writable_roots[0] used" "$bar" "$got" |
| 89 | +else |
| 90 | + printf 'SKIP 2 plan-meta test (jq not on PATH)\n' |
| 91 | +fi |
| 92 | + |
| 93 | +# Scenario 3: both unset → echoes $REPO. |
| 94 | +fake_repo_3="$TMP/repo3" |
| 95 | +mkdir -p "$fake_repo_3" |
| 96 | +unset CODEX_FLEET_WORKER_CWD |
| 97 | +got="$(run_resolver "$fake_repo_3")" |
| 98 | +assert_eq "3 fallback to \$REPO" "$fake_repo_3" "$got" |
| 99 | + |
| 100 | +# Scenario 4: CODEX_FLEET_WORKER_CWD points at non-existent path. |
| 101 | +# With no plan-meta, must fall through to $REPO. Confirms the env path |
| 102 | +# does NOT clobber the resolution when the target is unusable. |
| 103 | +fake_repo_4="$TMP/repo4" |
| 104 | +mkdir -p "$fake_repo_4" |
| 105 | +got="$(CODEX_FLEET_WORKER_CWD="$TMP/does-not-exist" run_resolver "$fake_repo_4")" |
| 106 | +assert_eq "4 non-existent env path falls through to \$REPO" "$fake_repo_4" "$got" |
| 107 | + |
| 108 | +# Scenario 4b: non-existent env path WITH valid plan-meta → plan-meta wins. |
| 109 | +baz="$TMP/baz" |
| 110 | +mkdir -p "$baz" |
| 111 | +fake_repo_4b="$TMP/repo4b" |
| 112 | +mkdir -p "$fake_repo_4b/.codex-fleet" |
| 113 | +cat >"$fake_repo_4b/.codex-fleet/active-plan-meta.json" <<JSON |
| 114 | +{ "metadata": { "writable_roots": ["$baz"] } } |
| 115 | +JSON |
| 116 | +if command -v jq >/dev/null 2>&1; then |
| 117 | + got="$(CODEX_FLEET_WORKER_CWD="$TMP/still-missing" run_resolver "$fake_repo_4b")" |
| 118 | + assert_eq "4b non-existent env path falls through to plan-meta" "$baz" "$got" |
| 119 | +fi |
| 120 | + |
| 121 | +printf '\n%d passed, %d failed\n' "$PASS" "$FAIL" |
| 122 | +[ "$FAIL" -eq 0 ] |
0 commit comments