Skip to content

Commit 8bd8465

Browse files
authored
Rollup merge of #66369 - tmiasko:compiletest-stamp, r=Mark-Simulacrum
compiletest: Obtain timestamps for common inputs only once Obtain timestamps for common inputs (e.g., libraries in run-lib path, or sources in `src/tool/compiletest/`) only once and reuse the result, instead of repeating the work for each test case.
2 parents 2d453b3 + 1ac470f commit 8bd8465

File tree

1 file changed

+90
-72
lines changed

1 file changed

+90
-72
lines changed

src/tools/compiletest/src/main.rs

+90-72
Original file line numberDiff line numberDiff line change
@@ -574,22 +574,59 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
574574

575575
pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
576576
debug!("making tests from {:?}", config.src_base.display());
577+
let inputs = common_inputs_stamp(config);
577578
let mut tests = Vec::new();
578579
collect_tests_from_dir(
579580
config,
580581
&config.src_base,
581582
&config.src_base,
582583
&PathBuf::new(),
584+
&inputs,
583585
&mut tests,
584586
).expect(&format!("Could not read tests from {}", config.src_base.display()));
585587
tests
586588
}
587589

590+
/// Returns a stamp constructed from input files common to all test cases.
591+
fn common_inputs_stamp(config: &Config) -> Stamp {
592+
let rust_src_dir = config
593+
.find_rust_src_root()
594+
.expect("Could not find Rust source root");
595+
596+
let mut stamp = Stamp::from_path(&config.rustc_path);
597+
598+
// Relevant pretty printer files
599+
let pretty_printer_files = [
600+
"src/etc/debugger_pretty_printers_common.py",
601+
"src/etc/gdb_load_rust_pretty_printers.py",
602+
"src/etc/gdb_rust_pretty_printing.py",
603+
"src/etc/lldb_batchmode.py",
604+
"src/etc/lldb_rust_formatters.py",
605+
];
606+
for file in &pretty_printer_files {
607+
let path = rust_src_dir.join(file);
608+
stamp.add_path(&path);
609+
}
610+
611+
stamp.add_dir(&config.run_lib_path);
612+
613+
if let Some(ref rustdoc_path) = config.rustdoc_path {
614+
stamp.add_path(&rustdoc_path);
615+
stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
616+
}
617+
618+
// Compiletest itself.
619+
stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
620+
621+
stamp
622+
}
623+
588624
fn collect_tests_from_dir(
589625
config: &Config,
590626
base: &Path,
591627
dir: &Path,
592628
relative_dir_path: &Path,
629+
inputs: &Stamp,
593630
tests: &mut Vec<test::TestDescAndFn>,
594631
) -> io::Result<()> {
595632
// Ignore directories that contain a file named `compiletest-ignore-dir`.
@@ -602,7 +639,7 @@ fn collect_tests_from_dir(
602639
file: dir.to_path_buf(),
603640
relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
604641
};
605-
tests.extend(make_test(config, &paths));
642+
tests.extend(make_test(config, &paths, inputs));
606643
return Ok(());
607644
}
608645

