| //! Tests for `[lints]` |
| |
| use cargo_test_support::project; |
| use cargo_test_support::registry::Package; |
| |
| #[cargo_test] |
| fn dependency_warning_ignored() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies] |
| bar.path = "../bar" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| let _bar = project() |
| .at("bar") |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rust] |
| unsafe_code = "forbid" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_stderr( |
| "\ |
| [CHECKING] [..] |
| [CHECKING] [..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn malformed_on_stable() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| lints = 20 |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [ERROR] invalid type: integer `20`, expected a lints table |
| --> Cargo.toml:2:25 |
| | |
| 2 | lints = 20 |
| | ^^ |
| | |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn fail_on_invalid_tool() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [workspace.lints.super-awesome-linter] |
| unsafe_code = "forbid" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [..] |
| |
| Caused by: |
| unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn invalid_type_in_lint_value() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [workspace.lints.rust] |
| rust-2018-idioms = -1 |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [ERROR] invalid type: integer `-1`, expected a string or map |
| --> Cargo.toml:7:36 |
| | |
| 7 | rust-2018-idioms = -1 |
| | ^^ |
| | |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn warn_on_unused_key() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [workspace.lints.rust] |
| rust-2018-idioms = { level = "allow", unused = true } |
| [lints.rust] |
| rust-2018-idioms = { level = "allow", unused = true } |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_stderr( |
| "\ |
| [WARNING] [CWD]/Cargo.toml: unused manifest key: lints.rust.rust-2018-idioms.unused |
| [WARNING] [CWD]/Cargo.toml: unused manifest key: workspace.lints.rust.rust-2018-idioms.unused |
| [CHECKING] foo v0.0.1 ([CWD]) |
| [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]s |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn fail_on_tool_injection() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [workspace.lints.rust] |
| "clippy::cyclomatic_complexity" = "warn" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [..] |
| |
| Caused by: |
| `lints.rust.clippy::cyclomatic_complexity` is not valid lint name; try `lints.clippy.cyclomatic_complexity` |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn fail_on_redundant_tool() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [workspace.lints.rust] |
| "rust::unsafe_code" = "forbid" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [..] |
| |
| Caused by: |
| `lints.rust.rust::unsafe_code` is not valid lint name; try `lints.rust.unsafe_code` |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn fail_on_conflicting_tool() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [workspace.lints.rust] |
| "super-awesome-tool::unsafe_code" = "forbid" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [..] |
| |
| Caused by: |
| `lints.rust.super-awesome-tool::unsafe_code` is not a valid lint name |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn package_lint_deny() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| error: usage of an `unsafe` block |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn workspace_cant_be_false() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints] |
| workspace = false |
| |
| [workspace.lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| error: `workspace` cannot be false |
| --> Cargo.toml:8:29 |
| | |
| 8 | workspace = false |
| | ^^^^^ |
| | |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn workspace_lint_deny() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints] |
| workspace = true |
| |
| [workspace.lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| error: usage of an `unsafe` block |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn workspace_and_package_lints() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints] |
| workspace = true |
| [lints.rust] |
| "unsafe_code" = "allow" |
| |
| [workspace.lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr( |
| "\ |
| [ERROR] failed to parse manifest at `[CWD]/Cargo.toml` |
| |
| Caused by: |
| cannot override `workspace.lints` in `lints`, either remove the overrides or `lints.workspace = true` and manually specify the lints |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn attribute_has_precedence() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| #![allow(unsafe_code)] |
| |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .arg("-v") // Show order of rustflags on failure |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn rustflags_has_precedence() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .arg("-v") // Show order of rustflags on failure |
| .env("RUSTFLAGS", "-Aunsafe_code") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn profile_rustflags_has_precedence() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| cargo-features = ["profile-rustflags"] |
| |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [lints.rust] |
| "unsafe_code" = "deny" |
| |
| [profile.dev] |
| rustflags = ["-A", "unsafe_code"] |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .arg("-v") // Show order of rustflags on failure |
| .masquerade_as_nightly_cargo(&["profile-rustflags"]) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn build_rustflags_has_precedence() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [lints.rust] |
| "unsafe_code" = "deny" |
| "#, |
| ) |
| .file( |
| ".cargo/config.toml", |
| r#" |
| [build] |
| rustflags = ["-A", "unsafe_code"] |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| pub fn foo(num: i32) -> u32 { |
| unsafe { std::mem::transmute(num) } |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .arg("-v") // Show order of rustflags on failure |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn without_priority() { |
| Package::new("reg-dep", "1.0.0").publish(); |
| |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2018" |
| authors = [] |
| |
| [dependencies] |
| reg-dep = "1.0.0" |
| |
| [lints.rust] |
| "rust-2018-idioms" = "deny" |
| "unused-extern-crates" = "allow" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| extern crate reg_dep; |
| |
| pub fn foo() -> u32 { |
| 2 |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| error: unused extern crate |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn with_priority() { |
| Package::new("reg-dep", "1.0.0").publish(); |
| |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| edition = "2018" |
| authors = [] |
| |
| [dependencies] |
| reg-dep = "1.0.0" |
| |
| [lints.rust] |
| "rust-2018-idioms" = { level = "deny", priority = -1 } |
| "unused-extern-crates" = "allow" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| extern crate reg_dep; |
| |
| pub fn foo() -> u32 { |
| 2 |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("check").run(); |
| } |
| |
| #[cargo_test] |
| fn rustdoc_lint() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rustdoc] |
| broken_intra_doc_links = "deny" |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| " |
| /// [`bar`] doesn't exist |
| pub fn foo() -> u32 { |
| } |
| ", |
| ) |
| .build(); |
| |
| foo.cargo("doc") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| error: unresolved link to `bar` |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn doctest_respects_lints() { |
| let foo = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lints.rust] |
| confusable-idents = 'allow' |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| /// Test |
| /// |
| /// [`Foo`] |
| /// |
| /// ``` |
| /// let s = "rust"; |
| /// let s_s = "rust2"; |
| /// ``` |
| pub fn f() {} |
| pub const Ě: i32 = 1; |
| pub const Ĕ: i32 = 2; |
| "#, |
| ) |
| .build(); |
| |
| foo.cargo("check") |
| .with_stderr( |
| "\ |
| [CHECKING] foo v0.0.1 ([CWD]) |
| [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]s |
| ", |
| ) |
| .run(); |
| |
| foo.cargo("test --doc") |
| .with_stderr( |
| "\ |
| [COMPILING] foo v0.0.1 ([CWD]) |
| [FINISHED] test [unoptimized + debuginfo] target(s) in [..]s |
| [DOCTEST] foo |
| ", |
| ) |
| .run(); |
| } |