Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions tests/claude-code/run-skill-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
WITH_TIMEOUT="$SCRIPT_DIR/../support/with-timeout.sh"
cd "$SCRIPT_DIR"

echo "========================================"
Expand Down Expand Up @@ -120,7 +121,7 @@ for test in "${tests[@]}"; do
start_time=$(date +%s)

if [ "$VERBOSE" = true ]; then
if timeout "$TIMEOUT" bash "$test_path"; then
if "$WITH_TIMEOUT" "$TIMEOUT" bash "$test_path"; then
end_time=$(date +%s)
duration=$((end_time - start_time))
echo ""
Expand All @@ -140,7 +141,7 @@ for test in "${tests[@]}"; do
fi
else
# Capture output for non-verbose mode
if output=$(timeout "$TIMEOUT" bash "$test_path" 2>&1); then
if output=$("$WITH_TIMEOUT" "$TIMEOUT" bash "$test_path" 2>&1); then
end_time=$(date +%s)
duration=$((end_time - start_time))
echo " [PASS] (${duration}s)"
Expand Down
5 changes: 4 additions & 1 deletion tests/claude-code/test-helpers.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env bash
# Helper functions for Claude Code skill tests

HELPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WITH_TIMEOUT="$HELPER_DIR/../support/with-timeout.sh"

# Run Claude Code with a prompt and capture output
# Usage: run_claude "prompt text" [timeout_seconds] [allowed_tools]
run_claude() {
Expand All @@ -16,7 +19,7 @@ run_claude() {
fi

# Run Claude in headless mode with timeout
if timeout "$timeout" "${cmd[@]}" > "$output_file" 2>&1; then
if "$WITH_TIMEOUT" "$timeout" "${cmd[@]}" > "$output_file" 2>&1; then
cat "$output_file"
rm -f "$output_file"
return 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
WITH_TIMEOUT="$SCRIPT_DIR/../support/with-timeout.sh"
source "$SCRIPT_DIR/test-helpers.sh"

echo "========================================"
Expand Down Expand Up @@ -164,7 +165,7 @@ PLUGIN_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
# other concurrent claude sessions.
echo "Running Claude (plugin-dir: $PLUGIN_DIR, cwd: $TEST_PROJECT)..."
echo "================================================================================"
cd "$TEST_PROJECT" && timeout 1800 claude -p "$PROMPT" --plugin-dir "$PLUGIN_DIR" --allowed-tools=all --permission-mode bypassPermissions 2>&1 | tee "$OUTPUT_FILE" || {
cd "$TEST_PROJECT" && "$WITH_TIMEOUT" 1800 claude -p "$PROMPT" --plugin-dir "$PLUGIN_DIR" --allowed-tools=all --permission-mode bypassPermissions 2>&1 | tee "$OUTPUT_FILE" || {
echo ""
echo "================================================================================"
echo "EXECUTION FAILED (exit code: $?)"
Expand Down
3 changes: 2 additions & 1 deletion tests/explicit-skill-requests/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Get the superpowers plugin root (two levels up)
PLUGIN_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
WITH_TIMEOUT="$SCRIPT_DIR/../support/with-timeout.sh"

TIMESTAMP=$(date +%s)
OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/explicit-skill-requests/${SKILL_NAME}"
Expand Down Expand Up @@ -68,7 +69,7 @@ echo "Running claude -p with explicit skill request..."
echo "Prompt: $PROMPT"
echo ""

timeout 300 claude -p "$PROMPT" \
"$WITH_TIMEOUT" 300 claude -p "$PROMPT" \
--plugin-dir "$PLUGIN_DIR" \
--dangerously-skip-permissions \
--max-turns "$MAX_TURNS" \
Expand Down
3 changes: 2 additions & 1 deletion tests/opencode/test-priority.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
WITH_TIMEOUT="$SCRIPT_DIR/../support/with-timeout.sh"
OPENCODE_TEST_TIMEOUT_SECONDS="${OPENCODE_TEST_TIMEOUT_SECONDS:-120}"

echo "=== Test: Skill Priority Resolution ==="
Expand Down Expand Up @@ -107,7 +108,7 @@ run_opencode() {
local exit_code

set +e
command_output=$(cd "$dir" && timeout "${OPENCODE_TEST_TIMEOUT_SECONDS}s" opencode run --print-logs --format json "$prompt" 2>&1)
command_output=$(cd "$dir" && "$WITH_TIMEOUT" "${OPENCODE_TEST_TIMEOUT_SECONDS}s" opencode run --print-logs --format json "$prompt" 2>&1)
exit_code=$?
set -e

Expand Down
3 changes: 2 additions & 1 deletion tests/opencode/test-tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
WITH_TIMEOUT="$SCRIPT_DIR/../support/with-timeout.sh"
OPENCODE_TEST_TIMEOUT_SECONDS="${OPENCODE_TEST_TIMEOUT_SECONDS:-120}"

echo "=== Test: Tools Functionality ==="
Expand All @@ -31,7 +32,7 @@ run_opencode() {
local exit_code

set +e
command_output=$(cd "$dir" && timeout "${OPENCODE_TEST_TIMEOUT_SECONDS}s" opencode run --print-logs --format json "$prompt" 2>&1)
command_output=$(cd "$dir" && "$WITH_TIMEOUT" "${OPENCODE_TEST_TIMEOUT_SECONDS}s" opencode run --print-logs --format json "$prompt" 2>&1)
exit_code=$?
set -e

Expand Down
50 changes: 50 additions & 0 deletions tests/support/with-timeout.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail

if [[ $# -lt 2 ]]; then
echo "Usage: $0 SECONDS COMMAND [ARG...]" >&2
exit 2
fi

duration="$1"
shift

if command -v timeout >/dev/null 2>&1; then
exec timeout "$duration" "$@"
fi

if command -v gtimeout >/dev/null 2>&1; then
exec gtimeout "$duration" "$@"
fi

command -v python3 >/dev/null 2>&1 || {
echo "ERROR: timeout/gtimeout not found and python3 is unavailable" >&2
exit 127
}

exec python3 - "$duration" "$@" <<'PY'
import subprocess
import sys

raw_duration = sys.argv[1]
command = sys.argv[2:]

try:
timeout_seconds = float(raw_duration[:-1] if raw_duration.endswith("s") else raw_duration)
except ValueError:
print(f"ERROR: invalid timeout duration: {raw_duration}", file=sys.stderr)
sys.exit(2)

try:
completed = subprocess.run(command, timeout=timeout_seconds)
except subprocess.TimeoutExpired:
print(f"ERROR: command timed out after {raw_duration}", file=sys.stderr)
sys.exit(124)
except FileNotFoundError:
print(f"ERROR: command not found: {command[0]}", file=sys.stderr)
sys.exit(127)

if completed.returncode < 0:
sys.exit(128 + abs(completed.returncode))
sys.exit(completed.returncode)
PY