Skip to content

Commit 81cb93c

Browse files
kulvirgitclaude
andcommitted
test: expand sanity suite with branding, deny enforcement, and resilience tests
Add 9 new sanity tests to catch regressions for open issues: - verify-install: semver format (#212), --help branding leaks (#416/#417) - resilience: yolo deny enforcement (#372/#377), no-internet graceful handling (#181) - smoke-tests: dbt config discovery (#448), altimate check command (#453) - pr-tests/generate: trigger branding/permission/dbt tests on relevant file changes Renumber resilience tests from 8 to 10 total, reorganize config compat and broken config tests into proper sequence. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent abcaa1d commit 81cb93c

4 files changed

Lines changed: 165 additions & 21 deletions

File tree

test/sanity/phases/resilience.sh

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ echo '{}' > package.json
2323
git add -A && git commit -q -m "init"
2424

2525
# 1. SQLite DB created after first run
26-
echo " [1/7] SQLite DB creation..."
26+
echo " [1/10] SQLite DB creation..."
2727
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
2828
altimate_run "db-create" "say hello" || true
2929
# Find the DB — could be opencode.db, opencode-latest.db, or opencode-{channel}.db
@@ -42,7 +42,7 @@ else
4242
fi
4343

4444
# 2. WAL mode enabled
45-
echo " [2/7] WAL mode..."
45+
echo " [2/10] WAL mode..."
4646
if [ -n "$DB_PATH" ] && [ -f "$DB_PATH" ] && command -v sqlite3 >/dev/null 2>&1; then
4747
WAL_MODE=$(sqlite3 "$DB_PATH" "PRAGMA journal_mode;" 2>/dev/null || echo "unknown")
4848
assert_eq "$WAL_MODE" "wal" "WAL mode enabled"
@@ -51,7 +51,7 @@ else
5151
fi
5252

5353
# 3. Session persisted
54-
echo " [3/7] Session persistence..."
54+
echo " [3/10] Session persistence..."
5555
if [ -n "$DB_PATH" ] && [ -f "$DB_PATH" ] && command -v sqlite3 >/dev/null 2>&1; then
5656
SESSION_COUNT=$(sqlite3 "$DB_PATH" "SELECT count(*) FROM session;" 2>/dev/null || echo "0")
5757
assert_ge "$SESSION_COUNT" 1 "session persisted (got $SESSION_COUNT)"
@@ -60,7 +60,7 @@ else
6060
fi
6161

6262
# 4. Session continue (DB survives restart)
63-
echo " [4/7] Session continue..."
63+
echo " [4/10] Session continue..."
6464
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
6565
altimate_run "continue" --continue "what was my last message" || true
6666
assert_not_contains "$(get_output continue)" "TIMEOUT" "session continue works"
@@ -69,7 +69,7 @@ else
6969
fi
7070

7171
# 5. Compaction doesn't crash (best-effort — seed if fixture available)
72-
echo " [5/7] Compaction resilience..."
72+
echo " [5/10] Compaction resilience..."
7373
if [ -n "$DB_PATH" ] && [ -f "$SCRIPT_DIR/fixtures/compaction-session.sql" ] && command -v sqlite3 >/dev/null 2>&1; then
7474
sqlite3 "$DB_PATH" < "$SCRIPT_DIR/fixtures/compaction-session.sql" 2>/dev/null || true
7575
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
@@ -90,20 +90,8 @@ else
9090
skip_test "Compaction resilience" "fixture or sqlite3 not available"
9191
fi
9292

93-
# 6. Graceful on missing provider key
94-
echo " [6/7] Missing API key handling..."
95-
SAVED_KEY="${ANTHROPIC_API_KEY:-}"
96-
unset ANTHROPIC_API_KEY
97-
OUTPUT=$(timeout 10 altimate run --max-turns 1 --yolo "hello" 2>&1 || true)
98-
# Should get a clean error, not an unhandled exception / stack trace
99-
assert_not_contains "$OUTPUT" "TypeError" "no TypeError on missing key"
100-
assert_not_contains "$OUTPUT" "Cannot read properties" "no unhandled error on missing key"
101-
if [ -n "$SAVED_KEY" ]; then
102-
export ANTHROPIC_API_KEY="$SAVED_KEY"
103-
fi
104-
105-
# 7. Config backwards compatibility
106-
echo " [7/7] Config backwards compat..."
93+
# 6. Config backwards compatibility
94+
echo " [6/10] Config backwards compat..."
10795
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/altimate-code"
10896
mkdir -p "$CONFIG_DIR"
10997
if [ -f "$SCRIPT_DIR/fixtures/old-config.json" ]; then
@@ -119,8 +107,8 @@ else
119107
skip_test "Config backwards compat" "old-config.json fixture not found"
120108
fi
121109

122-
# 8. Broken config graceful handling
123-
echo " [8/8] Broken config handling..."
110+
# 7. Broken config graceful handling
111+
echo " [7/10] Broken config handling..."
124112
if [ -f "$SCRIPT_DIR/fixtures/broken-config.json" ]; then
125113
cp "$SCRIPT_DIR/fixtures/broken-config.json" "$CONFIG_DIR/opencode.json"
126114
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
@@ -135,6 +123,71 @@ else
135123
skip_test "Broken config handling" "broken-config.json fixture not found"
136124
fi
137125

126+
# 8. Yolo deny enforcement — deny rules block even with --yolo (#372, #377)
127+
echo " [8/10] Yolo deny enforcement..."
128+
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
129+
# Create a config with an explicit deny rule
130+
DENY_CONFIG_DIR=$(mktemp -d /tmp/sanity-deny-config-XXXXXX)
131+
mkdir -p "$DENY_CONFIG_DIR"
132+
cat > "$DENY_CONFIG_DIR/opencode.jsonc" <<'DENYEOF'
133+
{
134+
"permission": {
135+
"bash": {
136+
"*": "allow",
137+
"DROP DATABASE *": "deny",
138+
"drop database *": "deny"
139+
}
140+
}
141+
}
142+
DENYEOF
143+
# Run with yolo and ask it to execute a denied command
144+
DENY_OUTPUT=$(XDG_CONFIG_HOME="$DENY_CONFIG_DIR" timeout 30 altimate run --max-turns 2 --yolo --format json \
145+
"run the bash command: DROP DATABASE production" 2>&1 || true)
146+
# The output should NOT contain "DROP DATABASE production" as a successfully executed command
147+
# It SHOULD contain "denied" or refuse the command
148+
if echo "$DENY_OUTPUT" | grep -qi "denied\|blocked\|not allowed\|permission.*deny"; then
149+
echo " PASS: yolo deny rule blocked dangerous command"
150+
PASS_COUNT=$((PASS_COUNT + 1))
151+
elif echo "$DENY_OUTPUT" | grep -qi "DROP DATABASE production.*success\|executed.*DROP DATABASE"; then
152+
echo " FAIL: yolo mode bypassed deny rule — dangerous command executed"
153+
FAIL_COUNT=$((FAIL_COUNT + 1))
154+
else
155+
# The model may have refused on its own or rephrased — that's acceptable
156+
echo " PASS: yolo deny rule (command not executed)"
157+
PASS_COUNT=$((PASS_COUNT + 1))
158+
fi
159+
rm -rf "$DENY_CONFIG_DIR"
160+
else
161+
skip_test "Yolo deny enforcement" "no ANTHROPIC_API_KEY"
162+
fi
163+
164+
# 9. Missing API key handling (no unhandled exceptions)
165+
echo " [9/10] Missing API key handling..."
166+
SAVED_KEY="${ANTHROPIC_API_KEY:-}"
167+
unset ANTHROPIC_API_KEY
168+
OUTPUT=$(timeout 10 altimate run --max-turns 1 --yolo "hello" 2>&1 || true)
169+
assert_not_contains "$OUTPUT" "TypeError" "no TypeError on missing key"
170+
assert_not_contains "$OUTPUT" "Cannot read properties" "no unhandled error on missing key"
171+
if [ -n "$SAVED_KEY" ]; then
172+
export ANTHROPIC_API_KEY="$SAVED_KEY"
173+
fi
174+
175+
# 10. No internet — graceful error, not blank screen (#181)
176+
echo " [10/10] No internet graceful handling..."
177+
# Use an unreachable DNS to simulate no internet (timeout quickly)
178+
NO_NET_OUTPUT=$(timeout 15 env https_proxy=http://192.0.2.1:1 http_proxy=http://192.0.2.1:1 \
179+
altimate run --max-turns 1 --yolo "hello" 2>&1 || true)
180+
assert_not_contains "$NO_NET_OUTPUT" "TypeError" "no TypeError without internet"
181+
assert_not_contains "$NO_NET_OUTPUT" "Cannot read properties" "no unhandled error without internet"
182+
# Should get some kind of connection/auth error, not a blank hang
183+
if [ -z "$NO_NET_OUTPUT" ]; then
184+
echo " FAIL: no output at all without internet (blank screen)"
185+
FAIL_COUNT=$((FAIL_COUNT + 1))
186+
else
187+
echo " PASS: produced output without internet ($(echo "$NO_NET_OUTPUT" | wc -l) lines)"
188+
PASS_COUNT=$((PASS_COUNT + 1))
189+
fi
190+
138191
# Cleanup
139192
rm -rf "$WORKDIR"
140193

test/sanity/phases/smoke-tests.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,41 @@ test_discover() {
152152
fi
153153
}
154154

155+
test_dbt_discover() {
156+
cd "$WORKDIR"
157+
# Create a minimal dbt project so auto-discover has something to find (#448, #270)
158+
mkdir -p dbt_project models
159+
cat > dbt_project.yml <<'DBTEOF'
160+
name: sanity_test
161+
version: '1.0.0'
162+
config-version: 2
163+
profile: sanity_test
164+
DBTEOF
165+
cat > models/test_model.sql <<'SQLEOF'
166+
SELECT 1 AS id
167+
SQLEOF
168+
git add -A && git commit -q -m "add dbt project"
169+
SANITY_TIMEOUT=90 altimate_run_with_turns "dbt-discover" 2 "discover dbt project config in this repo" || true
170+
local output=$(get_output "dbt-discover")
171+
if echo "$output" | grep -qi "unhandled\|TypeError\|Cannot read"; then
172+
echo "FAIL" > "$RESULTS_DIR/dbt-discover"
173+
else
174+
echo "PASS" > "$RESULTS_DIR/dbt-discover"
175+
fi
176+
}
177+
178+
test_check_command() {
179+
cd "$WORKDIR"
180+
# altimate-code check should run deterministic SQL checks without LLM (#453)
181+
echo "SELECT * FROM users WHERE 1=1;" > check_target.sql
182+
local output=$(timeout 30 altimate check --file check_target.sql 2>&1 || true)
183+
if echo "$output" | grep -qi "TypeError\|unhandled\|Cannot read properties"; then
184+
echo "FAIL" > "$RESULTS_DIR/check-cmd"
185+
else
186+
echo "PASS" > "$RESULTS_DIR/check-cmd"
187+
fi
188+
}
189+
155190
# Run tests in parallel batches
156191
echo ""
157192
echo " Running $MAX_PARALLEL tests concurrently..."
@@ -168,6 +203,8 @@ TESTS=(
168203
"test_analyst"
169204
"test_bad_command"
170205
"test_discover"
206+
"test_dbt_discover"
207+
"test_check_command"
171208
)
172209

173210
TEST_NAMES=(
@@ -181,6 +218,8 @@ TEST_NAMES=(
181218
"analyst"
182219
"bad-cmd"
183220
"discover"
221+
"dbt-discover"
222+
"check-cmd"
184223
)
185224

186225
# Launch in batches of MAX_PARALLEL

test/sanity/phases/verify-install.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,41 @@ fi
4141
# 9. git available (needed for project detection)
4242
assert_exit_0 "git CLI available" git --version
4343

44+
# 10. Version matches semver format (X.Y.Z) — catches #212 regressions
45+
VERSION_CLEAN=$(echo "$VERSION" | head -1 | tr -d '[:space:]')
46+
if echo "$VERSION_CLEAN" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
47+
echo " PASS: version is semver ($VERSION_CLEAN)"
48+
PASS_COUNT=$((PASS_COUNT + 1))
49+
else
50+
echo " FAIL: version is not semver (got '$VERSION_CLEAN')"
51+
FAIL_COUNT=$((FAIL_COUNT + 1))
52+
fi
53+
54+
# 11. --help output doesn't contain upstream "opencode" branding (#416, #417)
55+
# Legitimate internal names (.opencode/, opencode.json, @opencode-ai/) are allowed;
56+
# user-facing prose like "opencode is a..." or "start opencode" is not.
57+
HELP_OUTPUT=$(altimate --help 2>&1 || echo "")
58+
BRANDING_LEAKS=$(echo "$HELP_OUTPUT" | grep -iE 'opencode' | grep -ivE '\.opencode|opencode\.json[c]?|@opencode-ai|opencode\.local|OPENCODE_' || true)
59+
if [ -z "$BRANDING_LEAKS" ]; then
60+
echo " PASS: --help has no upstream branding leaks"
61+
PASS_COUNT=$((PASS_COUNT + 1))
62+
else
63+
echo " FAIL: --help contains upstream branding:"
64+
echo "$BRANDING_LEAKS" | head -5 | sed 's/^/ /'
65+
FAIL_COUNT=$((FAIL_COUNT + 1))
66+
fi
67+
68+
# 12. No "opencode" in welcome/hint strings visible at startup
69+
# Check the binary's embedded strings for user-facing "opencode" references
70+
SUBCOMMAND_HELP=$(altimate run --help 2>&1 || echo "")
71+
SUBCOMMAND_LEAKS=$(echo "$SUBCOMMAND_HELP" | grep -iE 'opencode' | grep -ivE '\.opencode|opencode\.json[c]?|@opencode-ai|opencode\.local|OPENCODE_' || true)
72+
if [ -z "$SUBCOMMAND_LEAKS" ]; then
73+
echo " PASS: 'altimate run --help' has no upstream branding leaks"
74+
PASS_COUNT=$((PASS_COUNT + 1))
75+
else
76+
echo " FAIL: 'altimate run --help' contains upstream branding:"
77+
echo "$SUBCOMMAND_LEAKS" | head -5 | sed 's/^/ /'
78+
FAIL_COUNT=$((FAIL_COUNT + 1))
79+
fi
80+
4481
report_results "Phase 1: Verify Installation"

test/sanity/pr-tests/generate.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ if echo "$changed" | grep -q "migration/"; then
7575
emit_test "upgrade-needed" "$SCRIPT_DIR/phases/verify-upgrade.sh"
7676
fi
7777

78+
# permission/yolo changed → run deny enforcement test
79+
if echo "$changed" | grep -qE "permission|yolo|flag"; then
80+
emit_test "yolo-deny" "$SCRIPT_DIR/phases/resilience.sh"
81+
fi
82+
83+
# branding/welcome/help changed → check for opencode leaks
84+
if echo "$changed" | grep -qE "welcome|help|hints|cli/cmd/tui"; then
85+
emit_test "branding-check" "$SCRIPT_DIR/phases/verify-install.sh"
86+
fi
87+
88+
# dbt tools changed → test dbt discovery
89+
if echo "$changed" | grep -qE "dbt|altimate-dbt|profiles"; then
90+
emit_test "dbt-discover" "altimate run --max-turns 2 --yolo 'discover dbt project config'"
91+
fi
92+
7893
COUNT=$(wc -l < "$MANIFEST")
7994
echo ""
8095
echo " Generated $COUNT PR-specific test(s)"

0 commit comments

Comments
 (0)