Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
launch.sh dashboard.sh harvest.sh \
costs.sh progress.sh \
lib/*.sh lib/drivers/*.sh \
tests/test_*.sh tests/test.sh
tests/*.sh

unit-tests:
strategy:
Expand Down
7 changes: 7 additions & 0 deletions tests/_test_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# Keep test behavior independent of host Git settings.
export GIT_CONFIG_GLOBAL=/dev/null
export GIT_CONFIG_SYSTEM=/dev/null
export GIT_CONFIG_COUNT=0
unset GIT_CONFIG GIT_CONFIG_PARAMETERS
3 changes: 3 additions & 0 deletions tests/manual_interactive_e2e.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Manual interactive E2E fixture generator.
#
# This is intentionally not named test_*.sh, so tests/test.sh --unit
Expand Down
25 changes: 21 additions & 4 deletions tests/runtime_signal_trap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034
set -uo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# tests/runtime_signal_trap.sh
#
# Drive the harness's emergency-push paths under real Docker.
Expand Down Expand Up @@ -180,6 +183,22 @@ wait_for_session() {
return 1
}

wait_for_test_commit() {
local name="$1" tag="$2" timeout="${3:-30}"
local i subject
for i in $(seq 1 "$timeout"); do
subject=$(docker exec "$name" \
git -C /workspace log -1 --format='%s' 2>/dev/null || true)
if [ "$subject" = "test commit [${tag}]" ]; then
return 0
fi
sleep 1
done
echo " timed out waiting for test commit [${tag}] in ${name}"
docker logs "$name" 2>&1 | tail -15 | sed 's/^/ /'
return 1
}

await_exit() {
local name="$1" timeout="${2:-90}"
local i status
Expand All @@ -205,8 +224,7 @@ count_landed() {
echo
echo "=== Item 3: SIGTERM mid-session ==="
start_container "${NAMES[0]}" -e TC_TAG=sigterm-tag
wait_for_session "${NAMES[0]}" || exit 1
sleep 2
wait_for_test_commit "${NAMES[0]}" sigterm-tag || exit 1
echo " sending docker stop -t 60..."
docker stop -t 60 "${NAMES[0]}" >/dev/null
EXIT_3=$(await_exit "${NAMES[0]}")
Expand All @@ -221,8 +239,7 @@ echo

echo "=== Item 4: SIGINT mid-session ==="
start_container "${NAMES[1]}" -e TC_TAG=sigint-tag
wait_for_session "${NAMES[1]}" || exit 1
sleep 2
wait_for_test_commit "${NAMES[1]}" sigint-tag || exit 1
echo " sending docker kill --signal=SIGINT..."
docker kill --signal=SIGINT "${NAMES[1]}" >/dev/null
EXIT_4=$(await_exit "${NAMES[1]}")
Expand Down
3 changes: 3 additions & 0 deletions tests/test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Smoke test: launch agents with a counting prompt, verify results.
# Each agent N writes test-results/agent-N.txt with N*100..N*100+99.
#
Expand Down
3 changes: 3 additions & 0 deletions tests/test_activity_filter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for lib/activity-filter.sh.
# No Docker or API key required.

Expand Down
24 changes: 23 additions & 1 deletion tests/test_ci_workflows.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for GitHub Actions workflow shape.

PASS=0
FAIL=0
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TESTS_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$TESTS_DIR/.." && pwd)"
CI_YML="$REPO_ROOT/.github/workflows/ci.yml"
INTEGRATION_YML="$REPO_ROOT/.github/workflows/integration.yml"

assert_eq() {
Expand All @@ -32,6 +37,23 @@ assert_eq "workflow has no full-matrix job" "0" \
assert_eq "workflow does not run --all" "0" \
"$(grep -cF './tests/test.sh --all' "$INTEGRATION_YML" || true)"

echo ""
echo "=== 2. Shared test environment ==="

missing_env=""
for test_file in "$TESTS_DIR"/*.sh; do
[ "$test_file" = "$TESTS_DIR/_test_env.sh" ] && continue
if ! grep -qF \
'source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"' \
"$test_file"; then
missing_env="${missing_env} $(basename "$test_file")"
fi
done

assert_eq "all test scripts source the shared environment" "" "$missing_env"
assert_eq "CI checks every test script" "1" \
"$(grep -cF 'tests/*.sh' "$CI_YML")"

echo ""
echo "==============================="
echo " ${PASS} passed, ${FAIL} failed"
Expand Down
3 changes: 3 additions & 0 deletions tests/test_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for swarm.json config parsing.
# No Docker or API key required -- validates jq expressions only.

Expand Down
3 changes: 3 additions & 0 deletions tests/test_costs.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for costs.sh aggregation and formatting logic.
# No Docker or API key required.

Expand Down
3 changes: 3 additions & 0 deletions tests/test_dashboard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034,SC2016
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for dashboard.sh helper functions:
# format_model, truncate_str, and column layout (with optional Tag).
# No Docker or API key required.
Expand Down
3 changes: 3 additions & 0 deletions tests/test_drivers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for the driver role interface.
# No Docker or API key required.

Expand Down
3 changes: 3 additions & 0 deletions tests/test_format.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for formatting functions used by dashboard.sh and costs.sh.
# No Docker or API key required.

Expand Down
48 changes: 34 additions & 14 deletions tests/test_harness.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# shellcheck disable=SC2034
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for harness.sh stat extraction and logic.
# No Docker or API key required.

Expand Down Expand Up @@ -404,11 +407,16 @@ hlog_pipe() {
}

AGENT_ID=3
OUT=$(hlog "test message")
OUT=$(
date() {
printf '%s\n' "12:34:56"
}
hlog "test message"
)
PLAIN=$(echo "$OUT" | strip_ansi)

assert_contains "hlog timestamp" \
"$(date +%H:%M:%S)" "$PLAIN"
"12:34:56 harness[3] test message" "$PLAIN"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, was that adding to the flakiness?

@radubahmata radubahmata Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, if it gets to the next second between the two date invocations. previously it compared the real-time string to one extracted a few milliseconds before.

assert_contains "hlog prefix" "harness[3]" "$PLAIN"
assert_contains "hlog body" "test message" "$PLAIN"

Expand Down Expand Up @@ -644,6 +652,12 @@ source "$TESTS_DIR/../lib/signing.sh"
# Exercises configure_git_signing from lib/signing.sh against
# a sandboxed $HOME so --global writes land in a scratch dir
# instead of the tester's real ~/.gitconfig.
with_sandboxed_git_config() {
local sandbox="$1"
shift
HOME="$sandbox" GIT_CONFIG_GLOBAL="$sandbox/.gitconfig" "$@"
}

run_signing_config() {
local create_key="$1"
local sandbox="$TMPDIR/sign-sandbox-$$-${RANDOM}"
Expand All @@ -655,12 +669,14 @@ run_signing_config() {
touch "$key_path"
fi

HOME="$sandbox" configure_git_signing "$key_path" "$dst_path"
with_sandboxed_git_config "$sandbox" \
configure_git_signing "$key_path" "$dst_path"

local format gpgsign
format=$(HOME="$sandbox" git config --global --get gpg.format \
2>/dev/null || echo "none")
gpgsign=$(HOME="$sandbox" git config --global --get commit.gpgsign)
format=$(with_sandboxed_git_config "$sandbox" \
git config --global --get gpg.format 2>/dev/null || echo "none")
gpgsign=$(with_sandboxed_git_config "$sandbox" \
git config --global --get commit.gpgsign)
echo "${format}|${gpgsign}"
rm -rf "$sandbox"
}
Expand All @@ -683,7 +699,8 @@ copy_src="$copy_sandbox/src_key"
copy_dst="$copy_sandbox/dst_key"
echo "fake-key-bytes" > "$copy_src"
chmod 644 "$copy_src"
HOME="$copy_sandbox" configure_git_signing "$copy_src" "$copy_dst"
with_sandboxed_git_config "$copy_sandbox" \
configure_git_signing "$copy_src" "$copy_dst"
assert_eq "key copied to scratch location" \
"yes" \
"$([ -f "$copy_dst" ] && echo yes || echo no)"
Expand All @@ -693,7 +710,8 @@ assert_eq "key copy has 0600 perms" \
|| stat -f '%Lp' "$copy_dst" 2>/dev/null)"
assert_eq "user.signingkey points at copy" \
"$copy_dst" \
"$(HOME="$copy_sandbox" git config --global --get user.signingkey)"
"$(with_sandboxed_git_config "$copy_sandbox" \
git config --global --get user.signingkey)"
assert_eq "no swarm key written under \$HOME" \
"no" \
"$([ -e "$copy_sandbox/.ssh/swarm-signing-key" ] && echo yes || echo no)"
Expand All @@ -709,26 +727,28 @@ fail_src="$fail_sandbox/src_key"
fail_dst="$fail_sandbox/no/such/dir/dst_key"
touch "$fail_src"
fail_rc=0
HOME="$fail_sandbox" configure_git_signing "$fail_src" "$fail_dst" \
>/dev/null 2>&1 || fail_rc=$?
with_sandboxed_git_config "$fail_sandbox" \
configure_git_signing "$fail_src" "$fail_dst" \
>/dev/null 2>&1 || fail_rc=$?
assert_eq "install failure -> non-zero return" \
"1" \
"$fail_rc"
assert_eq "install failure -> user.signingkey not set" \
"" \
"$(HOME="$fail_sandbox" git config --global --get user.signingkey \
2>/dev/null)"
"$(with_sandboxed_git_config "$fail_sandbox" \
git config --global --get user.signingkey 2>/dev/null)"
rm -rf "$fail_sandbox"

# Defaults to /etc/swarm/signing_key when called with no arg;
# verify by pointing HOME at a sandbox where that path doesn't
# exist and expecting the "absent" branch.
default_path_sandbox="$TMPDIR/sign-default-$$-${RANDOM}"
mkdir -p "$default_path_sandbox"
HOME="$default_path_sandbox" configure_git_signing
with_sandboxed_git_config "$default_path_sandbox" configure_git_signing
assert_eq "default key path absent -> gpgsign false" \
"false" \
"$(HOME="$default_path_sandbox" git config --global --get commit.gpgsign)"
"$(with_sandboxed_git_config "$default_path_sandbox" \
git config --global --get commit.gpgsign)"
rm -rf "$default_path_sandbox"

# ============================================================
Expand Down
3 changes: 3 additions & 0 deletions tests/test_harvest.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for harvest.sh logic.
# Uses local git repos (no Docker or API key required).

Expand Down
9 changes: 3 additions & 6 deletions tests/test_launch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
# shellcheck disable=SC2034
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for launch.sh parsing logic.
# No Docker or API key required.

# Isolate from host gitconfig (signing keys, hooks, templates).
# Several tests build scratch repos and run `git commit` /
# `commit-tree`;
export GIT_CONFIG_GLOBAL=/dev/null
export GIT_CONFIG_SYSTEM=/dev/null

PASS=0
FAIL=0
TMPDIR=$(mktemp -d)
Expand Down
3 changes: 3 additions & 0 deletions tests/test_locale.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Guard against the regression reported in the bug:
# dashboard.sh: line 207: printf: 52.185737173...: invalid number
# on systems using `,` as the decimal separator. Pin the
Expand Down
3 changes: 3 additions & 0 deletions tests/test_manual_interactive_e2e.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Unit tests for the manual interactive E2E fixture generator.

PASS=0
Expand Down
8 changes: 3 additions & 5 deletions tests/test_session_end_push.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euo pipefail

# shellcheck source=_test_env.sh
source "$(dirname "${BASH_SOURCE[0]}")/_test_env.sh"

# Guard against the regression reported in issue #82:
# session-end `git pull --rebase && git push` at
# lib/harness.sh fails every retry when the target repo
Expand All @@ -11,11 +14,6 @@ set -euo pipefail
# the hook-suppression mechanism end-to-end, and pin the
# park-push retry loop both structurally and behaviorally.

# Isolate from host gitconfig (signing keys, hooks, templates).
# This test exercises rebase/push mechanics, not signing.
export GIT_CONFIG_GLOBAL=/dev/null
export GIT_CONFIG_SYSTEM=/dev/null

PASS=0
FAIL=0
TMPDIR=$(mktemp -d)
Expand Down
Loading