//! 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));
}
