| use std::fmt::{self, Write}; |
| |
| use crate::support::install::exe; |
| use crate::support::paths::CargoPathExt; |
| use crate::support::registry::Package; |
| use crate::support::{basic_manifest, project}; |
| |
| #[cargo_test] |
| fn check_success() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::baz(); }", |
| ) |
| .build(); |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("check").run(); |
| } |
| |
| #[cargo_test] |
| fn check_fail() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::baz(42); }", |
| ) |
| .build(); |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr_contains("[..]this function takes 0 parameters but 1 parameter was supplied") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn custom_derive() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| r#" |
| #[macro_use] |
| extern crate bar; |
| |
| trait B { |
| fn b(&self); |
| } |
| |
| #[derive(B)] |
| struct A; |
| |
| fn main() { |
| let a = A; |
| a.b(); |
| } |
| "#, |
| ) |
| .build(); |
| let _bar = project() |
| .at("bar") |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "0.1.0" |
| authors = [] |
| [lib] |
| proc-macro = true |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| extern crate proc_macro; |
| |
| use proc_macro::TokenStream; |
| |
| #[proc_macro_derive(B)] |
| pub fn derive(_input: TokenStream) -> TokenStream { |
| format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap() |
| } |
| "#, |
| ) |
| .build(); |
| |
| foo.cargo("check").run(); |
| } |
| |
| #[cargo_test] |
| fn check_build() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::baz(); }", |
| ) |
| .build(); |
| |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("check").run(); |
| foo.cargo("build").run(); |
| } |
| |
| #[cargo_test] |
| fn build_check() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::baz(); }", |
| ) |
| .build(); |
| |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("build -v").run(); |
| foo.cargo("check -v").run(); |
| } |
| |
| // Checks that where a project has both a lib and a bin, the lib is only checked |
| // not built. |
| #[cargo_test] |
| fn issue_3418() { |
| let foo = project() |
| .file("src/lib.rs", "") |
| .file("src/main.rs", "fn main() {}") |
| .build(); |
| |
| foo.cargo("check -v") |
| .with_stderr_contains("[..] --emit=[..]metadata [..]") |
| .run(); |
| } |
| |
| // Some weirdness that seems to be caused by a crate being built as well as |
| // checked, but in this case with a proc macro too. |
| #[cargo_test] |
| fn issue_3419() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies] |
| rustc-serialize = "*" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| extern crate rustc_serialize; |
| |
| use rustc_serialize::Decodable; |
| |
| pub fn take<T: Decodable>() {} |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| r#" |
| extern crate rustc_serialize; |
| |
| extern crate foo; |
| |
| #[derive(RustcDecodable)] |
| pub struct Foo; |
| |
| fn main() { |
| foo::take::<Foo>(); |
| } |
| "#, |
| ) |
| .build(); |
| |
| Package::new("rustc-serialize", "1.0.0") |
| .file( |
| "src/lib.rs", |
| r#"pub trait Decodable: Sized { |
| fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>; |
| } |
| pub trait Decoder { |
| type Error; |
| fn read_struct<T, F>(&mut self, s_name: &str, len: usize, f: F) |
| -> Result<T, Self::Error> |
| where F: FnOnce(&mut Self) -> Result<T, Self::Error>; |
| } "#, |
| ) |
| .publish(); |
| |
| p.cargo("check").run(); |
| } |
| |
| // Check on a dylib should have a different metadata hash than build. |
| #[cargo_test] |
| fn dylib_check_preserves_build_cache() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| authors = [] |
| |
| [lib] |
| crate-type = ["dylib"] |
| |
| [dependencies] |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("build") |
| .with_stderr( |
| "\ |
| [..]Compiling foo v0.1.0 ([..]) |
| [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] |
| ", |
| ) |
| .run(); |
| |
| p.cargo("check").run(); |
| |
| p.cargo("build") |
| .with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]") |
| .run(); |
| } |
| |
| // test `cargo rustc --profile check` |
| #[cargo_test] |
| fn rustc_check() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::baz(); }", |
| ) |
| .build(); |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("rustc --profile check -- --emit=metadata").run(); |
| } |
| |
| #[cargo_test] |
| fn rustc_check_err() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "../bar" |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| "extern crate bar; fn main() { ::bar::qux(); }", |
| ) |
| .build(); |
| let _bar = project() |
| .at("bar") |
| .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| foo.cargo("rustc --profile check -- --emit=metadata") |
| .with_status(101) |
| .with_stderr_contains("[CHECKING] bar [..]") |
| .with_stderr_contains("[CHECKING] foo [..]") |
| .with_stderr_contains("[..]cannot find function `qux` in module `bar`") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn check_all() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [workspace] |
| [dependencies] |
| b = { path = "b" } |
| "#, |
| ) |
| .file("src/main.rs", "fn main() {}") |
| .file("examples/a.rs", "fn main() {}") |
| .file("tests/a.rs", "") |
| .file("src/lib.rs", "") |
| .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) |
| .file("b/src/main.rs", "fn main() {}") |
| .file("b/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check --all -v") |
| .with_stderr_contains("[..] --crate-name foo src/lib.rs [..]") |
| .with_stderr_contains("[..] --crate-name foo src/main.rs [..]") |
| .with_stderr_contains("[..] --crate-name b b/src/lib.rs [..]") |
| .with_stderr_contains("[..] --crate-name b b/src/main.rs [..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn check_virtual_all_implied() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["bar", "baz"] |
| "#, |
| ) |
| .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) |
| .file("bar/src/lib.rs", "pub fn bar() {}") |
| .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) |
| .file("baz/src/lib.rs", "pub fn baz() {}") |
| .build(); |
| |
| p.cargo("check -v") |
| .with_stderr_contains("[..] --crate-name bar bar/src/lib.rs [..]") |
| .with_stderr_contains("[..] --crate-name baz baz/src/lib.rs [..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn exclude_warns_on_non_existing_package() { |
| let p = project().file("src/lib.rs", "").build(); |
| p.cargo("check --all --exclude bar") |
| .with_stdout("") |
| .with_stderr( |
| r#"[WARNING] excluded package(s) bar not found in workspace `[CWD]` |
| [CHECKING] foo v0.0.1 ([CWD]) |
| [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] |
| "#, |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn targets_selected_default() { |
| let foo = project() |
| .file("src/main.rs", "fn main() {}") |
| .file("src/lib.rs", "pub fn smth() {}") |
| .file("examples/example1.rs", "fn main() {}") |
| .file("tests/test2.rs", "#[test] fn t() {}") |
| .file("benches/bench3.rs", "") |
| .build(); |
| |
| foo.cargo("check -v") |
| .with_stderr_contains("[..] --crate-name foo src/lib.rs [..]") |
| .with_stderr_contains("[..] --crate-name foo src/main.rs [..]") |
| .with_stderr_does_not_contain("[..] --crate-name example1 examples/example1.rs [..]") |
| .with_stderr_does_not_contain("[..] --crate-name test2 tests/test2.rs [..]") |
| .with_stderr_does_not_contain("[..] --crate-name bench3 benches/bench3.rs [..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn targets_selected_all() { |
| let foo = project() |
| .file("src/main.rs", "fn main() {}") |
| .file("src/lib.rs", "pub fn smth() {}") |
| .file("examples/example1.rs", "fn main() {}") |
| .file("tests/test2.rs", "#[test] fn t() {}") |
| .file("benches/bench3.rs", "") |
| .build(); |
| |
| foo.cargo("check --all-targets -v") |
| .with_stderr_contains("[..] --crate-name foo src/lib.rs [..]") |
| .with_stderr_contains("[..] --crate-name foo src/main.rs [..]") |
| .with_stderr_contains("[..] --crate-name example1 examples/example1.rs [..]") |
| .with_stderr_contains("[..] --crate-name test2 tests/test2.rs [..]") |
| .with_stderr_contains("[..] --crate-name bench3 benches/bench3.rs [..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn check_unit_test_profile() { |
| let foo = project() |
| .file( |
| "src/lib.rs", |
| r#" |
| #[cfg(test)] |
| mod tests { |
| #[test] |
| fn it_works() { |
| badtext |
| } |
| } |
| "#, |
| ) |
| .build(); |
| |
| foo.cargo("check").run(); |
| foo.cargo("check --profile test") |
| .with_status(101) |
| .with_stderr_contains("[..]badtext[..]") |
| .run(); |
| } |
| |
| // Verify what is checked with various command-line filters. |
| #[cargo_test] |
| fn check_filters() { |
| let p = project() |
| .file( |
| "src/lib.rs", |
| r#" |
| fn unused_normal_lib() {} |
| #[cfg(test)] |
| mod tests { |
| fn unused_unit_lib() {} |
| } |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| r#" |
| fn main() {} |
| fn unused_normal_bin() {} |
| #[cfg(test)] |
| mod tests { |
| fn unused_unit_bin() {} |
| } |
| "#, |
| ) |
| .file( |
| "tests/t1.rs", |
| r#" |
| fn unused_normal_t1() {} |
| #[cfg(test)] |
| mod tests { |
| fn unused_unit_t1() {} |
| } |
| "#, |
| ) |
| .file( |
| "examples/ex1.rs", |
| r#" |
| fn main() {} |
| fn unused_normal_ex1() {} |
| #[cfg(test)] |
| mod tests { |
| fn unused_unit_ex1() {} |
| } |
| "#, |
| ) |
| .file( |
| "benches/b1.rs", |
| r#" |
| fn unused_normal_b1() {} |
| #[cfg(test)] |
| mod tests { |
| fn unused_unit_b1() {} |
| } |
| "#, |
| ) |
| .build(); |
| |
| p.cargo("check") |
| .with_stderr_contains("[..]unused_normal_lib[..]") |
| .with_stderr_contains("[..]unused_normal_bin[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_t1[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_b1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_[..]") |
| .run(); |
| p.root().join("target").rm_rf(); |
| p.cargo("check --tests -v") |
| .with_stderr_contains("[..] --crate-name foo src/lib.rs [..] --test [..]") |
| .with_stderr_contains("[..] --crate-name foo src/lib.rs [..] --crate-type lib [..]") |
| .with_stderr_contains("[..] --crate-name foo src/main.rs [..] --test [..]") |
| .with_stderr_contains("[..]unused_unit_lib[..]") |
| .with_stderr_contains("[..]unused_unit_bin[..]") |
| .with_stderr_contains("[..]unused_normal_lib[..]") |
| .with_stderr_contains("[..]unused_normal_bin[..]") |
| .with_stderr_contains("[..]unused_unit_t1[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_b1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_b1[..]") |
| .with_stderr_does_not_contain("[..]--crate-type bin[..]") |
| .run(); |
| p.root().join("target").rm_rf(); |
| p.cargo("check --test t1 -v") |
| .with_stderr_contains("[..]unused_normal_lib[..]") |
| .with_stderr_contains("[..]unused_unit_t1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_lib[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_bin[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_bin[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") |
| .with_stderr_does_not_contain("[..]unused_normal_b1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_b1[..]") |
| .run(); |
| p.root().join("target").rm_rf(); |
| p.cargo("check --all-targets -v") |
| .with_stderr_contains("[..]unused_normal_lib[..]") |
| .with_stderr_contains("[..]unused_normal_bin[..]") |
| .with_stderr_contains("[..]unused_normal_t1[..]") |
| .with_stderr_contains("[..]unused_normal_ex1[..]") |
| .with_stderr_contains("[..]unused_normal_b1[..]") |
| .with_stderr_contains("[..]unused_unit_b1[..]") |
| .with_stderr_contains("[..]unused_unit_t1[..]") |
| .with_stderr_contains("[..]unused_unit_lib[..]") |
| .with_stderr_contains("[..]unused_unit_bin[..]") |
| .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn check_artifacts() { |
| // Verify which artifacts are created when running check (#4059). |
| let p = project() |
| .file("src/lib.rs", "") |
| .file("src/main.rs", "fn main() {}") |
| .file("tests/t1.rs", "") |
| .file("examples/ex1.rs", "fn main() {}") |
| .file("benches/b1.rs", "") |
| .build(); |
| |
| p.cargo("check").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 2); |
| |
| p.root().join("target").rm_rf(); |
| p.cargo("check --lib").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); |
| |
| p.root().join("target").rm_rf(); |
| p.cargo("check --bin foo").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 2); |
| |
| p.root().join("target").rm_rf(); |
| p.cargo("check --test t1").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); |
| assert_eq!(p.glob("target/debug/t1-*").count(), 0); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); |
| assert_eq!(p.glob("target/debug/deps/libt1-*.rmeta").count(), 1); |
| |
| p.root().join("target").rm_rf(); |
| p.cargo("check --example ex1").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p |
| .root() |
| .join("target/debug/examples") |
| .join(exe("ex1")) |
| .is_file()); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); |
| assert_eq!(p.glob("target/debug/examples/libex1-*.rmeta").count(), 1); |
| |
| p.root().join("target").rm_rf(); |
| p.cargo("check --bench b1").run(); |
| assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); |
| assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); |
| assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); |
| assert_eq!(p.glob("target/debug/b1-*").count(), 0); |
| assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); |
| assert_eq!(p.glob("target/debug/deps/libb1-*.rmeta").count(), 1); |
| } |
| |
| #[cargo_test] |
| fn short_message_format() { |
| let foo = project() |
| .file("src/lib.rs", "fn foo() { let _x: bool = 'a'; }") |
| .build(); |
| foo.cargo("check --message-format=short") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| src/lib.rs:1:27: error[E0308]: mismatched types |
| error: aborting due to previous error |
| error: Could not compile `foo`. |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn proc_macro() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "demo" |
| version = "0.0.1" |
| |
| [lib] |
| proc-macro = true |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| extern crate proc_macro; |
| |
| use proc_macro::TokenStream; |
| |
| #[proc_macro_derive(Foo)] |
| pub fn demo(_input: TokenStream) -> TokenStream { |
| "".parse().unwrap() |
| } |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| r#" |
| #[macro_use] |
| extern crate demo; |
| |
| #[derive(Foo)] |
| struct A; |
| |
| fn main() {} |
| "#, |
| ) |
| .build(); |
| p.cargo("check -v").env("CARGO_LOG", "cargo=trace").run(); |
| } |
| |
| #[cargo_test] |
| fn does_not_use_empty_rustc_wrapper() { |
| let p = project().file("src/lib.rs", "").build(); |
| p.cargo("check").env("RUSTC_WRAPPER", "").run(); |
| } |
| |
| #[cargo_test] |
| fn error_from_deep_recursion() -> Result<(), fmt::Error> { |
| let mut big_macro = String::new(); |
| writeln!(big_macro, "macro_rules! m {{")?; |
| for i in 0..130 { |
| writeln!(big_macro, "({}) => {{ m!({}); }};", i, i + 1)?; |
| } |
| writeln!(big_macro, "}}")?; |
| writeln!(big_macro, "m!(0);")?; |
| |
| let p = project().file("src/lib.rs", &big_macro).build(); |
| p.cargo("check --message-format=json") |
| .with_status(101) |
| .with_stdout_contains( |
| "[..]\"message\":\"recursion limit reached while expanding the macro `m`\"[..]", |
| ) |
| .run(); |
| |
| Ok(()) |
| } |