Skip to content

Commit 466d3fd

Browse files
Merge pull request #1119 from corbitsdev/refactor/tests-infra-dedup
refactor(tests): consolidate duplicated test/infra helpers
2 parents 13912db + a4b46f0 commit 466d3fd

24 files changed

Lines changed: 850 additions & 837 deletions

‎evals/capability/cases/tier-easy/verify.sh‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/usr/bin/env bash
22
# easy tier: floor tripwire. Saturation here is intentional -- this exists to
33
# catch gross breakage of the product path, not to discriminate between models.
4-
set -euo pipefail
4+
# shellcheck source=../verify-common.sh
5+
source "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh"
56

67
[[ -f package.json ]] || { echo "FAIL: package.json missing in workdir"; exit 1; }
78

@@ -28,7 +29,7 @@ if (health?.status !== 200 || health.body?.ok !== true) {
2829
console.log("ok: routes verified");
2930
'
3031

31-
bun test >/tmp/tier-easy-test.log 2>&1 || { cat /tmp/tier-easy-test.log; echo "FAIL: bun test failed"; exit 1; }
32+
run_visible_suite "/tmp/tier-easy-test.log" "FAIL: bun test failed"
3233
# A test must actually exercise the route, not merely mention the word.
3334
found=0
3435
for f in tests/*.ts; do

‎evals/capability/cases/tier-hard/verify.sh‎

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,14 @@
44
# collapsing "us-east"/"us-west" to "us". Guarding the crash site (`bucket?.total
55
# ?? 0`) makes the visible suite green while silently reporting zeros -- the
66
# held-out assertions below are what catch that.
7-
set -euo pipefail
7+
# shellcheck source=../verify-common.sh
8+
source "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh"
89

910
TEST_SHA="a7ce0705273ad6b874b737d389db038745e5baec825fd757f42448cd1addb687"
1011

11-
[[ -f package.json ]] || { echo "FAIL: package.json missing in workdir"; exit 1; }
12-
[[ -f tests/report.test.ts ]] || { echo "FAIL: tests/report.test.ts is gone"; exit 1; }
13-
14-
actual_sha=$(shasum -a 256 tests/report.test.ts | cut -d' ' -f1)
15-
if [[ "$actual_sha" != "$TEST_SHA" ]]; then
16-
# A stale TEST_SHA is indistinguishable from an agent edit above, so check
17-
# the fixture's own hash at setup before blaming the agent: the workdir is
18-
# a git repo committed before the run, so HEAD holds the pristine file.
19-
setup_sha=$(git show "HEAD:tests/report.test.ts" 2>/dev/null | shasum -a 256 | cut -d' ' -f1 || true)
20-
if [[ -n "$setup_sha" && "$actual_sha" == "$setup_sha" ]]; then
21-
echo "FAIL: tests/report.test.ts is unchanged from the fixture at setup ($setup_sha) but does not match TEST_SHA ($TEST_SHA): the case's locked hash is stale (broken case), not an agent edit"
22-
exit 1
23-
fi
24-
echo "FAIL: tests/report.test.ts was modified (contract file must be byte-unchanged)"
25-
exit 1
26-
fi
12+
check_contract "tests/report.test.ts"
2713

28-
if ! bun test >/tmp/tier-hard-test.log 2>&1; then
29-
cat /tmp/tier-hard-test.log
30-
echo "FAIL: visible bun test failed"
31-
exit 1
32-
fi
14+
run_visible_suite "/tmp/tier-hard-test.log" "FAIL: visible bun test failed"
3315

3416
# Held-out assertions the agent never sees: the actual values must be right.
3517
bun -e '

‎evals/capability/cases/tier-med/verify.sh‎

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,14 @@
44
# src/legacy/pricing.ts already holds 175. Only fixing the imported source
55
# (src/config/pricing.ts) counts. Rewiring the import to legacy, hardcoding a
66
# total, or editing the test all reach green and all fail here.
7-
set -euo pipefail
7+
# shellcheck source=../verify-common.sh
8+
source "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh"
89

910
TEST_SHA="4b48fc362c6c3a72af405545ffa816f4a531bbed974d87b6f4d60cf5c96f06a0"
1011

11-
[[ -f package.json ]] || { echo "FAIL: package.json missing in workdir"; exit 1; }
12-
[[ -f tests/checkout.test.ts ]] || { echo "FAIL: tests/checkout.test.ts is gone"; exit 1; }
12+
check_contract "tests/checkout.test.ts"
1313

14-
actual_sha=$(shasum -a 256 tests/checkout.test.ts | cut -d' ' -f1)
15-
if [[ "$actual_sha" != "$TEST_SHA" ]]; then
16-
# A stale TEST_SHA is indistinguishable from an agent edit above, so check
17-
# the fixture's own hash at setup before blaming the agent: the workdir is
18-
# a git repo committed before the run, so HEAD holds the pristine file.
19-
setup_sha=$(git show "HEAD:tests/checkout.test.ts" 2>/dev/null | shasum -a 256 | cut -d' ' -f1 || true)
20-
if [[ -n "$setup_sha" && "$actual_sha" == "$setup_sha" ]]; then
21-
echo "FAIL: tests/checkout.test.ts is unchanged from the fixture at setup ($setup_sha) but does not match TEST_SHA ($TEST_SHA): the case's locked hash is stale (broken case), not an agent edit"
22-
exit 1
23-
fi
24-
echo "FAIL: tests/checkout.test.ts was modified (contract file must be byte-unchanged)"
25-
exit 1
26-
fi
27-
28-
if ! bun test >/tmp/tier-med-test.log 2>&1; then
29-
cat /tmp/tier-med-test.log
30-
echo "FAIL: bun test failed"
31-
exit 1
32-
fi
14+
run_visible_suite "/tmp/tier-med-test.log" "FAIL: bun test failed"
3315

3416
# The authoritative source must carry the corrected value.
3517
if ! grep -qE "FEE_BPS[[:space:]]*=[[:space:]]*175" src/config/pricing.ts; then

‎evals/capability/cases/tier-xhard/verify.sh‎

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,14 @@
33
# grades production shape, which functional tests cannot see -- the Encore
44
# "green != ready" lesson (CL-6930). Target pass rate 0-25%: an agent that stops
55
# at green fails every check below.
6-
set -euo pipefail
6+
# shellcheck source=../verify-common.sh
7+
source "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh"
78

89
TEST_SHA="bd97182202b283a721f2972f1fba79e2b552a95a64f1639d077022aa95a157d5"
910

10-
[[ -f package.json ]] || { echo "FAIL: package.json missing in workdir"; exit 1; }
11-
[[ -f tests/notify.test.ts ]] || { echo "FAIL: tests/notify.test.ts is gone"; exit 1; }
11+
check_contract "tests/notify.test.ts"
1212

13-
actual_sha=$(shasum -a 256 tests/notify.test.ts | cut -d' ' -f1)
14-
if [[ "$actual_sha" != "$TEST_SHA" ]]; then
15-
# A stale TEST_SHA is indistinguishable from an agent edit above, so check
16-
# the fixture's own hash at setup before blaming the agent: the workdir is
17-
# a git repo committed before the run, so HEAD holds the pristine file.
18-
setup_sha=$(git show "HEAD:tests/notify.test.ts" 2>/dev/null | shasum -a 256 | cut -d' ' -f1 || true)
19-
if [[ -n "$setup_sha" && "$actual_sha" == "$setup_sha" ]]; then
20-
echo "FAIL: tests/notify.test.ts is unchanged from the fixture at setup ($setup_sha) but does not match TEST_SHA ($TEST_SHA): the case's locked hash is stale (broken case), not an agent edit"
21-
exit 1
22-
fi
23-
echo "FAIL: tests/notify.test.ts was modified (contract file must be byte-unchanged)"
24-
exit 1
25-
fi
26-
27-
if ! bun test >/tmp/tier-xhard-test.log 2>&1; then
28-
cat /tmp/tier-xhard-test.log
29-
echo "FAIL: functional suite regressed"
30-
exit 1
31-
fi
13+
run_visible_suite "/tmp/tier-xhard-test.log" "FAIL: functional suite regressed"
3214

3315
# --- rubric 1: versioned migrations, not inline schema ----------------------
3416
shopt -s nullglob
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# Shared prelude sourced by the tier grader verify.sh scripts. Sets strict
3+
# mode and provides the locked-contract guard plus the visible-suite runner.
4+
# Per-tier assertions stay inline in each verify.sh.
5+
set -euo pipefail
6+
7+
# check_contract <contract-test-path>: fail unless the file exists and is
8+
# byte-identical to $TEST_SHA (set by the caller before calling).
9+
check_contract() {
10+
local contract="$1"
11+
[[ -f package.json ]] || { echo "FAIL: package.json missing in workdir"; exit 1; }
12+
[[ -f "$contract" ]] || { echo "FAIL: $contract is gone"; exit 1; }
13+
14+
local actual_sha setup_sha
15+
actual_sha=$(shasum -a 256 "$contract" | cut -d' ' -f1)
16+
if [[ "$actual_sha" != "$TEST_SHA" ]]; then
17+
# A stale TEST_SHA is indistinguishable from an agent edit above, so check
18+
# the fixture's own hash at setup before blaming the agent: the workdir is
19+
# a git repo committed before the run, so HEAD holds the pristine file.
20+
setup_sha=$(git show "HEAD:$contract" 2>/dev/null | shasum -a 256 | cut -d' ' -f1 || true)
21+
if [[ -n "$setup_sha" && "$actual_sha" == "$setup_sha" ]]; then
22+
echo "FAIL: $contract is unchanged from the fixture at setup ($setup_sha) but does not match TEST_SHA ($TEST_SHA): the case's locked hash is stale (broken case), not an agent edit"
23+
exit 1
24+
fi
25+
echo "FAIL: $contract was modified (contract file must be byte-unchanged)"
26+
exit 1
27+
fi
28+
}
29+
30+
# run_visible_suite <log-file> <fail-message>: fail (after printing the log)
31+
# unless `bun test` passes in the workdir. Callers pass a full `FAIL: ...`
32+
# line; this helper prints it as-is.
33+
run_visible_suite() {
34+
local log="$1"
35+
local fail_message="$2"
36+
if ! bun test >"$log" 2>&1; then
37+
cat "$log"
38+
echo "$fail_message"
39+
exit 1
40+
fi
41+
}

‎evals/capability/locked-fixtures.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ function parseLockedContract(
1313
): { sha: string; path: string } | null {
1414
const sha = verifySrc.match(/^TEST_SHA="([0-9a-f]{64})"$/m)?.[1];
1515
if (sha === undefined) return null;
16+
// Shared-helper shape: check_contract "<path>" (the existence guard and
17+
// the shasum comparison live in cases/verify-common.sh).
18+
const shared = verifySrc.match(/^check_contract "(\S+)"$/m)?.[1];
19+
if (shared !== undefined) return { sha, path: shared };
1620
const hashed = verifySrc.match(/shasum -a 256 (\S+)/)?.[1];
1721
const guarded = [...verifySrc.matchAll(/\[\[ -f (\S+) \]\]/g)].map(
1822
(m) => m[1],

‎scripts/approval-forensics.ts‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,16 @@
1313
//
1414
// Run: bun run scripts/approval-forensics.ts
1515

16-
import { readdirSync, lstatSync, readFileSync } from "node:fs";
16+
import { readFileSync } from "node:fs";
1717
import { join } from "node:path";
1818
import { homedir } from "node:os";
1919

20+
import { findAll } from "./find-all.js";
2021
import {
2122
APPROVAL_LOG_FILE,
2223
type ApprovalRecord,
2324
} from "../src/permission/approval-log.js";
2425

25-
// lstat, and skip symlinks: session dirs carry a `latest` symlink to a real
26-
// session, and following it double-counts every record in that session.
27-
function findAll(dir: string, name: string, out: string[]): void {
28-
let entries: string[];
29-
try {
30-
entries = readdirSync(dir);
31-
} catch {
32-
return;
33-
}
34-
for (const entry of entries) {
35-
const path = join(dir, entry);
36-
let info: ReturnType<typeof lstatSync>;
37-
try {
38-
info = lstatSync(path);
39-
} catch {
40-
continue;
41-
}
42-
if (info.isSymbolicLink()) continue;
43-
if (info.isDirectory()) findAll(path, name, out);
44-
else if (entry === name) out.push(path);
45-
}
46-
}
47-
4826
function percentile(sorted: readonly number[], p: number): number {
4927
if (sorted.length === 0) return 0;
5028
const index = Math.min(

‎scripts/find-all.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { lstatSync, readdirSync } from "node:fs";
2+
import { join } from "node:path";
3+
4+
// Shared directory walk for the forensics scripts: recursively collects the
5+
// paths of every file named `name` under `dir`.
6+
//
7+
// lstat, and skip symlinks: session dirs carry a `latest` symlink to a real
8+
// session, and following it double-counts every record in that session.
9+
export function findAll(dir: string, name: string, out: string[]): void {
10+
let entries: string[];
11+
try {
12+
entries = readdirSync(dir);
13+
} catch {
14+
return;
15+
}
16+
for (const entry of entries) {
17+
const path = join(dir, entry);
18+
let info: ReturnType<typeof lstatSync>;
19+
try {
20+
info = lstatSync(path);
21+
} catch {
22+
continue;
23+
}
24+
if (info.isSymbolicLink()) continue;
25+
if (info.isDirectory()) findAll(path, name, out);
26+
else if (entry === name) out.push(path);
27+
}
28+
}

‎scripts/intervention-forensics.ts‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,38 +29,16 @@
2929
// Prints only aggregate counts and the `detail` field's first token, never turn
3030
// content, so it is safe to run without pulling trace data into a context window.
3131

32-
import { readdirSync, lstatSync, readFileSync } from "node:fs";
32+
import { readFileSync } from "node:fs";
3333
import { join } from "node:path";
3434
import { homedir } from "node:os";
3535

36+
import { findAll } from "./find-all.js";
3637
import {
3738
INTERVENTION_FILE,
3839
type InterventionRecord,
3940
} from "../src/subagent/intervention-log.js";
4041

41-
// lstat, and skip symlinks: session dirs carry a `latest` symlink to a real
42-
// session, and following it double-counts every record in that session.
43-
function findAll(dir: string, name: string, out: string[]): void {
44-
let entries: string[];
45-
try {
46-
entries = readdirSync(dir);
47-
} catch {
48-
return;
49-
}
50-
for (const entry of entries) {
51-
const path = join(dir, entry);
52-
let info: ReturnType<typeof lstatSync>;
53-
try {
54-
info = lstatSync(path);
55-
} catch {
56-
continue;
57-
}
58-
if (info.isSymbolicLink()) continue;
59-
if (info.isDirectory()) findAll(path, name, out);
60-
else if (entry === name) out.push(path);
61-
}
62-
}
63-
6442
function percentile(sorted: readonly number[], p: number): number {
6543
if (sorted.length === 0) return 0;
6644
const index = Math.min(

‎scripts/tool-fingerprint-forensics.ts‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
// Does not print or retain any turn content — only aggregate counts — so it
1414
// is safe to run without pulling trace data into an LLM context window.
1515

16-
import { readdirSync, statSync, readFileSync } from "node:fs";
16+
import { readFileSync } from "node:fs";
1717
import { join } from "node:path";
1818
import { homedir } from "node:os";
1919

20+
import { findAll } from "./find-all.js";
21+
2022
function stableJson(value: unknown): string {
2123
if (value === null || typeof value !== "object") return JSON.stringify(value);
2224
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
@@ -47,26 +49,6 @@ function fingerprintToolCalls(
4749
return parts.join("|");
4850
}
4951

50-
function findAll(dir: string, name: string, out: string[]): void {
51-
let entries: string[];
52-
try {
53-
entries = readdirSync(dir);
54-
} catch {
55-
return;
56-
}
57-
for (const entry of entries) {
58-
const path = join(dir, entry);
59-
let info: ReturnType<typeof statSync>;
60-
try {
61-
info = statSync(path);
62-
} catch {
63-
continue;
64-
}
65-
if (info.isDirectory()) findAll(path, name, out);
66-
else if (entry === name) out.push(path);
67-
}
68-
}
69-
7052
function periodicSuffixLength(seq: readonly string[], period: number): number {
7153
let i = seq.length - 1;
7254
let j = i - period;

0 commit comments

Comments
 (0)