2026-03-16 00:21:06 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# test_inject_extraction.sh — Tests the calculateParams body extraction logic in inject.sh.
|
|
|
|
|
# Verifies that the brace-depth counter correctly handles simple bodies and bodies
|
|
|
|
|
# containing nested if/else blocks.
|
|
|
|
|
# Exit: 0 if all tests pass, 1 if any fail.
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2026-03-18 13:11:33 +00:00
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
|
2026-03-16 00:21:06 +00:00
|
|
|
PASS=0
|
|
|
|
|
FAIL=0
|
|
|
|
|
|
|
|
|
|
run_extraction() {
|
|
|
|
|
local sol_content="$1"
|
|
|
|
|
python3 - <<PYEOF
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
push3 = """$sol_content"""
|
|
|
|
|
|
|
|
|
|
fn_start = push3.find("function calculateParams")
|
|
|
|
|
if fn_start == -1:
|
|
|
|
|
sys.exit("calculateParams not found")
|
|
|
|
|
brace_start = push3.find("{", fn_start)
|
|
|
|
|
body_start = push3.index("\n", brace_start) + 1
|
|
|
|
|
|
|
|
|
|
lines = push3[body_start:].split("\n")
|
|
|
|
|
body_lines = []
|
|
|
|
|
depth = 1
|
|
|
|
|
for line in lines:
|
|
|
|
|
depth += line.count("{") - line.count("}")
|
|
|
|
|
if depth <= 0:
|
|
|
|
|
break
|
|
|
|
|
body_lines.append(line)
|
|
|
|
|
else:
|
|
|
|
|
sys.exit("error: calculateParams body: closing brace never found (EOF)")
|
|
|
|
|
|
|
|
|
|
print("\n".join(body_lines))
|
|
|
|
|
PYEOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert_contains() {
|
|
|
|
|
local name="$1"
|
|
|
|
|
local output="$2"
|
|
|
|
|
local expected="$3"
|
|
|
|
|
if echo "$output" | grep -qF "$expected"; then
|
|
|
|
|
echo " PASS: $name"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo " FAIL: $name"
|
|
|
|
|
echo " expected to contain: $expected"
|
|
|
|
|
echo " actual output:"
|
|
|
|
|
echo "$output" | sed 's/^/ /'
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert_not_line() {
|
|
|
|
|
# Asserts no line in output matches the given ERE pattern exactly (anchored).
|
|
|
|
|
local name="$1"
|
|
|
|
|
local output="$2"
|
|
|
|
|
local pattern="$3"
|
|
|
|
|
if echo "$output" | grep -qE "^${pattern}$"; then
|
|
|
|
|
echo " FAIL: $name"
|
|
|
|
|
echo " expected no line matching: ^${pattern}\$"
|
|
|
|
|
echo " actual output:"
|
|
|
|
|
echo "$output" | sed 's/^/ /'
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
else
|
|
|
|
|
echo " PASS: $name"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ── Test 1: Simple body (no nested braces) ──────────────────────────────────
|
|
|
|
|
echo "Test 1: Simple body (no nested braces)"
|
|
|
|
|
SIMPLE_SOL='contract C {
|
|
|
|
|
function calculateParams() public pure returns (uint256 ci) {
|
|
|
|
|
uint256 x = 1;
|
|
|
|
|
ci = x;
|
|
|
|
|
}
|
|
|
|
|
}'
|
|
|
|
|
|
|
|
|
|
OUT=$(run_extraction "$SIMPLE_SOL")
|
|
|
|
|
assert_contains "simple: includes body statement" "$OUT" "uint256 x = 1;"
|
|
|
|
|
assert_contains "simple: includes assignment" "$OUT" "ci = x;"
|
|
|
|
|
assert_not_line "simple: excludes function closing }" "$OUT" " \}"
|
|
|
|
|
|
|
|
|
|
# ── Test 2: Nested if/else block ─────────────────────────────────────────────
|
|
|
|
|
echo "Test 2: Nested if/else block"
|
|
|
|
|
NESTED_SOL='contract C {
|
|
|
|
|
function calculateParams() public pure returns (uint256 ci) {
|
|
|
|
|
if (x > 0) {
|
|
|
|
|
ci = 1;
|
|
|
|
|
} else {
|
|
|
|
|
ci = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}'
|
|
|
|
|
|
|
|
|
|
OUT=$(run_extraction "$NESTED_SOL")
|
|
|
|
|
assert_contains "nested: includes if condition" "$OUT" "if (x > 0) {"
|
|
|
|
|
assert_contains "nested: includes true branch" "$OUT" "ci = 1;"
|
|
|
|
|
assert_contains "nested: includes else clause" "$OUT" "} else {"
|
|
|
|
|
assert_contains "nested: includes false branch" "$OUT" "ci = 0;"
|
|
|
|
|
assert_contains "nested: includes closing if brace" "$OUT" " }"
|
|
|
|
|
assert_not_line "nested: excludes function closing }" "$OUT" " \}"
|
|
|
|
|
|
|
|
|
|
# ── Test 3: Multiple levels of nesting ───────────────────────────────────────
|
|
|
|
|
echo "Test 3: Multiple nesting levels"
|
|
|
|
|
DEEP_SOL='contract C {
|
|
|
|
|
function calculateParams() public pure returns (uint256 ci) {
|
|
|
|
|
if (a) {
|
|
|
|
|
if (b) {
|
|
|
|
|
ci = 2;
|
|
|
|
|
} else {
|
|
|
|
|
ci = 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ci = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}'
|
|
|
|
|
|
|
|
|
|
OUT=$(run_extraction "$DEEP_SOL")
|
|
|
|
|
assert_contains "deep: outer if" "$OUT" "if (a) {"
|
|
|
|
|
assert_contains "deep: inner if" "$OUT" "if (b) {"
|
|
|
|
|
assert_contains "deep: inner value" "$OUT" "ci = 2;"
|
|
|
|
|
assert_contains "deep: outer else" "$OUT" "ci = 0;"
|
|
|
|
|
|
|
|
|
|
# ── Test 4: EOF without closing brace triggers non-zero exit ─────────────────
|
|
|
|
|
echo "Test 4: EOF without closing brace"
|
|
|
|
|
BAD_SOL='contract C {
|
|
|
|
|
function calculateParams() public pure returns (uint256 ci) {
|
|
|
|
|
uint256 x = 1;'
|
|
|
|
|
|
|
|
|
|
if python3 - <<PYEOF 2>/dev/null; then
|
|
|
|
|
import sys
|
|
|
|
|
push3 = """$BAD_SOL"""
|
|
|
|
|
fn_start = push3.find("function calculateParams")
|
|
|
|
|
brace_start = push3.find("{", fn_start)
|
|
|
|
|
body_start = push3.index("\n", brace_start) + 1
|
|
|
|
|
lines = push3[body_start:].split("\n")
|
|
|
|
|
body_lines = []
|
|
|
|
|
depth = 1
|
|
|
|
|
for line in lines:
|
|
|
|
|
depth += line.count("{") - line.count("}")
|
|
|
|
|
if depth <= 0:
|
|
|
|
|
break
|
|
|
|
|
body_lines.append(line)
|
|
|
|
|
else:
|
|
|
|
|
sys.exit("error: calculateParams body: closing brace never found (EOF)")
|
|
|
|
|
PYEOF
|
|
|
|
|
echo " FAIL: EOF case should have exited non-zero"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
else
|
|
|
|
|
echo " PASS: EOF case exits non-zero"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
fi
|
|
|
|
|
|
2026-03-18 13:11:33 +00:00
|
|
|
# ── Test 5: forge build on transpiled optimizer_seed.push3 ───────────────────
|
|
|
|
|
echo "Test 5: forge build on transpiled optimizer_seed.push3 (compile regression guard)"
|
|
|
|
|
|
|
|
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
|
TMPDIR_I5=$(mktemp -d)
|
|
|
|
|
trap 'rm -rf "$TMPDIR_I5"' EXIT
|
|
|
|
|
|
|
|
|
|
if [ ! -d "$SCRIPT_DIR/node_modules" ]; then
|
|
|
|
|
(cd "$SCRIPT_DIR" && npm install --silent)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
SOL_OUT="$TMPDIR_I5/OptimizerV3Push3.sol"
|
|
|
|
|
TRANSPILE_RC=0
|
2026-03-19 18:08:10 +00:00
|
|
|
(cd "$SCRIPT_DIR" && npx tsx src/index.ts \
|
2026-03-18 13:11:33 +00:00
|
|
|
"$REPO_ROOT/tools/push3-transpiler/optimizer_seed.push3" "$SOL_OUT") \
|
|
|
|
|
>/dev/null 2>&1 || TRANSPILE_RC=$?
|
|
|
|
|
|
|
|
|
|
if [ "$TRANSPILE_RC" -ne 0 ]; then
|
|
|
|
|
echo " FAIL: transpiler failed on optimizer_seed.push3"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
else
|
|
|
|
|
FORGE_BIN="$(command -v forge 2>/dev/null || true)"
|
|
|
|
|
if [ -z "$FORGE_BIN" ] && [ -x /root/.foundry/bin/forge ]; then
|
|
|
|
|
FORGE_BIN=/root/.foundry/bin/forge
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ -z "$FORGE_BIN" ]; then
|
|
|
|
|
echo " SKIP: forge not found — add foundry bin to PATH to enable compile verification"
|
|
|
|
|
else
|
|
|
|
|
FORGE_DIR="$TMPDIR_I5/forge_verify"
|
|
|
|
|
mkdir -p "$FORGE_DIR/src"
|
2026-03-18 13:17:18 +00:00
|
|
|
printf '[profile.default]\nsrc = "src"\nout = "out"\nlibs = []\nvia_ir = true\n' > "$FORGE_DIR/foundry.toml"
|
2026-03-18 13:11:33 +00:00
|
|
|
cp "$REPO_ROOT/onchain/src/IOptimizer.sol" "$FORGE_DIR/src/"
|
|
|
|
|
cp "$SOL_OUT" "$FORGE_DIR/src/OptimizerV3Push3.sol"
|
|
|
|
|
|
|
|
|
|
FORGE_OUT=""
|
|
|
|
|
FORGE_RC=0
|
|
|
|
|
FORGE_OUT=$(cd "$FORGE_DIR" && "$FORGE_BIN" build 2>&1) || FORGE_RC=$?
|
|
|
|
|
|
|
|
|
|
if [ "$FORGE_RC" -eq 0 ]; then
|
|
|
|
|
echo " PASS: forge build succeeded on transpiled optimizer_seed.push3"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo " FAIL: forge build failed on transpiled optimizer_seed.push3"
|
|
|
|
|
echo "$FORGE_OUT" | sed 's/^/ /'
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2026-03-16 00:21:06 +00:00
|
|
|
# ── Summary ──────────────────────────────────────────────────────────────────
|
|
|
|
|
echo ""
|
|
|
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
|
|
|
[ "$FAIL" -eq 0 ]
|