cargo/tests/testsuite/tree_graph_features.rs
Maybe Waffle 3d74ad8e3c Do not ignore --features when --all-features is present
This allows to specify dependency features when using `--all-features`,
for example:
```shell
$ cargo run --package a --example example --all-features --features="tracing/log"
```
2022-01-28 02:49:42 +03:00

362 lines
9.8 KiB
Rust

//! Tests for the `cargo tree` command with -e features option.
use cargo_test_support::project;
use cargo_test_support::registry::{Dependency, Package};
#[cargo_test]
fn dep_feature_various() {
// Checks different ways of setting features via dependencies.
Package::new("optdep", "1.0.0")
.feature("default", &["cat"])
.feature("cat", &[])
.publish();
Package::new("defaultdep", "1.0.0")
.feature("default", &["f1"])
.feature("f1", &["optdep"])
.add_dep(Dependency::new("optdep", "1.0").optional(true))
.publish();
Package::new("nodefaultdep", "1.0.0")
.feature("default", &["f1"])
.feature("f1", &[])
.publish();
Package::new("nameddep", "1.0.0")
.add_dep(Dependency::new("serde", "1.0").optional(true))
.feature("default", &["serde-stuff"])
.feature("serde-stuff", &["serde/derive"])
.feature("vehicle", &["car"])
.feature("car", &[])
.publish();
Package::new("serde_derive", "1.0.0").publish();
Package::new("serde", "1.0.0")
.feature("derive", &["serde_derive"])
.add_dep(Dependency::new("serde_derive", "1.0").optional(true))
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
defaultdep = "1.0"
nodefaultdep = {version="1.0", default-features = false}
nameddep = {version="1.0", features = ["vehicle", "serde"]}
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("tree -e features")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
├── nodefaultdep v1.0.0
├── defaultdep feature \"default\"
│ ├── defaultdep v1.0.0
│ │ └── optdep feature \"default\"
│ │ ├── optdep v1.0.0
│ │ └── optdep feature \"cat\"
│ │ └── optdep v1.0.0
│ └── defaultdep feature \"f1\"
│ ├── defaultdep v1.0.0 (*)
│ └── defaultdep feature \"optdep\"
│ └── defaultdep v1.0.0 (*)
├── nameddep feature \"default\"
│ ├── nameddep v1.0.0
│ │ └── serde feature \"default\"
│ │ └── serde v1.0.0
│ │ └── serde_derive feature \"default\"
│ │ └── serde_derive v1.0.0
│ └── nameddep feature \"serde-stuff\"
│ ├── nameddep v1.0.0 (*)
│ ├── nameddep feature \"serde\"
│ │ └── nameddep v1.0.0 (*)
│ └── serde feature \"derive\"
│ ├── serde v1.0.0 (*)
│ └── serde feature \"serde_derive\"
│ └── serde v1.0.0 (*)
├── nameddep feature \"serde\" (*)
└── nameddep feature \"vehicle\"
├── nameddep v1.0.0 (*)
└── nameddep feature \"car\"
└── nameddep v1.0.0 (*)
",
)
.run();
}
#[cargo_test]
fn graph_features_ws_interdependent() {
// A workspace with interdependent crates.
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["a", "b"]
"#,
)
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.1.0"
[dependencies]
b = {path="../b", features=["feat2"]}
[features]
default = ["a1"]
a1 = []
a2 = []
"#,
)
.file("a/src/lib.rs", "")
.file(
"b/Cargo.toml",
r#"
[package]
name = "b"
version = "0.1.0"
[features]
default = ["feat1"]
feat1 = []
feat2 = []
"#,
)
.file("b/src/lib.rs", "")
.build();
p.cargo("tree -e features")
.with_stdout(
"\
a v0.1.0 ([..]/foo/a)
├── b feature \"default\" (command-line)
│ ├── b v0.1.0 ([..]/foo/b)
│ └── b feature \"feat1\"
│ └── b v0.1.0 ([..]/foo/b)
└── b feature \"feat2\"
└── b v0.1.0 ([..]/foo/b)
b v0.1.0 ([..]/foo/b)
",
)
.run();
p.cargo("tree -e features -i a -i b")
.with_stdout(
"\
a v0.1.0 ([..]/foo/a)
├── a feature \"a1\"
│ └── a feature \"default\" (command-line)
└── a feature \"default\" (command-line)
b v0.1.0 ([..]/foo/b)
├── b feature \"default\" (command-line)
│ └── a v0.1.0 ([..]/foo/a) (*)
├── b feature \"feat1\"
│ └── b feature \"default\" (command-line) (*)
└── b feature \"feat2\"
└── a v0.1.0 ([..]/foo/a) (*)
",
)
.run();
}
#[cargo_test]
fn slash_feature_name() {
// dep_name/feat_name syntax
Package::new("opt", "1.0.0").feature("feat1", &[]).publish();
Package::new("notopt", "1.0.0")
.feature("cat", &[])
.feature("animal", &["cat"])
.publish();
Package::new("opt2", "1.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
opt = {version = "1.0", optional=true}
opt2 = {version = "1.0", optional=true}
notopt = "1.0"
[features]
f1 = ["opt/feat1", "notopt/animal"]
f2 = ["f1"]
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("tree -e features --features f1")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
├── notopt feature \"default\"
│ └── notopt v1.0.0
└── opt feature \"default\"
└── opt v1.0.0
",
)
.run();
p.cargo("tree -e features --features f1 -i foo")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
├── foo feature \"default\" (command-line)
├── foo feature \"f1\" (command-line)
└── foo feature \"opt\"
└── foo feature \"f1\" (command-line)
",
)
.run();
p.cargo("tree -e features --features f1 -i notopt")
.with_stdout(
"\
notopt v1.0.0
├── notopt feature \"animal\"
│ └── foo feature \"f1\" (command-line)
├── notopt feature \"cat\"
│ └── notopt feature \"animal\" (*)
└── notopt feature \"default\"
└── foo v0.1.0 ([..]/foo)
├── foo feature \"default\" (command-line)
├── foo feature \"f1\" (command-line)
└── foo feature \"opt\"
└── foo feature \"f1\" (command-line)
",
)
.run();
p.cargo("tree -e features --features notopt/animal -i notopt")
.with_stdout(
"\
notopt v1.0.0
├── notopt feature \"animal\" (command-line)
├── notopt feature \"cat\"
│ └── notopt feature \"animal\" (command-line)
└── notopt feature \"default\"
└── foo v0.1.0 ([..]/foo)
└── foo feature \"default\" (command-line)
",
)
.run();
p.cargo("tree -e features --all-features")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
├── notopt feature \"default\"
│ └── notopt v1.0.0
├── opt feature \"default\"
│ └── opt v1.0.0
└── opt2 feature \"default\"
└── opt2 v1.0.0
",
)
.run();
p.cargo("tree -e features --all-features -i opt2")
.with_stdout(
"\
opt2 v1.0.0
└── opt2 feature \"default\"
└── foo v0.1.0 ([..]/foo)
├── foo feature \"default\" (command-line)
├── foo feature \"f1\" (command-line)
│ └── foo feature \"f2\" (command-line)
├── foo feature \"f2\" (command-line)
├── foo feature \"opt\" (command-line)
│ └── foo feature \"f1\" (command-line) (*)
└── foo feature \"opt2\" (command-line)
",
)
.run();
}
#[cargo_test]
fn features_enables_inactive_target() {
// Features that enable things on targets that are not enabled.
Package::new("optdep", "1.0.0")
.feature("feat1", &[])
.publish();
Package::new("dep1", "1.0.0")
.feature("somefeat", &[])
.publish();
Package::new("dep2", "1.0.0")
.add_dep(
Dependency::new("optdep", "1.0.0")
.optional(true)
.target("cfg(whatever)"),
)
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[target.'cfg(whatever)'.dependencies]
optdep = {version="1.0", optional=true}
dep1 = "1.0"
[dependencies]
dep2 = "1.0"
[features]
f1 = ["optdep"]
f2 = ["optdep/feat1"]
f3 = ["dep1/somefeat"]
f4 = ["dep2/optdep"]
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("tree -e features")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
└── dep2 feature \"default\"
└── dep2 v1.0.0
",
)
.run();
p.cargo("tree -e features --all-features")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
└── dep2 feature \"default\"
└── dep2 v1.0.0
",
)
.run();
p.cargo("tree -e features --all-features --target=all")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
├── dep1 feature \"default\"
│ └── dep1 v1.0.0
├── dep2 feature \"default\"
│ └── dep2 v1.0.0
│ └── optdep feature \"default\"
│ └── optdep v1.0.0
└── optdep feature \"default\" (*)
",
)
.run();
}