Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/pineforge/src/codegen-docs-rule.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const GIT_FLAGS = ['-c', 'core.commitGraph=false', '-c', 'advice.graftFileDeprec

function git(dir, args, { binary = false } = {}) {
const result = spawnSync('git', ['-C', dir, ...GIT_FLAGS, ...args], {
encoding: binary ? null : 'utf8', timeout: 10_000, maxBuffer: 32 * 1024 * 1024,
encoding: binary ? null : 'utf8', maxBuffer: 32 * 1024 * 1024,
env: { ...process.env, GIT_OPTIONAL_LOCKS: '0', GIT_NO_REPLACE_OBJECTS: '1', GIT_GRAFT_FILE: '/dev/null' },
});
if (result.error || result.status !== 0) {
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ concurrency:
jobs:
preflight-docs:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 360
permissions:
contents: read
outputs:
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
needs: preflight-docs
if: needs.preflight-docs.outputs.docs_only != 'true' && (github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 360
permissions:
contents: read
env:
Expand Down Expand Up @@ -105,7 +105,7 @@ jobs:
needs: preflight-docs
if: needs.preflight-docs.outputs.docs_only != 'true' && (github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 360
permissions:
contents: read
strategy:
Expand All @@ -132,7 +132,7 @@ jobs:
if: always()
needs: [preflight-docs, differential, pytest]
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 360
permissions:
statuses: write
steps:
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/promote-baseline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,15 @@ jobs:
chmod +x /tmp/cloud-sql-proxy
/tmp/cloud-sql-proxy --port 5433 \
gen-lang-client-0864094636:asia-east1:pineforge-workflow-pg &
for _ in $(seq 1 30); do
proxy_pid=$!
while true; do
if (exec 3<>/dev/tcp/127.0.0.1/5433) 2>/dev/null; then exit 0; fi
if ! kill -0 "$proxy_pid" 2>/dev/null; then
echo "cloud-sql-proxy exited before it became ready" >&2
exit 1
fi
sleep 1
done
echo "cloud-sql-proxy did not become ready" >&2
exit 1

- name: Install campaign dependencies
if: steps.ci.outputs.green == 'true'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ concurrency:
jobs:
preflight-docs:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 360
outputs:
docs_only: ${{ steps.docs.outputs.docs_only }}
steps:
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
needs: preflight-docs
if: needs.preflight-docs.outputs.docs_only != 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
Expand Down
8 changes: 4 additions & 4 deletions scripts/gen_host_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ def find_clang(preferred: str | None = None) -> str | None:
if path is None:
continue
try:
version = subprocess.run([path, "--version"], capture_output=True, text=True,
timeout=60).stdout
version = subprocess.run([path, "--version"], capture_output=True,
text=True).stdout
except OSError:
continue
if "clang" in version.lower():
Expand All @@ -104,7 +104,7 @@ def emitter_target(repo: Path) -> tuple[tuple[str, ...], str]:
[sys.executable, "-c",
"import sys; import pineforge_codegen as pc; "
"sys.stdout.write(pc.transpile(sys.stdin.read()))"],
input=probe, capture_output=True, text=True, timeout=300,
input=probe, capture_output=True, text=True,
env=dict(os.environ, PYTHONPATH=str(repo)), cwd=repo)
if proc.returncode != 0:
raise RuntimeError(f"transpile failed:\n{proc.stderr}")
Expand All @@ -121,7 +121,7 @@ def _dump(qualified: str, tu: Path, cxx: str, include_dirs: list[str]) -> list[d
for inc in include_dirs:
cmd += ["-I", inc]
cmd += ["-Xclang", "-ast-dump=json", "-Xclang", f"-ast-dump-filter={qualified}", str(tu)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"clang could not read the host header:\n{proc.stderr[-2000:]}")
decoder, text, pos, out = json.JSONDecoder(), proc.stdout, 0, []
Expand Down
8 changes: 4 additions & 4 deletions tests/_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def compile_cpp(cpp_source: str, *, label: str = "snippet",
cmd += list(extra_flags)
cmd.append(cpp_path)
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=60,
cmd, capture_output=True, text=True,
)
if result.returncode != 0:
# Truncate large emitted-source dumps so failure reports stay
Expand Down Expand Up @@ -315,7 +315,7 @@ def narrowing_diagnostics(cpp_source: str, *, label: str = "snippet") -> list[st
*_include_flags(isolate_headers=True),
cpp_path,
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
result = subprocess.run(cmd, capture_output=True, text=True)
out = (result.stderr or "") + (result.stdout or "")
if result.returncode != 0:
raise AssertionError(
Expand Down Expand Up @@ -377,13 +377,13 @@ def run_emitted_tu(cpp_source: str, driver_main: str, *, opt: str,
*_include_flags(isolate_headers=True),
"-I", tmpdir, str(drv), str(_ENGINE_LIB), "-o", str(exe),
]
build = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
build = subprocess.run(cmd, capture_output=True, text=True)
if build.returncode != 0:
raise AssertionError(
f"could not build {label} at {opt} (exit={build.returncode}):\n"
+ "\n".join((build.stderr or build.stdout).splitlines()[:40])
)
run = subprocess.run([str(exe)], capture_output=True, text=True, timeout=120)
run = subprocess.run([str(exe)], capture_output=True, text=True)
if run.returncode != 0:
raise AssertionError(
f"{label} at {opt} exited {run.returncode}:\n{run.stdout}\n{run.stderr}"
Expand Down
8 changes: 4 additions & 4 deletions tests/_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def transpile_json(pine: Path, root: Path = REPO_ROOT,
env = dict(os.environ, PYTHONPATH=str(root), **(extra_env or {}))
proc = subprocess.run(
[sys.executable, "-c", _GLUE_MAIN, str(root / "gate"), str(pine)],
capture_output=True, text=True, timeout=300, env=env, cwd=root)
capture_output=True, text=True, env=env, cwd=root)
if proc.returncode != 0:
raise RuntimeError(f"transpile_json crashed on {pine}:\n{proc.stderr}")
return json.loads(proc.stdout)
Expand All @@ -113,7 +113,7 @@ def reference_codegen(commit: str) -> Path | None:
tree = None
proc = subprocess.run(
["git", "-C", str(REPO_ROOT), "archive", "--format=tar", commit,
"pineforge_codegen", "gate"], capture_output=True, timeout=120)
"pineforge_codegen", "gate"], capture_output=True)
if proc.returncode == 0:
tree = Path(tempfile.mkdtemp(prefix=f"pf-codegen-{commit[:12]}-"))
with tarfile.open(fileobj=io.BytesIO(proc.stdout)) as tar:
Expand All @@ -135,7 +135,7 @@ def build_strategy_library(cpp: str, workdir: Path) -> None:
cmd = [compile_env._COMPILER, "-std=c++17", "-O2", *compile_env.STRATEGY_FP_FLAGS,
"-fPIC", "-shared", *compile_env._include_flags(isolate_headers=True),
str(workdir / "generated.cpp"), *link, "-o", str(workdir / "strategy.so")]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"compile failed in {workdir}:\n"
+ "\n".join(proc.stderr.splitlines()[:40]))
Expand All @@ -156,7 +156,7 @@ def run_strategy(engine_root: Path, workdir: Path, feed: Path,
trace_path = workdir / f"trace_{tag}.json"
if trace:
cmd += ["--trace-json", str(trace_path)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"run_strategy failed in {workdir}:\n{proc.stdout}\n{proc.stderr}")
records = json.loads(trace_path.read_text())["trace"] if trace else None
Expand Down
2 changes: 1 addition & 1 deletion tests/_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def run(engine_root: Path, workdir: Path, feed: Path, root: Path | None,
[sys.executable, str(engine_root / "scripts" / "run_strategy.py"), str(workdir),
"--ohlcv", str(feed), "--inputs-json", str(workdir / f"inputs_{tag}.json"),
"--no-trim-output", "-o", str(out), "--trace-json", str(trace_path)],
capture_output=True, text=True, timeout=600, env=env)
capture_output=True, text=True, env=env)
if proc.returncode != 0:
return Run(False, proc.stdout + proc.stderr, {}, b"")
per_bar: dict[int, dict[str, float]] = {}
Expand Down
4 changes: 2 additions & 2 deletions tests/test_array_checked_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,14 +547,14 @@ def _compile_and_run(cpp_source: str) -> str:
if compile_env._GENERATED_INC is not None:
command += ["-I", str(compile_env._GENERATED_INC)]
command += [str(cpp_path), str(engine_lib), "-pthread", "-o", str(exe_path)]
built = subprocess.run(command, capture_output=True, text=True, timeout=120)
built = subprocess.run(command, capture_output=True, text=True)
if built.returncode != 0:
raise AssertionError(
"checked-array runtime probe failed to link\n"
+ "\n".join((built.stderr or built.stdout).splitlines()[:100])
)
ran = subprocess.run(
[str(exe_path)], capture_output=True, text=True, timeout=30
[str(exe_path)], capture_output=True, text=True
)
if ran.returncode != 0:
raise AssertionError(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_arrseg_coded_run_stops.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def test_history_stop_run_json_reports_code_and_args(name, tmp_path):
[sys.executable, str(engine / "docker" / "run_json.py"),
"--so", str(tmp_path / "strategy.so"), "--ohlcv", str(feed),
"--generated-cpp", str(tmp_path / "generated.cpp")],
capture_output=True, text=True, timeout=180)
capture_output=True, text=True)
assert result.returncode == 1, f"{result.stdout}\n{result.stderr}"
payload = json.loads(result.stdout)
assert set(payload) == {"engine", "error", "code", "args"}
Expand Down
3 changes: 0 additions & 3 deletions tests/test_codegen_determinism.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ def _transpile_under_seed(seed: int, fixture: str = FIXTURE) -> str:
env=env,
capture_output=True,
text=True,
timeout=120,
)
assert proc.returncode == 0, (
f"transpile subprocess failed under PYTHONHASHSEED={seed} "
Expand Down Expand Up @@ -241,7 +240,6 @@ def test_security_history_envelopes_ignore_memory_layout(fixture: str) -> None:
env={**os.environ, "PYTHONHASHSEED": str(seed)},
capture_output=True,
text=True,
timeout=120,
)
assert process.returncode == 0, process.stderr
assert process.stdout
Expand Down Expand Up @@ -279,7 +277,6 @@ def test_collision_error_envelope_byte_identical_across_hash_seeds() -> None:
env={**os.environ, "PYTHONHASHSEED": str(seed)},
capture_output=True,
text=True,
timeout=120,
)
assert process.returncode == 0, process.stderr
envelope = json.loads(process.stdout)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_e2e_bar_magnifier_flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def _host(engine_root: Path, feeds: dict[str, Path], workdir: Path, tape: str,
out = workdir / "engine_trades.csv"
cmd = [sys.executable, str(engine_root / "scripts" / "run_strategy.py"), str(workdir),
"--ohlcv", str(feed), "--no-trim-output", "-o", str(out)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"run_strategy failed:\n{proc.stdout}\n{proc.stderr}")
outcome.engine = trades(out, 0)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_e2e_drawing_lifetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def _replay(engine_root: Path, feed: Path, workdir: Path, case: Case, codegen: P
cmd = [sys.executable, str(engine_root / "scripts" / "run_strategy.py"), str(workdir),
"--ohlcv", str(feed), "--no-trim-output", "-o", str(out),
"--trace-json", str(trace)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"run_strategy failed:\n{proc.stdout}\n{proc.stderr}")
outcome.engine = trades(out, 0)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_e2e_function_global_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def run_on_tape(engine_root: Path, workdir: Path, feed: Path) -> Path:
out = workdir / "engine_trades.csv"
cmd = [sys.executable, str(engine_root / "scripts" / "run_strategy.py"), str(workdir),
"--ohlcv", str(feed), "-o", str(out)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"run_strategy failed in {workdir}:\n{proc.stdout}\n{proc.stderr}")
return out
Expand Down
2 changes: 1 addition & 1 deletion tests/test_e2e_strategy_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def run_on_tape(engine_root: Path, workdir: Path, feed: Path) -> Path:
out = workdir / "engine_trades.csv"
cmd = [sys.executable, str(engine_root / "scripts" / "run_strategy.py"), str(workdir),
"--ohlcv", str(feed), "-o", str(out)]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"run_strategy failed in {workdir}:\n{proc.stdout}\n{proc.stderr}")
return out
Expand Down
4 changes: 2 additions & 2 deletions tests/test_float_relational_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,15 @@ def _compile_and_run(cpp_source: str) -> str:
cmd += ["-I", str(compile_env._GENERATED_INC)]
cmd += [str(cpp_path), str(engine_lib), "-pthread", "-o", str(exe_path)]

built = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
built = subprocess.run(cmd, capture_output=True, text=True)
if built.returncode != 0:
raise AssertionError(
"generated comparator runtime probe failed to link\n"
+ "\n".join((built.stderr or built.stdout).splitlines()[:80])
)

ran = subprocess.run(
[str(exe_path)], capture_output=True, text=True, timeout=30
[str(exe_path)], capture_output=True, text=True
)
if ran.returncode != 0:
raise AssertionError(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_lazy_edge_ta_every_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,10 +668,10 @@ def _compile_and_run(source: str) -> str:
if compile_env._GENERATED_INC is not None:
command += ["-I", str(compile_env._GENERATED_INC)]
command += [str(cpp), str(engine_lib), "-pthread", "-o", str(exe)]
built = subprocess.run(command, capture_output=True, text=True, timeout=180)
built = subprocess.run(command, capture_output=True, text=True)
if built.returncode != 0:
raise AssertionError(built.stderr or built.stdout)
ran = subprocess.run([str(exe)], capture_output=True, text=True, timeout=30)
ran = subprocess.run([str(exe)], capture_output=True, text=True)
if ran.returncode != 0:
raise AssertionError(ran.stderr or ran.stdout)
return ran.stdout.strip()
Expand Down
4 changes: 2 additions & 2 deletions tests/test_lazy_source_clock_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ def _compile_and_run(source: str) -> str:
if compile_env._GENERATED_INC is not None:
command += ["-I", str(compile_env._GENERATED_INC)]
command += [str(cpp), str(engine_lib), "-pthread", "-o", str(exe)]
built = subprocess.run(command, capture_output=True, text=True, timeout=180)
built = subprocess.run(command, capture_output=True, text=True)
if built.returncode != 0:
raise AssertionError(built.stderr or built.stdout)
ran = subprocess.run([str(exe)], capture_output=True, text=True, timeout=30)
ran = subprocess.run([str(exe)], capture_output=True, text=True)
if ran.returncode != 0:
raise AssertionError(ran.stderr or ran.stdout)
return ran.stdout.strip()
Expand Down
4 changes: 2 additions & 2 deletions tests/test_map_param_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,14 @@ def _compile_and_run(cpp_source: str) -> str:
if compile_env._GENERATED_INC is not None:
command += ["-I", str(compile_env._GENERATED_INC)]
command += [str(cpp_path), str(engine_lib), "-pthread", "-o", str(exe_path)]
built = subprocess.run(command, capture_output=True, text=True, timeout=120)
built = subprocess.run(command, capture_output=True, text=True)
if built.returncode != 0:
raise AssertionError(
"typed-map runtime probe failed to link\n"
+ "\n".join((built.stderr or built.stdout).splitlines()[:100])
)
ran = subprocess.run(
[str(exe_path)], capture_output=True, text=True, timeout=30
[str(exe_path)], capture_output=True, text=True
)
if ran.returncode != 0:
raise AssertionError(
Expand Down
51 changes: 51 additions & 0 deletions tests/test_no_time_limit_on_slow_compiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""A slow but correct compiler must never fail a check; this test runs about
65 seconds on purpose to exercise a compiler slower than the old helper limit.
"""

import os
import shlex
import shutil
import subprocess
import sys
from pathlib import Path

import pytest

from tests._compile import skip_if_no_compile_env


def test_compile_cpp_waits_for_slow_compiler(tmp_path):
skip_if_no_compile_env()
real_compiler = shutil.which(os.environ.get("CXX", "g++"))
if real_compiler is None:
pytest.skip("CXX compiler not found on PATH (try CXX=clang++).")

wrapper = tmp_path / "slow-compiler"
wrapper.write_text(
"#!/bin/sh\n"
"sleep 62\n"
f'exec {shlex.quote(str(Path(real_compiler).absolute()))} "$@"\n',
encoding="utf-8",
)
wrapper.chmod(0o755)
child_env = os.environ.copy()
child_env["CXX"] = str(wrapper)
child_code = (
"from tests._compile import compile_cpp\n"
'compile_cpp("int main() { return 0; }\\n", label="slow-compiler")\n'
'print("SLOW_COMPILER_OK")\n'
)
child = subprocess.run(
[sys.executable, "-c", child_code],
cwd=Path(__file__).resolve().parents[1],
env=child_env,
capture_output=True,
text=True,
)

output = f"stdout:\n{child.stdout}\nstderr:\n{child.stderr}"
assert child.returncode == 0, output
assert "SLOW_COMPILER_OK" in child.stdout.splitlines(), output
for word in ("TimeoutExpired", "timed out", "Timeout"):
assert word not in child.stdout, output
assert word not in child.stderr, output
2 changes: 1 addition & 1 deletion tests/test_parser_corpus_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def _pytest(*args: str, cwd: Path, include: Path | None) -> subprocess.Completed
return subprocess.run(
[sys.executable, "-m", "pytest", "-p", "no:cacheprovider", "-o", "addopts=",
"--rootdir", str(REPO_ROOT), str(TEST_PARSER), "-k", TEST_NAME, "-q", *args],
cwd=cwd, env=env, capture_output=True, text=True, timeout=300)
cwd=cwd, env=env, capture_output=True, text=True)


def _collected(cwd: Path, include: Path) -> list[str]:
Expand Down
Loading
Loading