diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 38a434b60..049b3e00e 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -1,7 +1,9 @@ use std::fs::{self, File, OpenOptions}; use std::io::prelude::*; use std::net::TcpListener; +use std::path::PathBuf; use std::thread; +use std::time::SystemTime; use crate::support::paths::CargoPathExt; use crate::support::registry::Package; @@ -1178,6 +1180,83 @@ fn changing_rustflags_is_cached() { .run(); } +fn simple_deps_cleaner(mut dir: PathBuf, timestamp: filetime::FileTime) { + // Cargo is experimenting with letting outside projects develop some + // limited forms of GC for target_dir. This is one of the forms. + // Specifically, Cargo is updating the mtime of files in + // target/profile/deps each time it uses the file. + // So a cleaner can remove files older then a time stamp without + // effecting any builds that happened since that time stamp. + let mut cleand = false; + dir.push("deps"); + for dep in fs::read_dir(&dir).unwrap() { + let dep = dep.unwrap(); + if filetime::FileTime::from_last_modification_time(&dep.metadata().unwrap()) <= timestamp { + fs::remove_file(dep.path()).unwrap(); + cleand = true; + } + } + assert!( + cleand, + "called simple_deps_cleaner, but there was nothing to remove" + ); +} + +#[test] +fn simple_deps_cleaner_dose_not_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .env("RUSTFLAGS", "-C target-cpu=native") + .with_stderr( + "\ +[COMPILING] bar v0.0.1 ([..]) +[COMPILING] foo v0.0.1 ([..]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", + ) + .run(); + if is_coarse_mtime() { + sleep_ms(1000); + } + let timestamp = filetime::FileTime::from_system_time(SystemTime::now()); + // This dose not make new files, but it dose update the mtime. + p.cargo("build") + .env("RUSTFLAGS", "-C target-cpu=native") + .with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + .run(); + simple_deps_cleaner(p.target_debug_dir(), timestamp); + // This should not recompile! + p.cargo("build") + .env("RUSTFLAGS", "-C target-cpu=native") + .with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") + .run(); + // But this should be cleaned and so need a rebuild + p.cargo("build") + .with_stderr( + "\ +[COMPILING] bar v0.0.1 ([..]) +[COMPILING] foo v0.0.1 ([..]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", + ) + .run(); +} + #[test] fn reuse_panic_build_dep_test() { let p = project()