Rust · 2214 bytes Raw Blame History
1 use std::fs;
2 use std::path::PathBuf;
3 use std::process::Command;
4
5 fn have_xcrun() -> bool {
6 Command::new("xcrun")
7 .arg("-f")
8 .arg("as")
9 .output()
10 .map(|o| o.status.success())
11 .unwrap_or(false)
12 }
13
14 fn assemble(src: &str, out: &PathBuf) -> Result<(), String> {
15 let tmp = std::env::temp_dir().join(format!(
16 "afs-ld-cli-diag-{}-{}.s",
17 std::process::id(),
18 out.file_stem().and_then(|s| s.to_str()).unwrap_or("t")
19 ));
20 fs::write(&tmp, src).map_err(|e| format!("write: {e}"))?;
21 let output = Command::new("xcrun")
22 .args(["--sdk", "macosx", "as", "-arch", "arm64"])
23 .arg(&tmp)
24 .arg("-o")
25 .arg(out)
26 .output()
27 .map_err(|e| format!("spawn xcrun as: {e}"))?;
28 let _ = fs::remove_file(&tmp);
29 if !output.status.success() {
30 return Err(format!(
31 "xcrun as failed: {}",
32 String::from_utf8_lossy(&output.stderr)
33 ));
34 }
35 Ok(())
36 }
37
38 fn scratch(name: &str) -> PathBuf {
39 std::env::temp_dir().join(format!("afs-ld-cli-diag-{}-{name}", std::process::id()))
40 }
41
42 #[test]
43 fn undefined_symbol_diagnostic_is_not_double_prefixed() {
44 if !have_xcrun() {
45 eprintln!("skipping: xcrun as unavailable");
46 return;
47 }
48
49 let exe = env!("CARGO_BIN_EXE_afs-ld");
50 let obj = scratch("missing.o");
51 let src = r#"
52 .section __TEXT,__text,regular,pure_instructions
53 .globl _main
54 _main:
55 bl _missing
56 ret
57 .subsections_via_symbols
58 "#;
59 if let Err(e) = assemble(src, &obj) {
60 eprintln!("skipping: assemble failed: {e}");
61 return;
62 }
63
64 let out = Command::new(exe)
65 .arg("-o")
66 .arg(scratch("missing.out"))
67 .arg(&obj)
68 .output()
69 .expect("afs-ld should run");
70 let stderr = String::from_utf8_lossy(&out.stderr);
71 assert!(
72 stderr.contains("afs-ld: error: undefined symbol: _missing"),
73 "missing expected undefined-symbol diagnostic:\n{stderr}"
74 );
75 assert!(
76 !stderr.contains("afs-ld: error: afs-ld: error:"),
77 "diagnostic was double-prefixed:\n{stderr}"
78 );
79
80 let _ = fs::remove_file(obj);
81 }
82