cargo/tests/testsuite/clean.rs

630 lines
16 KiB
Rust
Raw Normal View History

2019-11-25 02:42:45 +00:00
//! Tests for the `cargo clean` command.
use cargo_test_support::registry::Package;
use cargo_test_support::{
2022-10-30 04:28:49 +00:00
basic_bin_manifest, basic_lib_manifest, basic_manifest, git, main_file, project, project_in,
rustc_host,
};
use glob::GlobError;
2020-05-05 21:22:06 +00:00
use std::env;
use std::path::{Path, PathBuf};
2014-07-07 08:50:05 +00:00
#[cargo_test]
fn cargo_clean_simple() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
2014-07-07 08:50:05 +00:00
p.cargo("build").run();
2018-08-29 05:53:01 +00:00
assert!(p.build_dir().is_dir());
2014-07-07 08:50:05 +00:00
p.cargo("clean").run();
2018-08-29 05:53:01 +00:00
assert!(!p.build_dir().is_dir());
}
#[cargo_test]
fn different_dir() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.file("src/bar/a.rs", "")
.build();
p.cargo("build").run();
2018-08-29 05:53:01 +00:00
assert!(p.build_dir().is_dir());
2019-04-05 19:55:01 +00:00
p.cargo("clean").cwd("src").with_stdout("").run();
2018-08-29 05:53:01 +00:00
assert!(!p.build_dir().is_dir());
}
#[cargo_test]
fn clean_multiple_packages() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies.d1]
path = "d1"
[dependencies.d2]
path = "d2"
2020-09-27 00:59:58 +00:00
[[bin]]
name = "foo"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
2018-07-24 22:35:01 +00:00
.file("d1/Cargo.toml", &basic_bin_manifest("d1"))
.file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
2018-07-24 22:35:01 +00:00
.file("d2/Cargo.toml", &basic_bin_manifest("d2"))
.file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
.build();
p.cargo("build -p d1 -p d2 -p foo").run();
2018-03-14 15:17:44 +00:00
let d1_path = &p
.build_dir()
2018-03-14 15:17:44 +00:00
.join("debug")
.join(format!("d1{}", env::consts::EXE_SUFFIX));
let d2_path = &p
.build_dir()
2018-03-14 15:17:44 +00:00
.join("debug")
.join(format!("d2{}", env::consts::EXE_SUFFIX));
2015-09-24 21:47:50 +00:00
2018-08-29 06:11:10 +00:00
assert!(p.bin("foo").is_file());
assert!(d1_path.is_file());
assert!(d2_path.is_file());
p.cargo("clean -p d1 -p d2")
.cwd("src")
.with_stdout("")
.run();
2018-08-29 06:11:10 +00:00
assert!(p.bin("foo").is_file());
assert!(!d1_path.is_file());
assert!(!d2_path.is_file());
}
#[cargo_test]
fn clean_multiple_packages_in_glob_char_path() {
let p = project_in("[d1]")
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
let foo_path = &p.build_dir().join("debug").join("deps");
2022-10-30 04:28:49 +00:00
#[cfg(not(target_env = "msvc"))]
let file_glob = "foo-*";
#[cfg(target_env = "msvc")]
let file_glob = "foo.pdb";
// Assert that build artifacts are produced
p.cargo("build").run();
2022-10-30 04:28:49 +00:00
assert_ne!(get_build_artifacts(foo_path, file_glob).len(), 0);
// Assert that build artifacts are destroyed
p.cargo("clean -p foo").run();
2022-10-30 04:28:49 +00:00
assert_eq!(get_build_artifacts(foo_path, file_glob).len(), 0);
}
2022-10-30 04:28:49 +00:00
#[cargo_test]
fn clean_p_only_cleans_specified_package() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = [
"foo",
"foo_core",
]
"#,
)
.file("foo/Cargo.toml", &basic_lib_manifest("foo"))
.file("foo/src/lib.rs", "//! foo")
.file("foo_core/Cargo.toml", &basic_lib_manifest("foo_core"))
.file("foo_core/src/lib.rs", "//! foo_core")
.build();
2022-10-30 04:28:49 +00:00
let deps_path = &p.build_dir().join("debug").join("deps");
let foo_glob = "foo-*";
let foo_core_glob = "foo_core-*";
2022-10-30 04:28:49 +00:00
p.cargo("build -p foo -p foo_core").run();
// Artifacts present for both after building
assert!(!get_build_artifacts(deps_path, foo_glob).is_empty());
let num_foo_core_artifacts = get_build_artifacts(deps_path, foo_core_glob).len();
assert_ne!(num_foo_core_artifacts, 0);
p.cargo("clean -p foo").run();
// Cleaning `foo` leaves artifacts for `foo_core`
assert!(get_build_artifacts(deps_path, foo_glob).is_empty());
assert_eq!(
num_foo_core_artifacts,
get_build_artifacts(deps_path, foo_core_glob).len()
);
}
fn get_build_artifacts(path: &PathBuf, file_glob: &str) -> Vec<Result<PathBuf, GlobError>> {
let pattern = path.to_str().expect("expected utf-8 path");
let pattern = glob::Pattern::escape(pattern);
2022-10-30 04:28:49 +00:00
let path = PathBuf::from(pattern).join(file_glob);
let path = path.to_str().expect("expected utf-8 path");
glob::glob(path)
.expect("expected glob to run")
.into_iter()
.collect::<Vec<Result<PathBuf, GlobError>>>()
}
#[cargo_test]
fn clean_release() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
2018-07-24 22:35:01 +00:00
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file("a/src/lib.rs", "")
.build();
p.cargo("build --release").run();
p.cargo("clean -p foo").run();
p.cargo("build --release").with_stdout("").run();
p.cargo("clean -p foo --release").run();
p.cargo("build --release")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-11-26 14:40:50 +00:00
2018-11-26 15:12:11 +00:00
p.cargo("build").run();
2018-11-26 14:40:50 +00:00
p.cargo("clean").arg("--release").run();
2018-11-26 15:12:11 +00:00
assert!(p.build_dir().is_dir());
assert!(p.build_dir().join("debug").is_dir());
2018-11-26 14:40:50 +00:00
assert!(!p.build_dir().join("release").is_dir());
}
#[cargo_test]
2018-05-01 15:33:10 +00:00
fn clean_doc() {
let p = project()
2018-05-01 15:33:10 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
2018-07-24 22:35:01 +00:00
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
2018-05-01 15:33:10 +00:00
.file("a/src/lib.rs", "")
.build();
p.cargo("doc").run();
2018-05-01 15:33:10 +00:00
let doc_path = &p.build_dir().join("doc");
2018-08-29 05:53:01 +00:00
assert!(doc_path.is_dir());
2018-05-01 15:33:10 +00:00
p.cargo("clean --doc").run();
2018-05-01 15:33:10 +00:00
2018-08-29 05:53:01 +00:00
assert!(!doc_path.is_dir());
assert!(p.build_dir().is_dir());
2018-05-01 15:33:10 +00:00
}
#[cargo_test]
fn build_script() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
build = "build.rs"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
2018-03-14 15:17:44 +00:00
.file(
"build.rs",
r#"
2020-09-27 00:59:58 +00:00
use std::path::PathBuf;
use std::env;
fn main() {
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
if env::var("FIRST").is_ok() {
std::fs::File::create(out.join("out")).unwrap();
} else {
assert!(!out.join("out").exists());
}
}
2020-09-27 00:59:58 +00:00
"#,
2018-12-08 11:19:47 +00:00
)
.file("a/src/lib.rs", "")
.build();
p.cargo("build").env("FIRST", "1").run();
p.cargo("clean -p foo").run();
p.cargo("build -v")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[COMPILING] foo v0.0.1 ([..])
2016-11-29 23:11:58 +00:00
[RUNNING] `rustc [..] build.rs [..]`
2016-11-04 07:37:02 +00:00
[RUNNING] `[..]build-script-build`
2018-08-02 09:18:48 +00:00
[RUNNING] `rustc [..] src/main.rs [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn clean_git() {
let git = git::new("dep", |project| {
2018-03-14 15:17:44 +00:00
project
2018-07-24 22:35:01 +00:00
.file("Cargo.toml", &basic_manifest("dep", "0.5.0"))
2018-03-14 15:17:44 +00:00
.file("src/lib.rs", "")
});
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
dep = {{ git = '{}' }}
"#,
2018-03-14 15:17:44 +00:00
git.url()
),
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build").run();
p.cargo("clean -p dep").with_stdout("").run();
p.cargo("build").run();
}
#[cargo_test]
fn registry() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
.build();
Package::new("bar", "0.1.0").publish();
p.cargo("build").run();
p.cargo("clean -p bar").with_stdout("").run();
p.cargo("build").run();
}
#[cargo_test]
2018-03-14 15:17:44 +00:00
fn clean_verbose() {
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/main.rs", "fn main() {}")
2018-03-14 15:17:44 +00:00
.build();
Package::new("bar", "0.1.0").publish();
p.cargo("build").run();
p.cargo("clean -p bar --verbose")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[REMOVING] [..]
[REMOVING] [..]
[REMOVING] [..]
2020-05-05 21:22:06 +00:00
[REMOVING] [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("build").run();
}
#[cargo_test]
fn clean_remove_rlib_rmeta() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
assert!(p.target_debug_dir().join("libfoo.rlib").exists());
let rmeta = p.glob("target/debug/deps/*.rmeta").next().unwrap().unwrap();
assert!(rmeta.exists());
p.cargo("clean -p foo").run();
assert!(!p.target_debug_dir().join("libfoo.rlib").exists());
assert!(!rmeta.exists());
}
2020-05-05 21:22:06 +00:00
#[cargo_test]
fn package_cleans_all_the_things() {
// -p cleans everything
// Use dashes everywhere to make sure dash/underscore stuff is handled.
for crate_type in &["rlib", "dylib", "cdylib", "staticlib", "proc-macro"] {
// Try each crate type individually since the behavior changes when
// they are combined.
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo-bar"
version = "0.1.0"
[lib]
crate-type = ["{}"]
"#,
crate_type
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("clean -p foo-bar").run();
assert_all_clean(&p.build_dir());
}
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo-bar"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["rlib", "dylib", "staticlib"]
[[example]]
name = "foo-ex-rlib"
crate-type = ["rlib"]
test = true
[[example]]
name = "foo-ex-cdylib"
crate-type = ["cdylib"]
test = true
[[example]]
name = "foo-ex-bin"
test = true
"#,
)
.file("src/lib.rs", "")
2021-11-29 18:04:15 +00:00
.file("src/lib/some-main.rs", "fn main() {}")
2020-05-05 21:22:06 +00:00
.file("src/bin/other-main.rs", "fn main() {}")
.file("examples/foo-ex-rlib.rs", "")
.file("examples/foo-ex-cdylib.rs", "")
.file("examples/foo-ex-bin.rs", "fn main() {}")
.file("tests/foo-test.rs", "")
.file("benches/foo-bench.rs", "")
.file("build.rs", "fn main() {}")
.build();
p.cargo("build --all-targets")
.env("CARGO_INCREMENTAL", "1")
.run();
p.cargo("test --all-targets")
.env("CARGO_INCREMENTAL", "1")
.run();
p.cargo("check --all-targets")
.env("CARGO_INCREMENTAL", "1")
.run();
p.cargo("clean -p foo-bar").run();
assert_all_clean(&p.build_dir());
// Try some targets.
p.cargo("build --all-targets --target")
.arg(rustc_host())
.run();
p.cargo("clean -p foo-bar --target").arg(rustc_host()).run();
assert_all_clean(&p.build_dir());
}
// Ensures that all files for the package have been deleted.
#[track_caller]
2020-05-05 21:22:06 +00:00
fn assert_all_clean(build_dir: &Path) {
let walker = walkdir::WalkDir::new(build_dir).into_iter();
for entry in walker.filter_entry(|e| {
let path = e.path();
// This is a known limitation, clean can't differentiate between
// the different build scripts from different packages.
!(path
.file_name()
.unwrap()
.to_str()
.unwrap()
.starts_with("build_script_build")
&& path
.parent()
.unwrap()
.file_name()
.unwrap()
.to_str()
.unwrap()
== "incremental")
}) {
let entry = entry.unwrap();
let path = entry.path();
if let ".rustc_info.json" | ".cargo-lock" | "CACHEDIR.TAG" =
path.file_name().unwrap().to_str().unwrap()
{
2020-05-05 21:22:06 +00:00
continue;
}
2022-01-13 21:36:24 +00:00
if path.is_symlink() || path.is_file() {
2020-05-05 21:22:06 +00:00
panic!("{:?} was not cleaned", path);
}
}
}
#[cargo_test]
fn clean_spec_multiple() {
// clean -p foo where foo matches multiple versions
Package::new("bar", "1.0.0").publish();
Package::new("bar", "2.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar1 = {version="1.0", package="bar"}
bar2 = {version="2.0", package="bar"}
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
2021-01-22 21:37:52 +00:00
// Check suggestion for bad pkgid.
p.cargo("clean -p baz")
.with_status(101)
.with_stderr(
"\
error: package ID specification `baz` did not match any packages
<tab>Did you mean `bar`?
",
)
.run();
2020-05-05 21:22:06 +00:00
p.cargo("clean -p bar:1.0.0")
.with_stderr(
"warning: version qualifier in `-p bar:1.0.0` is ignored, \
cleaning all versions of `bar` found",
)
.run();
let mut walker = walkdir::WalkDir::new(p.build_dir())
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| {
let n = e.file_name().to_str().unwrap();
n.starts_with("bar") || n.starts_with("libbar")
});
if let Some(e) = walker.next() {
panic!("{:?} was not cleaned", e.path());
}
}
#[cargo_test]
fn clean_spec_reserved() {
// Clean when a target (like a test) has a reserved name. In this case,
// make sure `clean -p` doesn't delete the reserved directory `build` when
// there is a test named `build`.
Package::new("bar", "1.0.0")
.file("src/lib.rs", "")
.file("build.rs", "fn main() {}")
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "1.0"
"#,
)
.file("src/lib.rs", "")
.file("tests/build.rs", "")
.build();
p.cargo("build --all-targets").run();
assert!(p.target_debug_dir().join("build").is_dir());
let build_test = p.glob("target/debug/deps/build-*").next().unwrap().unwrap();
assert!(build_test.exists());
// Tests are never "uplifted".
assert!(p.glob("target/debug/build-*").next().is_none());
p.cargo("clean -p foo").run();
// Should not delete this.
assert!(p.target_debug_dir().join("build").is_dir());
// This should not rebuild bar.
p.cargo("build -v --all-targets")
.with_stderr(
"\
[FRESH] bar v1.0.0
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc [..]
[RUNNING] `rustc [..]
[RUNNING] `rustc [..]
[FINISHED] [..]
",
)
.run();
}