Skip to content

Commit ff54663

Browse files
committed
Expose compiletest as a library for use in Clippy
1 parent c4c7b30 commit ff54663

File tree

8 files changed

+154
-106
lines changed

8 files changed

+154
-106
lines changed

src/bootstrap/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
13821382
cmd.arg("--rust-demangler-path").arg(rust_demangler);
13831383
}
13841384

1385+
cmd.arg("--source-root").arg(&builder.src);
13851386
cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
13861387
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
13871388
cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));

src/tools/compiletest/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ name = "compiletest"
33
version = "0.0.0"
44
edition = "2021"
55

6+
[lib]
7+
doctest = false
8+
69
[dependencies]
710
colored = "2"
811
diff = "0.1.10"

src/tools/compiletest/src/common.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use std::iter;
66
use std::path::{Path, PathBuf};
77
use std::process::Command;
88
use std::str::FromStr;
9+
use std::sync::Arc;
910

1011
use crate::util::{add_dylib_path, PathBufExt};
1112
use lazycell::LazyCell;
12-
use test::ColorConfig;
13+
pub use test::ColorConfig;
1314

1415
#[derive(Clone, Copy, PartialEq, Debug)]
1516
pub enum Mode {
@@ -177,6 +178,21 @@ pub enum PanicStrategy {
177178
Abort,
178179
}
179180

181+
#[derive(Clone, Default)]
182+
pub struct Hooks {
183+
/// Return `true` to exclude a given [Path] from being considered a test file
184+
pub exclude_file: Option<Arc<dyn Fn(&Path) -> bool + Send + Sync>>,
185+
186+
/// Modify a compiler [`Command`] just before it's executed
187+
pub modify_compiler_command: Option<Arc<dyn Fn(&Path, &mut Command) + Send + Sync>>,
188+
}
189+
190+
impl fmt::Debug for Hooks {
191+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
192+
f.debug_struct("Hooks").finish_non_exhaustive()
193+
}
194+
}
195+
180196
/// Configuration for compiletest
181197
#[derive(Debug, Clone)]
182198
pub struct Config {
@@ -224,6 +240,9 @@ pub struct Config {
224240
/// `None` then these tests will be ignored.
225241
pub run_clang_based_tests_with: Option<String>,
226242

243+
/// The project root directory
244+
pub source_root: PathBuf,
245+
227246
/// The directory containing the tests to run
228247
pub src_base: PathBuf,
229248

@@ -236,6 +255,9 @@ pub struct Config {
236255
/// The test mode, e.g. ui or debuginfo.
237256
pub mode: Mode,
238257

258+
/// Don't require compile-fail or build-fail tests to contain `//~ ERROR` style comments
259+
pub no_expected_comments: bool,
260+
239261
/// The test suite (essentially which directory is running, but without the
240262
/// directory prefix such as src/test)
241263
pub suite: String,
@@ -375,6 +397,9 @@ pub struct Config {
375397
pub force_rerun: bool,
376398

377399
pub target_cfg: LazyCell<TargetCfg>,
400+
401+
/// Contains callbacks to be invoked at certain points in the test, used by Clippy
402+
pub hooks: Hooks,
378403
}
379404

380405
impl Config {

src/tools/compiletest/src/header.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -736,17 +736,10 @@ impl Config {
736736
}
737737
}
738738

739-
pub fn find_rust_src_root(&self) -> Option<PathBuf> {
740-
let mut path = self.src_base.clone();
741-
let path_postfix = Path::new("src/etc/lldb_batchmode.py");
739+
pub fn find_rust_src_root(&self) -> &Path {
740+
assert!(self.source_root.join("x.py").exists(), "Not running in Rust source root");
742741

743-
while path.pop() {
744-
if path.join(&path_postfix).is_file() {
745-
return Some(path);
746-
}
747-
}
748-
749-
None
742+
&self.source_root
750743
}
751744

752745
fn parse_edition(&self, line: &str) -> Option<String> {

src/tools/compiletest/src/header/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn config() -> Config {
4444
"--run-lib-path=",
4545
"--python=",
4646
"--jsondocck-path=",
47+
"--source-root=",
4748
"--src-base=",
4849
"--build-base=",
4950
"--stage-id=stage2",

src/tools/compiletest/src/lib.rs

+22-73
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ extern crate test;
77

88
use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
99
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths};
10-
use crate::util::logv;
1110
use getopts::Options;
1211
use lazycell::LazyCell;
1312
use std::env;
@@ -27,32 +26,15 @@ use self::header::{make_test_description, EarlyProps};
2726
mod tests;
2827

2928
pub mod common;
30-
pub mod compute_diff;
31-
pub mod errors;
32-
pub mod header;
29+
mod compute_diff;
30+
mod errors;
31+
mod header;
3332
mod json;
3433
mod raise_fd_limit;
3534
mod read2;
36-
pub mod runtest;
35+
mod runtest;
3736
pub mod util;
3837

39-
fn main() {
40-
tracing_subscriber::fmt::init();
41-
42-
let config = parse_config(env::args().collect());
43-
44-
if config.valgrind_path.is_none() && config.force_valgrind {
45-
panic!("Can't find Valgrind to run Valgrind tests");
46-
}
47-
48-
if !config.has_tidy && config.mode == Mode::Rustdoc {
49-
eprintln!("warning: `tidy` is not installed; diffs will not be generated");
50-
}
51-
52-
log_config(&config);
53-
run_tests(config);
54-
}
55-
5638
pub fn parse_config(args: Vec<String>) -> Config {
5739
let mut opts = Options::new();
5840
opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
@@ -67,6 +49,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
6749
.optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
6850
.optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
6951
.optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
52+
.reqopt("", "source-root", "root directory of the project", "PATH")
7053
.reqopt("", "src-base", "directory to scan for test files", "PATH")
7154
.reqopt("", "build-base", "directory to deposit test outputs", "PATH")
7255
.reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
@@ -232,10 +215,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
232215
run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
233216
llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
234217
llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
218+
source_root: opt_path(matches, "source-root"),
235219
src_base,
236220
build_base: opt_path(matches, "build-base"),
237221
stage_id: matches.opt_str("stage-id").unwrap(),
238222
mode,
223+
no_expected_comments: false,
239224
suite: matches.opt_str("suite").unwrap(),
240225
debugger: None,
241226
run_ignored,
@@ -296,55 +281,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
296281
npm: matches.opt_str("npm"),
297282

298283
force_rerun: matches.opt_present("force-rerun"),
299-
300284
target_cfg: LazyCell::new(),
285+
hooks: Default::default(),
301286
}
302287
}
303288

304-
pub fn log_config(config: &Config) {
305-
let c = config;
306-
logv(c, "configuration:".to_string());
307-
logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
308-
logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
309-
logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
310-
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
311-
logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
312-
logv(c, format!("src_base: {:?}", config.src_base.display()));
313-
logv(c, format!("build_base: {:?}", config.build_base.display()));
314-
logv(c, format!("stage_id: {}", config.stage_id));
315-
logv(c, format!("mode: {}", config.mode));
316-
logv(c, format!("run_ignored: {}", config.run_ignored));
317-
logv(c, format!("filters: {:?}", config.filters));
318-
logv(c, format!("skip: {:?}", config.skip));
319-
logv(c, format!("filter_exact: {}", config.filter_exact));
320-
logv(
321-
c,
322-
format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
323-
);
324-
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
325-
logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
326-
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
327-
logv(c, format!("target: {}", config.target));
328-
logv(c, format!("host: {}", config.host));
329-
logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
330-
logv(c, format!("adb_path: {:?}", config.adb_path));
331-
logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
332-
logv(c, format!("adb_device_status: {}", config.adb_device_status));
333-
logv(c, format!("ar: {}", config.ar));
334-
logv(c, format!("linker: {:?}", config.linker));
335-
logv(c, format!("verbose: {}", config.verbose));
336-
logv(c, format!("quiet: {}", config.quiet));
337-
logv(c, "\n".to_string());
338-
}
339-
340-
pub fn opt_str(maybestr: &Option<String>) -> &str {
341-
match *maybestr {
342-
None => "(none)",
343-
Some(ref s) => s,
344-
}
345-
}
346-
347-
pub fn opt_str2(maybestr: Option<String>) -> String {
289+
fn opt_str2(maybestr: Option<String>) -> String {
348290
match maybestr {
349291
None => "(none)".to_owned(),
350292
Some(s) => s,
@@ -524,7 +466,11 @@ pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
524466

525467
/// Returns a stamp constructed from input files common to all test cases.
526468
fn common_inputs_stamp(config: &Config) -> Stamp {
527-
let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
469+
if config.force_rerun {
470+
return Stamp { time: SystemTime::UNIX_EPOCH };
471+
}
472+
473+
let rust_src_dir = config.find_rust_src_root();
528474

529475
let mut stamp = Stamp::from_path(&config.rustc_path);
530476

@@ -627,6 +573,12 @@ pub fn is_test(file_name: &OsString) -> bool {
627573
}
628574

629575
fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
576+
if let Some(hook) = &config.hooks.exclude_file {
577+
if hook(&testpaths.file) {
578+
return Vec::new();
579+
}
580+
}
581+
630582
let test_path = if config.mode == Mode::RunMake {
631583
// Parse directives in the Makefile
632584
testpaths.file.join("Makefile")
@@ -648,7 +600,7 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
648600
let src_file =
649601
std::fs::File::open(&test_path).expect("open test file to parse ignores");
650602
let cfg = revision.map(|v| &**v);
651-
let test_name = crate::make_test_name(config, testpaths, revision);
603+
let test_name = make_test_name(config, testpaths, revision);
652604
let mut desc = make_test_description(config, test_name, &test_path, src_file, cfg);
653605
// Ignore tests that already run and are up to date with respect to inputs.
654606
if !config.force_rerun {
@@ -770,10 +722,7 @@ fn make_test_name(
770722
testpaths: &TestPaths,
771723
revision: Option<&String>,
772724
) -> test::TestName {
773-
// Print the name of the file, relative to the repository root.
774-
// `src_base` looks like `/path/to/rust/src/test/ui`
775-
let root_directory = config.src_base.parent().unwrap().parent().unwrap().parent().unwrap();
776-
let path = testpaths.file.strip_prefix(root_directory).unwrap();
725+
let path = testpaths.file.strip_prefix(&config.source_root).unwrap();
777726
let debugger = match config.debugger {
778727
Some(d) => format!("-{}", d),
779728
None => String::new(),

src/tools/compiletest/src/main.rs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::env;
2+
3+
use compiletest::common::{Config, Mode};
4+
use compiletest::util::logv;
5+
use compiletest::{parse_config, run_tests};
6+
7+
fn main() {
8+
tracing_subscriber::fmt::init();
9+
10+
let config = parse_config(env::args().collect());
11+
12+
if config.valgrind_path.is_none() && config.force_valgrind {
13+
panic!("Can't find Valgrind to run Valgrind tests");
14+
}
15+
16+
if !config.has_tidy && config.mode == Mode::Rustdoc {
17+
eprintln!("warning: `tidy` is not installed; diffs will not be generated");
18+
}
19+
20+
log_config(&config);
21+
run_tests(config);
22+
}
23+
24+
fn log_config(config: &Config) {
25+
let c = config;
26+
logv(c, "configuration:".to_string());
27+
logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
28+
logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
29+
logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
30+
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
31+
logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
32+
logv(c, format!("src_base: {:?}", config.src_base.display()));
33+
logv(c, format!("build_base: {:?}", config.build_base.display()));
34+
logv(c, format!("stage_id: {}", config.stage_id));
35+
logv(c, format!("mode: {}", config.mode));
36+
logv(c, format!("run_ignored: {}", config.run_ignored));
37+
logv(c, format!("filters: {:?}", config.filters));
38+
logv(c, format!("skip: {:?}", config.skip));
39+
logv(c, format!("filter_exact: {}", config.filter_exact));
40+
logv(
41+
c,
42+
format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
43+
);
44+
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
45+
logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
46+
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
47+
logv(c, format!("target: {}", config.target));
48+
logv(c, format!("host: {}", config.host));
49+
logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
50+
logv(c, format!("adb_path: {:?}", config.adb_path));
51+
logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
52+
logv(c, format!("adb_device_status: {}", config.adb_device_status));
53+
logv(c, format!("ar: {}", config.ar));
54+
logv(c, format!("linker: {:?}", config.linker));
55+
logv(c, format!("verbose: {}", config.verbose));
56+
logv(c, format!("quiet: {}", config.quiet));
57+
logv(c, "\n".to_string());
58+
}
59+
60+
fn opt_str(maybestr: &Option<String>) -> &str {
61+
match *maybestr {
62+
None => "(none)",
63+
Some(ref s) => s,
64+
}
65+
}

0 commit comments

Comments
 (0)