avoid cloning the whole compiletest configuration for every test

This commit is contained in:
Pietro Albini 2023-03-10 12:17:36 +01:00
parent c075691b82
commit 55121a9c46
No known key found for this signature in database
GPG Key ID: CD76B35F7734769E
3 changed files with 50 additions and 31 deletions

View File

@ -8,7 +8,7 @@ use std::process::Command;
use std::str::FromStr;
use crate::util::{add_dylib_path, PathBufExt};
use lazycell::LazyCell;
use lazycell::AtomicLazyCell;
use serde::de::{Deserialize, Deserializer, Error as _};
use std::collections::{HashMap, HashSet};
use test::{ColorConfig, OutputFormat};
@ -326,7 +326,7 @@ pub struct Config {
/// Only rerun the tests that result has been modified accoring to Git status
pub only_modified: bool,
pub target_cfg: LazyCell<TargetCfg>,
pub target_cfgs: AtomicLazyCell<TargetCfgs>,
pub nocapture: bool,
}
@ -340,7 +340,13 @@ impl Config {
}
pub fn target_cfgs(&self) -> &TargetCfgs {
self.target_cfgs.borrow_with(|| TargetCfgs::new(self))
match self.target_cfgs.borrow() {
Some(cfgs) => cfgs,
None => {
let _ = self.target_cfgs.fill(TargetCfgs::new(self));
self.target_cfgs.borrow().unwrap()
}
}
}
pub fn target_cfg(&self) -> &TargetCfg {

View File

@ -11,7 +11,7 @@ use crate::util::logv;
use build_helper::git::{get_git_modified_files, get_git_untracked_files};
use core::panic;
use getopts::Options;
use lazycell::LazyCell;
use lazycell::AtomicLazyCell;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
@ -25,6 +25,7 @@ use tracing::*;
use walkdir::WalkDir;
use self::header::{make_test_description, EarlyProps};
use std::sync::Arc;
#[cfg(test)]
mod tests;
@ -42,7 +43,7 @@ pub mod util;
fn main() {
tracing_subscriber::fmt::init();
let config = parse_config(env::args().collect());
let config = Arc::new(parse_config(env::args().collect()));
if config.valgrind_path.is_none() && config.force_valgrind {
panic!("Can't find Valgrind to run Valgrind tests");
@ -313,7 +314,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
force_rerun: matches.opt_present("force-rerun"),
target_cfgs: LazyCell::new(),
target_cfgs: AtomicLazyCell::new(),
nocapture: matches.opt_present("nocapture"),
}
@ -369,7 +370,7 @@ pub fn opt_str2(maybestr: Option<String>) -> String {
}
}
pub fn run_tests(config: Config) {
pub fn run_tests(config: Arc<Config>) {
// If we want to collect rustfix coverage information,
// we first make sure that the coverage file does not exist.
// It will be created later on.
@ -411,7 +412,7 @@ pub fn run_tests(config: Config) {
};
let mut tests = Vec::new();
for c in &configs {
for c in configs {
let mut found_paths = BTreeSet::new();
make_tests(c, &mut tests, &mut found_paths);
check_overlapping_tests(&found_paths);
@ -433,7 +434,11 @@ pub fn run_tests(config: Config) {
println!(
"Some tests failed in compiletest suite={}{} mode={} host={} target={}",
config.suite,
config.compare_mode.map(|c| format!(" compare_mode={:?}", c)).unwrap_or_default(),
config
.compare_mode
.as_ref()
.map(|c| format!(" compare_mode={:?}", c))
.unwrap_or_default(),
config.mode,
config.host,
config.target
@ -453,13 +458,13 @@ pub fn run_tests(config: Config) {
}
}
fn configure_cdb(config: &Config) -> Option<Config> {
fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
config.cdb.as_ref()?;
Some(Config { debugger: Some(Debugger::Cdb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
}
fn configure_gdb(config: &Config) -> Option<Config> {
fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
config.gdb_version?;
if config.matches_env("msvc") {
@ -490,10 +495,10 @@ fn configure_gdb(config: &Config) -> Option<Config> {
env::set_var("RUST_TEST_THREADS", "1");
}
Some(Config { debugger: Some(Debugger::Gdb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
}
fn configure_lldb(config: &Config) -> Option<Config> {
fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
config.lldb_python_dir.as_ref()?;
if let Some(350) = config.lldb_version {
@ -506,7 +511,7 @@ fn configure_lldb(config: &Config) -> Option<Config> {
return None;
}
Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() })
Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
}
pub fn test_opts(config: &Config) -> test::TestOpts {
@ -541,17 +546,17 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
}
pub fn make_tests(
config: &Config,
config: Arc<Config>,
tests: &mut Vec<test::TestDescAndFn>,
found_paths: &mut BTreeSet<PathBuf>,
) {
debug!("making tests from {:?}", config.src_base.display());
let inputs = common_inputs_stamp(config);
let modified_tests = modified_tests(config, &config.src_base).unwrap_or_else(|err| {
let inputs = common_inputs_stamp(&config);
let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
});
collect_tests_from_dir(
config,
config.clone(),
&config.src_base,
&PathBuf::new(),
&inputs,
@ -622,7 +627,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
}
fn collect_tests_from_dir(
config: &Config,
config: Arc<Config>,
dir: &Path,
relative_dir_path: &Path,
inputs: &Stamp,
@ -650,7 +655,7 @@ fn collect_tests_from_dir(
// sequential loop because otherwise, if we do it in the
// tests themselves, they race for the privilege of
// creating the directories and sometimes fail randomly.
let build_dir = output_relative_path(config, relative_dir_path);
let build_dir = output_relative_path(&config, relative_dir_path);
fs::create_dir_all(&build_dir).unwrap();
// Add each `.rs` file as a test, and recurse further on any
@ -666,13 +671,13 @@ fn collect_tests_from_dir(
let paths =
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
tests.extend(make_test(config, &paths, inputs))
tests.extend(make_test(config.clone(), &paths, inputs))
} else if file_path.is_dir() {
let relative_file_path = relative_dir_path.join(file.file_name());
if &file_name != "auxiliary" {
debug!("found directory: {:?}", file_path.display());
collect_tests_from_dir(
config,
config.clone(),
&file_path,
&relative_file_path,
inputs,
@ -701,14 +706,18 @@ pub fn is_test(file_name: &OsString) -> bool {
!invalid_prefixes.iter().any(|p| file_name.starts_with(p))
}
fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
fn make_test(
config: Arc<Config>,
testpaths: &TestPaths,
inputs: &Stamp,
) -> Vec<test::TestDescAndFn> {
let test_path = if config.mode == Mode::RunMake {
// Parse directives in the Makefile
testpaths.file.join("Makefile")
} else {
PathBuf::from(&testpaths.file)
};
let early_props = EarlyProps::from_file(config, &test_path);
let early_props = EarlyProps::from_file(&config, &test_path);
// Incremental tests are special, they inherently cannot be run in parallel.
// `runtest::run` will be responsible for iterating over revisions.
@ -723,19 +732,22 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
let src_file =
std::fs::File::open(&test_path).expect("open test file to parse ignores");
let cfg = revision.map(|v| &**v);
let test_name = crate::make_test_name(config, testpaths, revision);
let mut desc = make_test_description(config, test_name, &test_path, src_file, cfg);
let test_name = crate::make_test_name(&config, testpaths, revision);
let mut desc = make_test_description(&config, test_name, &test_path, src_file, cfg);
// Ignore tests that already run and are up to date with respect to inputs.
if !config.force_rerun {
desc.ignore |= is_up_to_date(
config,
&config,
testpaths,
&early_props,
revision.map(|s| s.as_str()),
inputs,
);
}
test::TestDescAndFn { desc, testfn: make_test_closure(config, testpaths, revision) }
test::TestDescAndFn {
desc,
testfn: make_test_closure(config.clone(), testpaths, revision),
}
})
.collect()
}
@ -869,7 +881,7 @@ fn make_test_name(
}
fn make_test_closure(
config: &Config,
config: Arc<Config>,
testpaths: &TestPaths,
revision: Option<&String>,
) -> test::TestFn {

View File

@ -30,6 +30,7 @@ use std::iter;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::str;
use std::sync::Arc;
use glob::glob;
use once_cell::sync::Lazy;
@ -96,7 +97,7 @@ pub fn get_lib_name(lib: &str, dylib: bool) -> String {
}
}
pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
match &*config.target {
"arm-linux-androideabi"
| "armv7-linux-androideabi"