//! Tests for inheriting Cargo.toml fields with field.workspace = true use cargo_test_support::prelude::*; use cargo_test_support::registry::{Dependency, Package, RegistryBuilder}; use cargo_test_support::{ basic_lib_manifest, basic_manifest, git, paths, project, publish, registry, str, }; #[cargo_test] fn permit_additional_workspace_fields() { let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.package] version = "1.2.3" authors = ["Rustaceans"] description = "This is a crate" documentation = "https://www.rust-lang.org/learn" readme = "README.md" homepage = "https://www.rust-lang.org" repository = "https://github.com/example/example" license = "MIT" license-file = "LICENSE" keywords = ["cli"] categories = ["development-tools"] publish = false edition = "2018" rust-version = "1.60" exclude = ["foo.txt"] include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] [workspace.dependencies] dep = "0.1" "#, ) .file( "bar/Cargo.toml", r#" [package] name = "bar" version = "0.1.0" edition = "2015" authors = [] workspace = ".." "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") // Should not warn about unused fields. .with_stderr_data(str![[r#" [CHECKING] bar v0.1.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); p.cargo("check").run(); let lockfile = p.read_lockfile(); assert!(!lockfile.contains("dep")); } #[cargo_test] fn deny_optional_dependencies() { let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.dependencies] dep1 = { version = "0.1", optional = true } "#, ) .file("src/main.rs", "fn main() {}") .file( "bar/Cargo.toml", r#" [package] name = "bar" version = "0.1.0" edition = "2015" authors = [] workspace = ".." "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: dep1 is optional, but workspace dependencies cannot be optional "#]]) .run(); } #[cargo_test] fn inherit_own_workspace_fields() { let registry = RegistryBuilder::new().http_api().http_index().build(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [package] name = "foo" version.workspace = true authors.workspace = true description.workspace = true documentation.workspace = true homepage.workspace = true repository.workspace = true license.workspace = true keywords.workspace = true categories.workspace = true publish.workspace = true edition.workspace = true rust-version.workspace = true exclude.workspace = true include.workspace = true [workspace] members = [] [workspace.package] version = "1.2.3" authors = ["Rustaceans"] description = "This is a crate" documentation = "https://www.rust-lang.org/learn" homepage = "https://www.rust-lang.org" repository = "https://github.com/example/example" license = "MIT" keywords = ["cli"] categories = ["development-tools"] publish = true edition = "2018" rust-version = "1.60" exclude = ["foo.txt"] include = ["bar.txt", "**/*.rs", "Cargo.toml"] "#, ) .file("src/main.rs", "fn main() {}") .file("foo.txt", "") // should be ignored when packaging .file("bar.txt", "") // should be included when packaging .build(); p.cargo("publish") .replace_crates_io(registry.index_url()) .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] both package.include and package.exclude are specified; the exclude list will be ignored [PACKAGING] foo v1.2.3 ([ROOT]/foo) [PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] foo v1.2.3 ([ROOT]/foo) [COMPILING] foo v1.2.3 ([ROOT]/foo/target/package/foo-1.2.3) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] foo v1.2.3 ([ROOT]/foo) [UPLOADED] foo v1.2.3 to registry `crates-io` [NOTE] waiting for `foo v1.2.3` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] foo v1.2.3 at registry `crates-io` "#]]) .run(); publish::validate_upload_with_contents( r#" { "authors": ["Rustaceans"], "badges": {}, "categories": ["development-tools"], "deps": [], "description": "This is a crate", "documentation": "https://www.rust-lang.org/learn", "features": {}, "homepage": "https://www.rust-lang.org", "keywords": ["cli"], "license": "MIT", "license_file": null, "links": null, "name": "foo", "readme": null, "readme_file": null, "repository": "https://github.com/example/example", "rust_version": "1.60", "vers": "1.2.3" } "#, "foo-1.2.3.crate", &[ "Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs", ".cargo_vcs_info.json", "bar.txt", ], &[( "Cargo.toml", &format!( r#"{} [package] edition = "2018" rust-version = "1.60" name = "foo" version = "1.2.3" authors = ["Rustaceans"] build = false exclude = ["foo.txt"] include = [ "bar.txt", "**/*.rs", "Cargo.toml", ] publish = true autobins = false autoexamples = false autotests = false autobenches = false description = "This is a crate" homepage = "https://www.rust-lang.org" documentation = "https://www.rust-lang.org/learn" readme = false keywords = ["cli"] categories = ["development-tools"] license = "MIT" repository = "https://github.com/example/example" [[bin]] name = "foo" path = "src/main.rs" "#, cargo::core::manifest::MANIFEST_PREAMBLE ), )], ); } #[cargo_test] fn inherit_own_dependencies() { let registry = RegistryBuilder::new().http_api().http_index().build(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep.workspace = true [build-dependencies] dep-build.workspace = true [dev-dependencies] dep-dev.workspace = true [workspace] members = [] [workspace.dependencies] dep = "0.1" dep-build = "0.8" dep-dev = "0.5.2" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("dep", "0.1.2").publish(); Package::new("dep-build", "0.8.2").publish(); Package::new("dep-dev", "0.5.2").publish(); p.cargo("check") // Unordered because the download order is nondeterministic. .with_stderr_data( str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 4 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) [DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`) [CHECKING] dep v0.1.2 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]] .unordered(), ) .run(); p.cargo("check").run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); assert!(lockfile.contains("dep-dev")); assert!(lockfile.contains("dep-build")); p.cargo("publish") .replace_crates_io(registry.index_url()) .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] manifest has no description, license, license-file, documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] bar v0.2.0 ([ROOT]/foo) [UPDATING] crates.io index [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] bar v0.2.0 ([ROOT]/foo) [COMPILING] dep v0.1.2 [COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] bar v0.2.0 ([ROOT]/foo) [UPLOADED] bar v0.2.0 to registry `crates-io` [NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] bar v0.2.0 at registry `crates-io` "#]]) .run(); publish::validate_upload_with_contents( r#" { "authors": [], "badges": {}, "categories": [], "deps": [ { "default_features": true, "features": [], "kind": "normal", "name": "dep", "optional": false, "target": null, "version_req": "^0.1" }, { "default_features": true, "features": [], "kind": "dev", "name": "dep-dev", "optional": false, "target": null, "version_req": "^0.5.2" }, { "default_features": true, "features": [], "kind": "build", "name": "dep-build", "optional": false, "target": null, "version_req": "^0.8" } ], "description": null, "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": null, "license_file": null, "links": null, "name": "bar", "readme": null, "readme_file": null, "repository": null, "rust_version": null, "vers": "0.2.0" } "#, "bar-0.2.0.crate", &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], &[( "Cargo.toml", &format!( r#"{} [package] edition = "2015" name = "bar" version = "0.2.0" authors = [] build = false autobins = false autoexamples = false autotests = false autobenches = false readme = false [[bin]] name = "bar" path = "src/main.rs" [dependencies.dep] version = "0.1" [dev-dependencies.dep-dev] version = "0.5.2" [build-dependencies.dep-build] version = "0.8" "#, cargo::core::manifest::MANIFEST_PREAMBLE ), )], ); } #[cargo_test] fn inherit_own_detailed_dependencies() { let registry = RegistryBuilder::new().http_api().http_index().build(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep.workspace = true [workspace] members = [] [workspace.dependencies] dep = { version = "0.1.2", features = ["testing"] } "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("dep", "0.1.2") .feature("testing", &vec![]) .publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) [CHECKING] dep v0.1.2 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); p.cargo("check").run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); p.cargo("publish") .replace_crates_io(registry.index_url()) .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] manifest has no description, license, license-file, documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] bar v0.2.0 ([ROOT]/foo) [UPDATING] crates.io index [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] bar v0.2.0 ([ROOT]/foo) [COMPILING] dep v0.1.2 [COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] bar v0.2.0 ([ROOT]/foo) [UPLOADED] bar v0.2.0 to registry `crates-io` [NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] bar v0.2.0 at registry `crates-io` "#]]) .run(); publish::validate_upload_with_contents( r#" { "authors": [], "badges": {}, "categories": [], "deps": [ { "default_features": true, "features": ["testing"], "kind": "normal", "name": "dep", "optional": false, "target": null, "version_req": "^0.1.2" } ], "description": null, "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": null, "license_file": null, "links": null, "name": "bar", "readme": null, "readme_file": null, "repository": null, "rust_version": null, "vers": "0.2.0" } "#, "bar-0.2.0.crate", &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], &[( "Cargo.toml", &format!( r#"{} [package] edition = "2015" name = "bar" version = "0.2.0" authors = [] build = false autobins = false autoexamples = false autotests = false autobenches = false readme = false [[bin]] name = "bar" path = "src/main.rs" [dependencies.dep] version = "0.1.2" features = ["testing"] "#, cargo::core::manifest::MANIFEST_PREAMBLE ), )], ); } #[cargo_test] fn inherit_from_own_undefined_field() { registry::init(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [package] name = "foo" version = "1.2.5" edition = "2015" authors = ["rustaceans"] description.workspace = true [workspace] members = [] "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: error inheriting `description` from workspace root manifest's `workspace.package.description` Caused by: `workspace.package.description` was not defined "#]]) .run(); } #[cargo_test] fn inherited_dependencies_union_features() { Package::new("dep", "0.1.0") .feature("fancy", &["fancy_dep"]) .feature("dancy", &["dancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .add_dep(Dependency::new("dancy_dep", "0.6").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); Package::new("dancy_dep", "0.6.8").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, features = ["dancy"] } [workspace] members = [] [workspace.dependencies] dep = { version = "0.1", features = ["fancy"] } "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data( str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 4 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [DOWNLOADED] dancy_dep v0.6.8 (registry `dummy-registry`) [CHECKING] fancy_dep v0.2.4 [CHECKING] dancy_dep v0.6.8 [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]] .unordered(), ) .run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); assert!(lockfile.contains("fancy_dep")); assert!(lockfile.contains("dancy_dep")); } #[cargo_test] fn inherit_workspace_fields() { let registry = RegistryBuilder::new().http_api().http_index().build(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.package] version = "1.2.3" authors = ["Rustaceans"] description = "This is a crate" documentation = "https://www.rust-lang.org/learn" readme = "README.md" homepage = "https://www.rust-lang.org" repository = "https://github.com/example/example" license = "MIT" license-file = "LICENSE" keywords = ["cli"] categories = ["development-tools"] publish = true edition = "2018" rust-version = "1.60" exclude = ["foo.txt"] include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] "#, ) .file("src/main.rs", "fn main() {}") .file( "bar/Cargo.toml", r#" [package] name = "bar" workspace = ".." version.workspace = true authors.workspace = true description.workspace = true documentation.workspace = true readme.workspace = true homepage.workspace = true repository.workspace = true license.workspace = true license-file.workspace = true keywords.workspace = true categories.workspace = true publish.workspace = true edition.workspace = true rust-version.workspace = true exclude.workspace = true include.workspace = true "#, ) .file("LICENSE", "license") .file("README.md", "README.md") .file("bar/src/main.rs", "fn main() {}") .file("bar/foo.txt", "") // should be ignored when packaging .file("bar/bar.txt", "") // should be included when packaging .build(); p.cargo("publish") .replace_crates_io(registry.index_url()) .cwd("bar") .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] both package.include and package.exclude are specified; the exclude list will be ignored [PACKAGING] bar v1.2.3 ([ROOT]/foo/bar) [PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] bar v1.2.3 ([ROOT]/foo/bar) [WARNING] only one of `license` or `license-file` is necessary `license` should be used if the package license can be expressed with a standard SPDX expression. `license-file` should be used if the package uses a non-standard license. See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information. [COMPILING] bar v1.2.3 ([ROOT]/foo/target/package/bar-1.2.3) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] bar v1.2.3 ([ROOT]/foo/bar) [UPLOADED] bar v1.2.3 to registry `crates-io` [NOTE] waiting for `bar v1.2.3` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] bar v1.2.3 at registry `crates-io` "#]]) .run(); publish::validate_upload_with_contents( r#" { "authors": ["Rustaceans"], "badges": {}, "categories": ["development-tools"], "deps": [], "description": "This is a crate", "documentation": "https://www.rust-lang.org/learn", "features": {}, "homepage": "https://www.rust-lang.org", "keywords": ["cli"], "license": "MIT", "license_file": "LICENSE", "links": null, "name": "bar", "readme": "README.md", "readme_file": "README.md", "repository": "https://github.com/example/example", "rust_version": "1.60", "vers": "1.2.3" } "#, "bar-1.2.3.crate", &[ "Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs", "README.md", "LICENSE", ".cargo_vcs_info.json", "bar.txt", ], &[( "Cargo.toml", &format!( r#"{} [package] edition = "2018" rust-version = "1.60" name = "bar" version = "1.2.3" authors = ["Rustaceans"] build = false exclude = ["foo.txt"] include = [ "bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md", ] publish = true autobins = false autoexamples = false autotests = false autobenches = false description = "This is a crate" homepage = "https://www.rust-lang.org" documentation = "https://www.rust-lang.org/learn" readme = "README.md" keywords = ["cli"] categories = ["development-tools"] license = "MIT" license-file = "LICENSE" repository = "https://github.com/example/example" [[bin]] name = "bar" path = "src/main.rs" "#, cargo::core::manifest::MANIFEST_PREAMBLE ), )], ); } #[cargo_test] fn inherit_dependencies() { let registry = RegistryBuilder::new().http_api().http_index().build(); let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.dependencies] dep = "0.1" dep-build = "0.8" dep-dev = "0.5.2" "#, ) .file( "bar/Cargo.toml", r#" [package] workspace = ".." name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep.workspace = true [build-dependencies] dep-build.workspace = true [dev-dependencies] dep-dev.workspace = true "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); Package::new("dep", "0.1.2").publish(); Package::new("dep-build", "0.8.2").publish(); Package::new("dep-dev", "0.5.2").publish(); p.cargo("check") // Unordered because the download order is nondeterministic. .with_stderr_data( str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 4 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) [DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`) [CHECKING] dep v0.1.2 [CHECKING] bar v0.2.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]] .unordered(), ) .run(); p.cargo("check").run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); assert!(lockfile.contains("dep-dev")); assert!(lockfile.contains("dep-build")); p.cargo("publish") .replace_crates_io(registry.index_url()) .cwd("bar") .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] manifest has no description, license, license-file, documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] bar v0.2.0 ([ROOT]/foo/bar) [UPDATING] crates.io index [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] bar v0.2.0 ([ROOT]/foo/bar) [COMPILING] dep v0.1.2 [COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] bar v0.2.0 ([ROOT]/foo/bar) [UPLOADED] bar v0.2.0 to registry `crates-io` [NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] bar v0.2.0 at registry `crates-io` "#]]) .run(); publish::validate_upload_with_contents( r#" { "authors": [], "badges": {}, "categories": [], "deps": [ { "default_features": true, "features": [], "kind": "normal", "name": "dep", "optional": false, "target": null, "version_req": "^0.1" }, { "default_features": true, "features": [], "kind": "dev", "name": "dep-dev", "optional": false, "target": null, "version_req": "^0.5.2" }, { "default_features": true, "features": [], "kind": "build", "name": "dep-build", "optional": false, "target": null, "version_req": "^0.8" } ], "description": null, "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": null, "license_file": null, "links": null, "name": "bar", "readme": null, "readme_file": null, "repository": null, "rust_version": null, "vers": "0.2.0" } "#, "bar-0.2.0.crate", &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], &[( "Cargo.toml", &format!( r#"{} [package] edition = "2015" name = "bar" version = "0.2.0" authors = [] build = false autobins = false autoexamples = false autotests = false autobenches = false readme = false [[bin]] name = "bar" path = "src/main.rs" [dependencies.dep] version = "0.1" [dev-dependencies.dep-dev] version = "0.5.2" [build-dependencies.dep-build] version = "0.8" "#, cargo::core::manifest::MANIFEST_PREAMBLE ), )], ); } #[cargo_test] fn inherit_target_dependencies() { let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.dependencies] dep = "0.1" "#, ) .file( "bar/Cargo.toml", r#" [package] workspace = ".." name = "bar" version = "0.2.0" edition = "2015" authors = [] [target.'cfg(unix)'.dependencies] dep.workspace = true [target.'cfg(windows)'.dependencies] dep.workspace = true "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); Package::new("dep", "0.1.2").publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) [CHECKING] dep v0.1.2 [CHECKING] bar v0.2.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); } #[cargo_test] fn inherit_dependency_override_optional() { Package::new("dep", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.dependencies] dep = "0.1.0" "#, ) .file( "bar/Cargo.toml", r#" [package] workspace = ".." name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, optional = true } "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 2 packages to latest compatible versions [CHECKING] bar v0.2.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn inherit_dependency_features() { Package::new("dep", "0.1.0") .feature("fancy", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); Package::new("dancy_dep", "0.6.8").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, features = ["fancy"] } [workspace] members = [] [workspace.dependencies] dep = "0.1" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [CHECKING] fancy_dep v0.2.4 [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); assert!(lockfile.contains("fancy_dep")); } #[cargo_test] fn inherit_detailed_dependencies() { let git_project = git::new("detailed", |project| { project .file("Cargo.toml", &basic_lib_manifest("detailed")) .file( "src/detailed.rs", r#" pub fn hello() -> &'static str { "hello world" } "#, ) }); // Make a new branch based on the current HEAD commit let repo = git2::Repository::open(&git_project.root()).unwrap(); let head = repo.head().unwrap().target().unwrap(); let head = repo.find_commit(head).unwrap(); repo.branch("branchy", &head, true).unwrap(); let p = project() .file( "Cargo.toml", &format!( r#" [workspace] members = ["bar"] [workspace.dependencies] detailed = {{ git = '{}', branch = "branchy" }} "#, git_project.url() ), ) .file( "bar/Cargo.toml", r#" [package] workspace = ".." name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] detailed.workspace = true "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] git repository `[ROOTURL]/detailed` [LOCKING] 2 packages to latest compatible versions [CHECKING] detailed v0.5.0 ([ROOTURL]/detailed?branch=branchy#[..]) [CHECKING] bar v0.2.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn inherit_path_dependencies() { let p = project() .file( "Cargo.toml", r#" [workspace] members = ["bar"] [workspace.dependencies] dep = { path = "dep" } "#, ) .file( "bar/Cargo.toml", r#" [package] workspace = ".." name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep.workspace = true "#, ) .file("bar/src/main.rs", "fn main() {}") .file("dep/Cargo.toml", &basic_manifest("dep", "0.9.0")) .file("dep/src/lib.rs", "") .build(); p.cargo("check") .with_stderr_data(str![[r#" [LOCKING] 2 packages to latest compatible versions [CHECKING] dep v0.9.0 ([ROOT]/foo/dep) [CHECKING] bar v0.2.0 ([ROOT]/foo/bar) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); let lockfile = p.read_lockfile(); assert!(lockfile.contains("dep")); } #[cargo_test] fn error_workspace_false() { registry::init(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [workspace] members = ["bar"] "#, ) .file("src/main.rs", "fn main() {}") .file( "bar/Cargo.toml", r#" [package] name = "bar" workspace = ".." version = "1.2.3" edition = "2015" authors = ["rustaceans"] description = { workspace = false } "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .cwd("bar") .with_status(101) .with_stderr_data(str![[r#" [ERROR] `workspace` cannot be false --> Cargo.toml:8:41 | 8 | description = { workspace = false } | ^^^^^ | "#]]) .run(); } #[cargo_test] fn error_workspace_dependency_looked_for_workspace_itself() { registry::init(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [package] name = "bar" version = "1.2.3" edition = "2015" [dependencies] dep.workspace = true [workspace] members = [] [workspace.dependencies] dep.workspace = true "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: dependency (dep) specified without providing a local path, Git repository, version, or workspace dependency to use "#]]) .run(); } #[cargo_test] fn error_malformed_workspace_root() { registry::init(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [workspace] members = [invalid toml "#, ) .file("src/main.rs", "fn main() {}") .file( "bar/Cargo.toml", r#" [package] name = "bar" workspace = ".." version = "1.2.3" edition = "2015" authors = ["rustaceans"] "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .cwd("bar") .with_status(101) .with_stderr_data(str![[r#" [ERROR] invalid array expected `]` --> ../Cargo.toml:3:24 | 3 | members = [invalid toml | ^ | "#]]) .run(); } #[cargo_test] fn error_no_root_workspace() { registry::init(); let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "bar/Cargo.toml", r#" [package] name = "bar" workspace = ".." version = "1.2.3" edition = "2015" authors = ["rustaceans"] description.workspace = true "#, ) .file("src/main.rs", "fn main() {}") .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .cwd("bar") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml` Caused by: error inheriting `description` from workspace root manifest's `workspace.package.description` Caused by: root of a workspace inferred but wasn't a root: [ROOT]/foo/Cargo.toml "#]]) .run(); } #[cargo_test] fn error_inherit_unspecified_dependency() { let p = project().build(); let _ = git::repo(&paths::root().join("foo")) .file( "Cargo.toml", r#" [workspace] members = ["bar"] "#, ) .file("src/main.rs", "fn main() {}") .file( "bar/Cargo.toml", r#" [package] name = "bar" workspace = ".." version = "1.2.3" edition = "2015" authors = ["rustaceans"] [dependencies] foo.workspace = true "#, ) .file("bar/src/main.rs", "fn main() {}") .build(); p.cargo("check") .cwd("bar") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml` Caused by: error inheriting `foo` from workspace root manifest's `workspace.dependencies.foo` Caused by: `workspace.dependencies` was not defined "#]]) .run(); } #[cargo_test] fn warn_inherit_def_feat_true_member_def_feat_false() { Package::new("dep", "0.1.0") .feature("default", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, default-features = false } [workspace] members = [] [workspace.dependencies] dep = { version = "0.1.0", default-features = true } "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check").with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was true for `workspace.dependencies.dep`, this could become a hard error in the future [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [CHECKING] fancy_dep v0.2.4 [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]).run(); } #[cargo_test(nightly, reason = "edition2024 is not stable")] fn warn_inherit_def_feat_true_member_def_feat_false_2024_edition() { Package::new("dep", "0.1.0") .feature("default", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); let p = project() .file( "Cargo.toml", r#" cargo-features = ["edition2024"] [package] name = "bar" version = "0.2.0" edition = "2024" authors = [] [dependencies] dep = { workspace = true, default-features = false } [workspace] members = [] [workspace.dependencies] dep = { version = "0.1.0", default-features = true } "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .masquerade_as_nightly_cargo(&["edition2024"]) .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep` Caused by: `default-features = false` cannot override workspace's `default-features` "#]]) .run(); } #[cargo_test] fn warn_inherit_simple_member_def_feat_false() { Package::new("dep", "0.1.0") .feature("default", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, default-features = false } [workspace] members = [] [workspace.dependencies] dep = "0.1.0" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check").with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was not specified for `workspace.dependencies.dep`, this could become a hard error in the future [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [CHECKING] fancy_dep v0.2.4 [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]).run(); } #[cargo_test(nightly, reason = "edition2024 is not stable")] fn warn_inherit_simple_member_def_feat_false_2024_edition() { Package::new("dep", "0.1.0") .feature("default", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); let p = project() .file( "Cargo.toml", r#" cargo-features = ["edition2024"] [package] name = "bar" version = "0.2.0" edition = "2024" authors = [] [dependencies] dep = { workspace = true, default-features = false } [workspace] members = [] [workspace.dependencies] dep = "0.1.0" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .masquerade_as_nightly_cargo(&["edition2024"]) .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep` Caused by: `default-features = false` cannot override workspace's `default-features` "#]]) .run(); } #[cargo_test] fn inherit_def_feat_false_member_def_feat_true() { Package::new("dep", "0.1.0") .feature("default", &["fancy_dep"]) .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) .file("src/lib.rs", "") .publish(); Package::new("fancy_dep", "0.2.4").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, default-features = true } [workspace] members = [] [workspace.dependencies] dep = { version = "0.1.0", default-features = false } "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [CHECKING] fancy_dep v0.2.4 [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn cannot_inherit_in_patch() { Package::new("bar", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [workspace] members = [] [workspace.dependencies] bar = { path = "bar" } [package] name = "foo" version = "0.2.0" edition = "2015" [patch.crates-io] bar.workspace = true [dependencies] bar = "0.1.0" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: dependency (bar) specified without providing a local path, Git repository, version, or workspace dependency to use "#]]) .run(); } #[cargo_test] fn warn_inherit_unused_manifest_key_dep() { Package::new("dep", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [workspace] members = [] [workspace.dependencies] dep = { version = "0.1", wxz = "wxz" } [package] name = "bar" version = "0.2.0" edition = "2015" authors = [] [dependencies] dep = { workspace = true, wxz = "wxz" } "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.dependencies.dep.wxz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: dependencies.dep.wxz [UPDATING] `dummy-registry` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) [CHECKING] dep v0.1.0 [CHECKING] bar v0.2.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn warn_unused_workspace_package_field() { Package::new("dep", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [workspace] members = [] [workspace.package] name = "unused" [package] name = "foo" edition = "2015" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.package.name [CHECKING] foo v0.0.0 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn warn_inherit_unused_manifest_key_package() { Package::new("dep", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [workspace] members = [] [workspace.package] version = "1.2.3" authors = ["Rustaceans"] description = "This is a crate" documentation = "https://www.rust-lang.org/learn" homepage = "https://www.rust-lang.org" repository = "https://github.com/example/example" license = "MIT" keywords = ["cli"] categories = ["development-tools"] publish = true edition = "2018" rust-version = "1.60" exclude = ["foo.txt"] include = ["bar.txt", "**/*.rs", "Cargo.toml"] [package] name = "bar" version = { workspace = true, xyz = "abc"} authors = { workspace = true, xyz = "abc"} description = { workspace = true, xyz = "abc"} documentation = { workspace = true, xyz = "abc"} homepage = { workspace = true, xyz = "abc"} repository = { workspace = true, xyz = "abc"} license = { workspace = true, xyz = "abc"} keywords = { workspace = true, xyz = "abc"} categories = { workspace = true, xyz = "abc"} publish = { workspace = true, xyz = "abc"} edition = { workspace = true, xyz = "abc"} rust-version = { workspace = true, xyz = "abc"} exclude = { workspace = true, xyz = "abc"} include = { workspace = true, xyz = "abc"} "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.authors.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.categories.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.description.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.documentation.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.edition.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.exclude.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.homepage.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.include.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.keywords.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.license.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.publish.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.repository.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.rust-version.xyz [WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.version.xyz [CHECKING] bar v1.2.3 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); }