cargo/tests/testsuite/tree_graph_features.rs
Ed Page 5b9799c6f4 refactor: Migrate from extern crate to test-support prelude
We now include the prelude in so many places, this simplifies how we can
present how `cargo-test-support` works.

Yes, this included some `use` clean ups but its already painful enough
walking through every test file, I didn't want to do it twice.
2024-07-12 15:57:00 -05:00

353 lines
9.7 KiB
Rust

//! Tests for the `cargo tree` command with -e features option.
use cargo_test_support::prelude::*;
use cargo_test_support::project;
use cargo_test_support::registry::{Dependency, Package};
use cargo_test_support::str;
#[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_data(str![[r#"
foo v0.1.0 ([ROOT]/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_data(str![[r#"
a v0.1.0 ([ROOT]/foo/a)
├── b feature "default" (command-line)
│ ├── b v0.1.0 ([ROOT]/foo/b)
│ └── b feature "feat1"
│ └── b v0.1.0 ([ROOT]/foo/b)
└── b feature "feat2"
└── b v0.1.0 ([ROOT]/foo/b)
b v0.1.0 ([ROOT]/foo/b)
"#]])
.run();
p.cargo("tree -e features -i a -i b")
.with_stdout_data(str![[r#"
a v0.1.0 ([ROOT]/foo/a)
├── a feature "a1"
│ └── a feature "default" (command-line)
└── a feature "default" (command-line)
b v0.1.0 ([ROOT]/foo/b)
├── b feature "default" (command-line)
│ └── a v0.1.0 ([ROOT]/foo/a) (*)
├── b feature "feat1"
│ └── b feature "default" (command-line) (*)
└── b feature "feat2"
└── a v0.1.0 ([ROOT]/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_data(str![[r#"
foo v0.1.0 ([ROOT]/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_data(str![[r#"
foo v0.1.0 ([ROOT]/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_data(str![[r#"
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 ([ROOT]/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_data(str![[r#"
notopt v1.0.0
├── notopt feature "animal" (command-line)
├── notopt feature "cat"
│ └── notopt feature "animal" (command-line)
└── notopt feature "default"
└── foo v0.1.0 ([ROOT]/foo)
└── foo feature "default" (command-line)
"#]])
.run();
p.cargo("tree -e features --all-features")
.with_stdout_data(str![[r#"
foo v0.1.0 ([ROOT]/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_data(str![[r#"
opt2 v1.0.0
└── opt2 feature "default"
└── foo v0.1.0 ([ROOT]/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_data(str![[r#"
foo v0.1.0 ([ROOT]/foo)
└── dep2 feature "default"
└── dep2 v1.0.0
"#]])
.run();
p.cargo("tree -e features --all-features")
.with_stdout_data(str![[r#"
foo v0.1.0 ([ROOT]/foo)
└── dep2 feature "default"
└── dep2 v1.0.0
"#]])
.run();
p.cargo("tree -e features --all-features --target=all")
.with_stdout_data(str![[r#"
foo v0.1.0 ([ROOT]/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();
}