Files
AILang/crates/ail/tests/embed_swarm_tsan.rs
T
Brummel fbeeadeba5 iter embedding-abi-m2.1 (DONE 5-9): swarm-safe ctx ABI complete + sanitiser-verified
Completes Embedding ABI — M2.1 (Tasks 1-4 committed c9a84b3 as the
known-good subset; this commit lands Tasks 5-9 from the re-dispatch
against the Boss-corrected plan).

- T5: swarm.c per-thread-ctx scalar-swarm capability demo (no
  SHARED_CTX) + rc_accounting_shared_ctx_is_flagged_by_tsan added to
  the item-1 harness driver (de-globalisation negative-control teeth,
  where a shared ctx genuinely races on ctx->alloc_count).
- T6: M1 host.c migrated to the ctx ABI; embed_e2e green (s==25
  through the ctx-threaded forwarder).
- T7: DESIGN.md current-state update (provisional-until-M3 narrowed
  to the value/record layout; Decision-10 per-thread-ctx note);
  docs_honesty-pinned sentence + (con Int) snippet preserved verbatim.
- T8: regression gate — workspace green; null-ctx fallback
  byte-behaviour preserved.
- T9: bench-trio — compile_check/cross_lang clean; check.py
  tracked-P2 noise only, causally exonerated (zero codegen/runtime
  diff vs HEAD), NO baseline ratified.

Boss-verified directly (not on report trust): docs_honesty_pin 5/0,
design_schema_drift 8/0, embed_export_hash_stable 1/0,
embed_export_gate 6/0, embed_e2e 1/0, embed_staticlib_alloc_guard
2/0, print_no_leak_pin 1/0 + e2e rc_stats 4/0; the tsan coherent-stop
proven by hand — per-ctx clean (exit 0, 0 warnings), shared-ctx a
real ThreadSanitizer data race at rc.c:157/:208 (exit 66).

Known debt (journal + roadmap): DESIGN.md '## Embedding ABI (M1)'
header still says (M1) while the body mirrors M2 — out of Task 7's
scope-limited regions by design; post-audit doc-honesty tidy.

Milestone-close audit next.
2026-05-18 17:31:50 +02:00

43 lines
1.8 KiB
Rust

//! M2 item 2 (capability demo). Builds the staticlib (rc) via the
//! `ail` CLI, links swarm.c against lib<entry>.a + libailang_rt.a
//! under -fsanitize=thread. Per-thread-ctx: tsan-clean, exit 0,
//! every thread's result == serial oracle. (The de-globalisation
//! negative control is in embed_rc_accounting_tsan.rs — item 1.)
use std::process::Command;
use std::path::PathBuf;
fn ws_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..").canonicalize().unwrap()
}
fn ail_bin() -> &'static str { env!("CARGO_BIN_EXE_ail") }
fn build_staticlib(outdir: &PathBuf) {
std::fs::create_dir_all(outdir).unwrap();
let st = Command::new(ail_bin())
.args(["build", "examples/embed_backtest_step.ail",
"--emit=staticlib", "--alloc=rc", "-o", outdir.to_str().unwrap()])
.current_dir(ws_root()).status().expect("ail build");
assert!(st.success(), "ail build --emit=staticlib failed");
}
#[test]
fn scalar_swarm_per_ctx_is_tsan_clean_and_matches_oracle() {
let outdir = std::env::temp_dir().join("ail_m2_swarm_ok");
build_staticlib(&outdir);
let root = ws_root();
let bin = outdir.join("swarm_ok");
let st = Command::new("clang").args([
"-O1", "-g", "-fsanitize=thread", "-pthread",
"-o", bin.to_str().unwrap(),
root.join("crates/ail/tests/embed/swarm.c").to_str().unwrap(),
&format!("-L{}", outdir.to_string_lossy()),
"-lembed_backtest_step", "-lailang_rt",
]).status().expect("clang");
assert!(st.success(), "linking swarm.c failed");
let out = Command::new(&bin).env("TSAN_OPTIONS", "halt_on_error=1")
.output().expect("run swarm");
assert!(out.status.success(),
"per-thread-ctx swarm must exit 0 tsan-clean; stderr:\n{}",
String::from_utf8_lossy(&out.stderr));
}