Skip to content

Commit 798e336

Browse files
test: create clang-like Test shim binary that validates -? options
1 parent b777f2e commit 798e336

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

src/bin/clang-shim.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//! This bin target is only used for this crate's tests.
2+
//! It is not intended for users and is not published with the library code to crates.io.
3+
4+
#![cfg_attr(test, allow(dead_code))]
5+
#![allow(clippy::disallowed_methods)]
6+
7+
use core::hash;
8+
use std::env;
9+
use std::fs::File;
10+
use std::io::{self, prelude::*};
11+
use std::path::PathBuf;
12+
use std::process::ExitCode;
13+
14+
fn main() -> ExitCode {
15+
let args = env::args().collect::<Vec<_>>();
16+
let mut args = args.iter();
17+
let program = args.next().expect("Unexpected empty args");
18+
19+
let out_dir = PathBuf::from(
20+
env::var_os("GCCTEST_OUT_DIR")
21+
.unwrap_or_else(|| panic!("{}: GCCTEST_OUT_DIR not found", program)),
22+
);
23+
24+
let mut passed_cli_validation = true;
25+
26+
// Validate that we got no `-?` without a preceding `--driver-mode=cl`. Compiler family
27+
// detection depends on this.
28+
if let Some(cl_like_help_option_idx) = args.clone().position(|a| a == "-?") {
29+
let has_cl_clang_driver_before_cl_like_help_option = args
30+
.clone()
31+
.take(cl_like_help_option_idx)
32+
.rev()
33+
.find_map(|a| a.strip_prefix("--driver-mode="))
34+
.is_some_and(|a| a == "cl");
35+
if !has_cl_clang_driver_before_cl_like_help_option {
36+
eprintln!(
37+
"Found `-?` argument, but it was not preceded by a `--driver-mode=cl` argument."
38+
);
39+
}
40+
passed_cli_validation &= has_cl_clang_driver_before_cl_like_help_option;
41+
}
42+
43+
// Find the first nonexistent candidate file to which the program's args can be written.
44+
let candidate = (0..).find_map(|i| {
45+
let candidate = out_dir.join(format!("out{}", i));
46+
47+
if candidate.exists() {
48+
// If the file exists, commands have already run. Try again.
49+
None
50+
} else {
51+
Some(candidate)
52+
}
53+
}).unwrap_or_else(|| panic!("Cannot find the first nonexistent candidate file to which the program's args can be written under out_dir '{}'", out_dir.display()));
54+
55+
// Create a file and record the args passed to the command.
56+
let f = File::create(&candidate).unwrap_or_else(|e| {
57+
panic!(
58+
"{}: can't create candidate: {}, error: {}",
59+
program,
60+
candidate.display(),
61+
e
62+
)
63+
});
64+
let mut f = io::BufWriter::new(f);
65+
66+
(|| {
67+
for arg in args {
68+
writeln!(f, "{}", arg)?;
69+
}
70+
71+
f.flush()?;
72+
73+
let mut f = f.into_inner()?;
74+
f.flush()?;
75+
f.sync_all()
76+
})()
77+
.unwrap_or_else(|e| {
78+
panic!(
79+
"{}: can't write to candidate: {}, error: {}",
80+
program,
81+
candidate.display(),
82+
e
83+
)
84+
});
85+
86+
// Create a file used by some tests.
87+
let path = &out_dir.join("libfoo.a");
88+
File::create(path).unwrap_or_else(|e| {
89+
panic!(
90+
"{}: can't create libfoo.a: {}, error: {}",
91+
program,
92+
path.display(),
93+
e
94+
)
95+
});
96+
97+
if passed_cli_validation {
98+
ExitCode::SUCCESS
99+
} else {
100+
ExitCode::FAILURE
101+
}
102+
}

tests/support/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ impl Test {
6767
}
6868

6969
pub fn clang() -> Test {
70-
let t = Test::new();
70+
let mut t = Test::new();
71+
t.gcc.pop();
72+
t.gcc.push(format!("clang-shim{}", env::consts::EXE_SUFFIX));
7173
t.shim("clang").shim("clang++").shim("ar");
7274
t
7375
}

0 commit comments

Comments
 (0)