Files
AILang/crates/ail/tests/embed_swarm_tsan.rs
T
Brummel 7ae92d3e60 refactor(test): hoist duplicated test helpers into ailang-test-support
closes #60

The fixture-corpus filter (NON_PARSEABLE_FIXTURES + list_ail_fixtures)
was copy-pasted across three test crates and drifted out of sync as
new reject fixtures landed; the examples_dir / workspace_root path
walk was reimplemented ~30 more times across the suite, under two
spellings (workspace_root / ws_root).

Introduce crates/ailang-test-support — a zero-dependency, dev-only
leaf crate — as the single home for these helpers:
- NON_PARSEABLE_FIXTURES, list_ail_fixtures
- workspace_root, examples_dir
- canonical_workspace_root (symlink-resolved variant, for the tsan/
  race tests that feed the root into native build steps)

All integration-test copies across ailang-core, ailang-surface,
ailang-prose, ailang-check, and ail now import from the shared crate;
the local definitions and their now-orphaned path imports are removed.
Path helpers resolve via the support crate's own CARGO_MANIFEST_DIR,
so they return the correct absolute paths from any caller.

ail_bin helpers are intentionally left in place: they depend on
env!("CARGO_BIN_EXE_ail"), which Cargo only defines when compiling the
ail crate's own integration tests, so they cannot move to a shared
crate.

Behaviour-identical: same paths, same fixture lists; full workspace
test suite green. Net -177 LOC.
2026-06-02 01:54:37 +02:00

40 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 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(ailang_test_support::canonical_workspace_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 = ailang_test_support::canonical_workspace_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));
}