mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
1293 lines
37 KiB
Rust
1293 lines
37 KiB
Rust
//! Tests for workspace feature unification.
|
|
|
|
use crate::prelude::*;
|
|
use crate::utils::cargo_process;
|
|
use cargo_test_support::{
|
|
basic_manifest,
|
|
compare::assert_e2e,
|
|
project,
|
|
registry::{Dependency, Package},
|
|
str,
|
|
};
|
|
|
|
#[cargo_test]
|
|
fn workspace_feature_unification() {
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[resolver]
|
|
feature-unification = "workspace"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(not(all(feature = "a", feature = "b")))]
|
|
compile_error!("features were not unified");
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["a"] }
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"] }
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check -p common")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] a v0.1.0 ([ROOT]/foo/a)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] b v0.1.0 ([ROOT]/foo/b)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_feature_unification() {
|
|
Package::new("outside", "0.1.0")
|
|
.feature("a", &[])
|
|
.feature("b", &[])
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[resolver]
|
|
feature-unification = "package"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["a"] }
|
|
outside = { version = "0.1.0", features = ["a"] }
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "pub use common::a;")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"] }
|
|
outside = { version = "0.1.0", features = ["b"] }
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "pub use common::b;")
|
|
.build();
|
|
|
|
p.cargo("check -p common")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] outside v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] outside v0.1.0
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[CHECKING] a v0.1.0 ([ROOT]/foo/a)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[CHECKING] outside v0.1.0
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[CHECKING] b v0.1.0 ([ROOT]/foo/b)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check -p a -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
// Sanity check that compilation without package feature unification does not work
|
|
p.cargo("check -p a -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] features were unified")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_feature_unification_default_features() {
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[resolver]
|
|
feature-unification = "package"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
default = ["a"]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common" }
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "pub use common::a;")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"], default-features = false }
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "pub use common::b;")
|
|
.build();
|
|
|
|
p.cargo("check -p common")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] a v0.1.0 ([ROOT]/foo/a)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[CHECKING] b v0.1.0 ([ROOT]/foo/b)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_feature_unification_cli_features() {
|
|
Package::new("outside", "0.1.0")
|
|
.feature("a", &[])
|
|
.feature("b", &[])
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[resolver]
|
|
feature-unification = "package"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common" }
|
|
outside = "0.1.0"
|
|
|
|
[features]
|
|
a = ["common/a", "outside/a"]
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "pub use common::a;")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"] }
|
|
outside = "0.1.0"
|
|
|
|
[features]
|
|
b = ["common/b", "outside/b"]
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "pub use common::b;")
|
|
.build();
|
|
|
|
p.cargo("check -p a -p b -F a,b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] outside v0.1.0 (registry `dummy-registry`)
|
|
[CHECKING] outside v0.1.0
|
|
[CHECKING] b v0.1.0 ([ROOT]/foo/b)
|
|
[CHECKING] a v0.1.0 ([ROOT]/foo/a)
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check --workspace --exclude common -F a,b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
|
|
p.cargo("check -p a -p b -F a/a,b/b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check -p a -p b -F a,b,c")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] none of the selected packages contains this feature: c
|
|
selected packages: a, b
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p a -F b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'a' does not contain this feature: b
|
|
[HELP] packages with the missing feature: common, b
|
|
|
|
"#]])
|
|
.run();
|
|
p.cargo("check -p a -F a/a,common/b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] features were unified")
|
|
.run();
|
|
|
|
p.cargo("check -p a -F a/a,outside/b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] features were unified")
|
|
.run();
|
|
|
|
// Sanity check that compilation without package feature unification does not work
|
|
p.cargo("check -p a -p b -F a,b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] features were unified")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn package_feature_unification_weak_dependencies() {
|
|
let p = project()
|
|
.file(
|
|
".cargo/config.toml",
|
|
r#"
|
|
[resolver]
|
|
feature-unification = "package"
|
|
"#,
|
|
)
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", optional = true }
|
|
|
|
[features]
|
|
default = ["dep:common", "common?/a"]
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "pub use common::a;")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", optional = true }
|
|
|
|
[features]
|
|
default = ["dep:common", "common?/b"]
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "pub use common::b;")
|
|
.build();
|
|
|
|
p.cargo("check -p a -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[CHECKING] a v0.1.0 ([ROOT]/foo/a)
|
|
[CHECKING] b v0.1.0 ([ROOT]/foo/b)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
p.cargo("check")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] common v0.1.0 ([ROOT]/foo/common)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Sanity check that compilation without package feature unification does not work
|
|
p.cargo("check -p a -p b")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] features were unified")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn feature_unification_cargo_tree() {
|
|
Package::new("outside", "0.1.0")
|
|
.feature("a", &[])
|
|
.feature("b", &[])
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["common", "a", "b"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features were unified");
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
#[cfg(feature = "b")]
|
|
pub fn b() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"a/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["a"] }
|
|
outside = { version = "0.1.0", features = ["a"] }
|
|
"#,
|
|
)
|
|
.file("a/src/lib.rs", "pub use common::a;")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"] }
|
|
outside = { version = "0.1.0", features = ["b"] }
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "pub use common::b;")
|
|
.build();
|
|
|
|
p.cargo("tree -e features")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_stdout_data(str![[r#"
|
|
a v0.1.0 ([ROOT]/foo/a)
|
|
├── common feature "a"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default" (command-line)
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── outside feature "a"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default"
|
|
└── outside v0.1.0
|
|
|
|
b v0.1.0 ([ROOT]/foo/b)
|
|
├── common feature "b"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default" (command-line) (*)
|
|
├── outside feature "b"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default" (*)
|
|
|
|
common v0.1.0 ([ROOT]/foo/common)
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("tree -e features")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stdout_data(str![[r#"
|
|
a v0.1.0 ([ROOT]/foo/a)
|
|
├── common feature "a"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default" (command-line)
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── outside feature "a"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default"
|
|
└── outside v0.1.0
|
|
|
|
b v0.1.0 ([ROOT]/foo/b)
|
|
├── common feature "b"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default" (command-line) (*)
|
|
├── outside feature "b"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default" (*)
|
|
|
|
common v0.1.0 ([ROOT]/foo/common)
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("tree -e features")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_stdout_data(str![[r#"
|
|
common v0.1.0 ([ROOT]/foo/common)
|
|
a v0.1.0 ([ROOT]/foo/a)
|
|
├── common feature "a"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── outside feature "a"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default"
|
|
└── outside v0.1.0
|
|
b v0.1.0 ([ROOT]/foo/b)
|
|
├── common feature "b"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── common feature "default"
|
|
│ └── common v0.1.0 ([ROOT]/foo/common)
|
|
├── outside feature "b"
|
|
│ └── outside v0.1.0
|
|
└── outside feature "default"
|
|
└── outside v0.1.0
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn cargo_install_ignores_config() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "common", features = ["a"] }
|
|
|
|
[workspace]
|
|
members = ["common", "b"]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file(
|
|
"common/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "common"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
b = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"common/src/lib.rs",
|
|
r#"
|
|
#[cfg(all(feature = "a", feature = "b"))]
|
|
compile_error!("features should not be unified");
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
common = { path = "../common", features = ["b"] }
|
|
"#,
|
|
)
|
|
.file("b/src/lib.rs", "")
|
|
.build();
|
|
|
|
cargo_process("install --path")
|
|
.arg(p.root())
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[INSTALLING] a v0.1.0 ([ROOT]/foo)
|
|
[COMPILING] common v0.1.0 ([ROOT]/foo/common)
|
|
[COMPILING] a v0.1.0 ([ROOT]/foo)
|
|
[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s
|
|
[INSTALLING] [ROOT]/home/.cargo/bin/a[EXE]
|
|
[INSTALLED] package `a v0.1.0 ([ROOT]/foo)` (executable `a[EXE]`)
|
|
[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries
|
|
|
|
"#]])
|
|
.run();
|
|
cargo_process("install --path")
|
|
.arg(p.root())
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_stderr_data(str![[r#"
|
|
[INSTALLING] a v0.1.0 ([ROOT]/foo)
|
|
[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s
|
|
[REPLACING] [ROOT]/home/.cargo/bin/a[EXE]
|
|
[REPLACED] package `a v0.1.0 ([ROOT]/foo)` with `a v0.1.0 ([ROOT]/foo)` (executable `a[EXE]`)
|
|
[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn unstable_config_on_stable() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["bar"]
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[WARNING] ignoring `resolver.feature-unification` without `-Zfeature-unification`
|
|
[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn cargo_fix_works() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
# Before project
|
|
[ project ] # After project header
|
|
# After project header line
|
|
name = "foo"
|
|
edition = "2021"
|
|
# After project table
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fix --edition --allow-no-vcs")
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_stderr_data(str![[r#"
|
|
[MIGRATING] Cargo.toml from 2021 edition to 2024
|
|
[FIXED] Cargo.toml (1 fix)
|
|
[CHECKING] foo v0.0.0 ([ROOT]/foo)
|
|
[MIGRATING] src/lib.rs from 2021 edition to 2024
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
assert_e2e().eq(
|
|
p.read_file("Cargo.toml"),
|
|
str![[r#"
|
|
|
|
# Before project
|
|
[ package ] # After project header
|
|
# After project header line
|
|
name = "foo"
|
|
edition = "2021"
|
|
# After project table
|
|
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn edition_v2_resolver_report() {
|
|
// Show a report if the V2 resolver shows differences.
|
|
Package::new("common", "1.0.0")
|
|
.feature("f1", &[])
|
|
.feature("dev-feat", &[])
|
|
.add_dep(Dependency::new("opt_dep", "1.0").optional(true))
|
|
.publish();
|
|
Package::new("opt_dep", "1.0.0").publish();
|
|
|
|
Package::new("bar", "1.0.0")
|
|
.add_dep(
|
|
Dependency::new("common", "1.0")
|
|
.target("cfg(whatever)")
|
|
.enable_features(&["f1"]),
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["bar"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2018"
|
|
|
|
[dependencies]
|
|
common = "1.0"
|
|
bar = "1.0"
|
|
|
|
[build-dependencies]
|
|
common = { version = "1.0", features = ["opt_dep"] }
|
|
|
|
[dev-dependencies]
|
|
common = { version="1.0", features=["dev-feat"] }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
edition = "2018"
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fix --edition --allow-no-vcs --workspace")
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.with_status(101)
|
|
.with_stderr_data(
|
|
str![[r#"
|
|
[MIGRATING] Cargo.toml from 2018 edition to 2021
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 3 packages to latest compatible versions
|
|
[DOWNLOADING] crates ...
|
|
[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)
|
|
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
|
|
[DOWNLOADED] opt_dep v1.0.0 (registry `dummy-registry`)
|
|
[MIGRATING] bar/Cargo.toml from 2018 edition to 2021
|
|
[ERROR] cannot fix edition when using `feature-unification = "package"`.
|
|
|
|
"#]]
|
|
.unordered(),
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn feature_unification_of_cli_features_within_workspace() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
resolver = "2"
|
|
members = ["parent", "child", "grandchild"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"grandchild/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "grandchild"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
a = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"grandchild/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "a")]
|
|
pub fn a() {}
|
|
"#,
|
|
)
|
|
.file(
|
|
"child/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "child"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
grandchild = { path = "../grandchild" }
|
|
"#,
|
|
)
|
|
.file("child/src/lib.rs", "pub use grandchild::*;")
|
|
.file(
|
|
"parent/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "parent"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
child = { path = "../child" }
|
|
"#,
|
|
)
|
|
.file("parent/src/lib.rs", "pub use child::a;")
|
|
.build();
|
|
|
|
p.cargo("check -p parent -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -p parent -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -p parent -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -p child -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] grandchild v0.1.0 ([ROOT]/foo/grandchild)
|
|
[CHECKING] child v0.1.0 ([ROOT]/foo/child)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -p child -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -p child -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_stderr_data(str![[r#"
|
|
[CHECKING] parent v0.1.0 ([ROOT]/foo/parent)
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_stderr_data(str![[r#"
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild --exclude child")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "package")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild --exclude child")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("check -F grandchild/a --workspace --exclude grandchild --exclude child")
|
|
.arg("-Zfeature-unification")
|
|
.masquerade_as_nightly_cargo(&["feature-unification"])
|
|
.env("CARGO_RESOLVER_FEATURE_UNIFICATION", "selected")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the package 'parent' does not contain this feature: grandchild/a
|
|
|
|
"#]])
|
|
.run();
|
|
}
|