use object::{Object, ObjectSection};
use std::process::Command;
mod artifact_guard;
fn synth() -> &'static str {
env!("CARGO_BIN_EXE_synth")
}
fn fixture(name: &str) -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join("scripts/repro")
.join(name)
}
fn compile_text(
fixture_name: &str,
out_tag: &str,
envs: &[(&str, &str)],
extra: &[&str],
) -> Result<Vec<u8>, String> {
let path = fixture(fixture_name);
let elf = artifact_guard::unique_artifact(&format!("volseg543_{out_tag}"), "elf");
let elf_str = elf.to_str().unwrap();
let mut args = vec![
"compile",
path.to_str().unwrap(),
"-o",
elf_str,
"-b",
"arm",
"--target",
"cortex-m4",
"--all-exports",
];
args.extend_from_slice(extra);
let mut cmd = Command::new(synth());
cmd.env_remove("SYNTH_BASE_CSE");
cmd.env_remove("SYNTH_CONST_CSE");
for (k, v) in envs {
cmd.env(k, v);
}
cmd.args(&args);
let bytes = artifact_guard::compile_artifact(&mut cmd, &elf)?;
let _ = std::fs::remove_file(&elf);
let obj = object::File::parse(&*bytes).expect("parse elf");
let text = obj
.section_by_name(".text")
.expect("fixture must have a .text section")
.data()
.expect("read .text")
.to_vec();
Ok(text)
}
const FIXTURE: &str = "base_cse_branch.wat";
#[test]
fn volatile_segment_flag_accepted_543() {
compile_text(
FIXTURE,
"accept_single",
&[],
&["--volatile-segment", "0x20001000:4096"],
)
.expect("single --volatile-segment must be accepted");
compile_text(
FIXTURE,
"accept_repeat",
&[],
&[
"--volatile-segment",
"0x20001000:4096",
"--volatile-segment",
"536875008:256",
],
)
.expect("repeated --volatile-segment must be accepted");
}
#[test]
fn volatile_segment_flag_rejects_garbage_543() {
let err = compile_text(FIXTURE, "reject", &[], &["--volatile-segment", "garbage"])
.expect_err("`--volatile-segment garbage` must fail");
assert!(
err.contains("volatile-segment"),
"error should name the offending flag, got: {err}"
);
}
#[test]
fn volatile_segment_flag_is_byte_inert_543() {
const BASE_CSE_OFF: (&str, &str) = ("SYNTH_BASE_CSE", "0");
const CONST_CSE_OFF: (&str, &str) = ("SYNTH_CONST_CSE", "0");
let without = compile_text(
FIXTURE,
"inert_without",
&[BASE_CSE_OFF, CONST_CSE_OFF],
&[],
)
.expect("baseline compile (no flag) must succeed");
let with = compile_text(
FIXTURE,
"inert_with",
&[BASE_CSE_OFF, CONST_CSE_OFF],
&["--volatile-segment", "0x20001000:4096"],
)
.expect("compile with flag must succeed");
assert_eq!(
without, with,
"#543: --volatile-segment changed the emitted .text with every \
address-caching lever disabled (SYNTH_BASE_CSE=0, SYNTH_CONST_CSE=0) \
— the back-off must only fire through an active lever"
);
}