@@ -627,12 +664,14 @@ fn collect_tests_from_dir(
627664
file: file_path,
628665
relative_dir: relative_dir_path.to_path_buf(),
629666
};
630-
tests.extend(make_test(config, &paths))
667+
tests.extend(make_test(config, &paths, inputs))
631668
} else if file_path.is_dir() {
632669
let relative_file_path = relative_dir_path.join(file.file_name());
633670
if &file_name != "auxiliary" {
634671
debug!("found directory: {:?}", file_path.display());
635-
collect_tests_from_dir(config, base, &file_path, &relative_file_path, tests)?;
672+
collect_tests_from_dir(
673+
config, base, &file_path, &relative_file_path,
674+
inputs, tests)?;
636675
}
637676
} else {
638677
debug!("found other file/directory: {:?}", file_path.display());
@@ -655,7 +694,7 @@ pub fn is_test(file_name: &OsString) -> bool {
655694
!invalid_prefixes.iter().any(|p| file_name.starts_with(p))
656695
}
657696

658-
pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec<test::TestDescAndFn> {
697+
fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test::TestDescAndFn> {
659698
let early_props = if config.mode == Mode::RunMake {
660699
// Allow `ignore` directives to be in the Makefile.
661700
EarlyProps::from_file(config, &testpaths.file.join("Makefile"))
@@ -685,19 +724,21 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec<test::TestDescAn
685724
revisions
686725
.into_iter()
687726
.map(|revision| {
688-
// Debugging emscripten code doesn't make sense today
689727
let ignore = early_props.ignore == Ignore::Ignore
690-
|| !up_to_date(
691-
config,
692-
testpaths,
693-
&early_props,
694-
revision.map(|s| s.as_str()),
695-
)
728+
// Debugging emscripten code doesn't make sense today
696729
|| ((config.mode == DebugInfoGdbLldb || config.mode == DebugInfoCdb ||
697730
config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
698731
&& config.target.contains("emscripten"))
699732
|| (config.mode == DebugInfoGdb && !early_props.ignore.can_run_gdb())
700-
|| (config.mode == DebugInfoLldb && !early_props.ignore.can_run_lldb());
733+
|| (config.mode == DebugInfoLldb && !early_props.ignore.can_run_lldb())
734+
// Ignore tests that already run and are up to date with respect to inputs.
735+
|| is_up_to_date(
736+
config,
737+
testpaths,
738+
&early_props,
739+
revision.map(|s| s.as_str()),
740+
inputs,
741+
);
701742
test::TestDescAndFn {
702743
desc: test::TestDesc {
703744
name: make_test_name(config, testpaths, revision),
@@ -716,98 +757,75 @@ fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> Path
716757
output_base_dir(config, testpaths, revision).join("stamp")
717758
}
718759

719-
fn up_to_date(
760+
fn is_up_to_date(
720761
config: &Config,
721762
testpaths: &TestPaths,
722763
props: &EarlyProps,
723764
revision: Option<&str>,
765+
inputs: &Stamp,
724766
) -> bool {
725767
let stamp_name = stamp(config, testpaths, revision);
726768
// Check hash.
727769
let contents = match fs::read_to_string(&stamp_name) {
728770
Ok(f) => f,
729771
Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
730-
Err(_) => return true,
772+
Err(_) => return false,
731773
};
732774
let expected_hash = runtest::compute_stamp_hash(config);
733775
if contents != expected_hash {
734-
return true;
776+
return false;
735777
}
736778

737779
// Check timestamps.
738-
let rust_src_dir = config
739-
.find_rust_src_root()
740-
.expect("Could not find Rust source root");
741-
let stamp = Stamp::from_path(&stamp_name);
742-
let mut inputs = vec![Stamp::from_path(&testpaths.file), Stamp::from_path(&config.rustc_path)];
743-
inputs.extend(
744-
props
745-
.aux
746-
.iter()
747-
.map(|aux| {
748-
Stamp::from_path(&testpaths.file.parent().unwrap().join("auxiliary").join(aux))
749-
}),
750-
);
751-
// Relevant pretty printer files
752-
let pretty_printer_files = [
753-
"src/etc/debugger_pretty_printers_common.py",
754-
"src/etc/gdb_load_rust_pretty_printers.py",
755-
"src/etc/gdb_rust_pretty_printing.py",
756-
"src/etc/lldb_batchmode.py",
757-
"src/etc/lldb_rust_formatters.py",
758-
];
759-
inputs.extend(pretty_printer_files.iter().map(|pretty_printer_file| {
760-
Stamp::from_path(&rust_src_dir.join(pretty_printer_file))
761-
}));
762-
inputs.extend(Stamp::from_dir(&config.run_lib_path));
763-
if let Some(ref rustdoc_path) = config.rustdoc_path {
764-
inputs.push(Stamp::from_path(&rustdoc_path));
765-
inputs.push(Stamp::from_path(&rust_src_dir.join("src/etc/htmldocck.py")));
780+
let mut inputs = inputs.clone();
781+
inputs.add_path(&testpaths.file);
782+
783+
for aux in &props.aux {
784+
let path = testpaths.file.parent()
785+
.unwrap()
786+
.join("auxiliary")
787+
.join(aux);
788+
inputs.add_path(&path);
766789
}
767790

768791
// UI test files.
769-
inputs.extend(UI_EXTENSIONS.iter().map(|extension| {
792+
for extension in UI_EXTENSIONS {
770793
let path = &expected_output_path(testpaths, revision, &config.compare_mode, extension);
771-
Stamp::from_path(path)
772-
}));
773-
774-
// Compiletest itself.
775-
inputs.extend(Stamp::from_dir(&rust_src_dir.join("src/tools/compiletest/")));
794+
inputs.add_path(path);
795+
}
776796

777-
inputs.iter().any(|input| input > &stamp)
797+
inputs < Stamp::from_path(&stamp_name)
778798
}
779799

780-
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
800+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
781801
struct Stamp {
782802
time: SystemTime,
783-
file: PathBuf,
784803
}
785804

786805
impl Stamp {
787-
fn from_path(p: &Path) -> Self {
788-
let time = fs::metadata(p)
806+
fn from_path(path: &Path) -> Self {
807+
let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
808+
stamp.add_path(path);
809+
stamp
810+
}
811+
812+
fn add_path(&mut self, path: &Path) {
813+
let modified = fs::metadata(path)
789814
.and_then(|metadata| metadata.modified())
790815
.unwrap_or(SystemTime::UNIX_EPOCH);
791-
792-
Stamp {
793-
time,
794-
file: p.into(),
795-
}
816+
self.time = self.time.max(modified);
796817
}
797818

798-
fn from_dir(path: &Path) -> impl Iterator<Item = Stamp> {
799-
WalkDir::new(path)
800-
.into_iter()
801-
.map(|entry| entry.unwrap())
802-
.filter(|entry| entry.file_type().is_file())
803-
.map(|entry| {
804-
let time = (|| -> io::Result<_> { entry.metadata()?.modified() })();
805-
806-
Stamp {
807-
time: time.unwrap_or(SystemTime::UNIX_EPOCH),
808-
file: entry.path().into(),
809-
}
810-
})
819+
fn add_dir(&mut self, path: &Path) {
820+
for entry in WalkDir::new(path) {
821+
let entry = entry.unwrap();
822+
if entry.file_type().is_file() {
823+
let modified = entry.metadata().ok()
824+
.and_then(|metadata| metadata.modified().ok())
825+
.unwrap_or(SystemTime::UNIX_EPOCH);
826+
self.time = self.time.max(modified);
827+
}
828+
}
811829
}
812830
}
813831

0 commit comments

Comments
 (0)