1 //! Tests for the `cargo tree` command.
3 use cargo_test_support
::cross_compile
::{self, alternate}
;
4 use cargo_test_support
::registry
::{Dependency, Package}
;
5 use cargo_test_support
::{basic_manifest, git, project, rustc_host, Project}
;
7 fn make_simple_proj() -> Project
{
8 Package
::new("c", "1.0.0").publish();
9 Package
::new("b", "1.0.0").dep("c", "1.0").publish();
10 Package
::new("a", "1.0.0").dep("b", "1.0").publish();
11 Package
::new("bdep", "1.0.0").dep("b", "1.0").publish();
12 Package
::new("devdep", "1.0.0").dep("b", "1.0.0").publish();
33 .file("src/lib.rs", "")
34 .file("build.rs", "fn main() {}")
40 // A simple test with a few different dependencies.
41 let p
= make_simple_proj();
61 p
.cargo("tree -p bdep")
73 fn virtual_workspace() {
74 // Multiple packages in a virtual workspace.
75 Package
::new("somedep", "1.0.0").publish();
81 members = ["a", "b", "c"]
84 .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
85 .file("a/src/lib.rs", "")
98 .file("b/src/lib.rs", "")
99 .file("c/Cargo.toml", &basic_manifest("c", "1.0.0"))
100 .file("c/src/lib.rs", "")
106 a v1.0.0 ([..]/foo/a)
108 b v0.1.0 ([..]/foo/b)
109 ├── c v1.0.0 ([..]/foo/c)
112 c v1.0.0 ([..]/foo/c)
117 p
.cargo("tree -p a").with_stdout("a v1.0.0 [..]").run();
123 b v0.1.0 ([..]/foo/b)
124 ├── c v1.0.0 ([..]/foo/c)
133 // Works around https://github.com/rust-lang/cargo/issues/7985
134 Package
::new("bitflags", "1.0.0").publish();
135 Package
::new("manyfeat", "1.0.0")
139 .dep("bitflags", "1.0")
141 Package
::new("a", "1.0.0")
142 .feature_dep("manyfeat", "1.0", &["f1"])
144 Package
::new("b", "1.0.0")
145 .feature_dep("manyfeat", "1.0", &["f2"])
147 Package
::new("c", "1.0.0")
148 .feature_dep("manyfeat", "1.0", &["f3"])
165 .file("src/lib.rs", "")
171 foo v0.1.0 ([..]/foo)
173 │ └── manyfeat v1.0.0
174 │ └── bitflags v1.0.0
176 │ └── manyfeat v1.0.0 (*)
178 └── manyfeat v1.0.0 (*)
186 // Handles renamed dependencies.
187 Package
::new("one", "1.0.0").publish();
188 Package
::new("two", "1.0.0").publish();
189 Package
::new("bar", "1.0.0").dep("one", "1.0").publish();
190 Package
::new("bar", "2.0.0").dep("two", "1.0").publish();
200 bar1 = {version = "1.0", package="bar"}
201 bar2 = {version = "2.0", package="bar"}
204 .file("src/lib.rs", "")
210 foo v1.0.0 ([..]/foo)
222 // Handles git and path sources.
223 Package
::new("regdep", "1.0.0").publish();
224 let git_project
= git
::new("gitdep", |p
| {
225 p
.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0"))
226 .file("src/lib.rs", "")
239 pathdep = {{ path = "pathdep" }}
240 gitdep = {{ git = "{}" }}
245 .file("src
/lib
.rs
", "")
246 .file("pathdep
/Cargo
.toml
", &basic_manifest("pathdep
", "1.0.0"))
247 .file("pathdep
/src
/lib
.rs
", "")
253 foo v0
.1
.0 ([..]/foo
)
254 ├── gitdep v1
.0
.0 (file
://[..]/gitdep#[..])
255 ├── pathdep v1
.0
.0 ([..]/foo
/pathdep
)
264 // Exercises a variety of feature behaviors.
265 Package::new("optdep_default
", "1.0.0").publish();
266 Package::new("optdep
", "1.0.0").publish();
276 optdep_default
= { version = "1.0", optional = true }
277 optdep
= { version = "1.0", optional = true }
280 default = ["optdep_default"]
283 .file("src
/lib
.rs
", "")
290 └── optdep_default v1
.0
.0
295 p.cargo("tree
--no
-default-features
")
303 p.cargo("tree
--all
-features
")
308 └── optdep_default v1
.0
.0
313 p.cargo("tree
--features optdep
")
318 └── optdep_default v1
.0
.0
325 fn filters_target() {
327 if cross_compile::disabled() {
330 Package::new("targetdep
", "1.0.0").publish();
331 Package::new("hostdep
", "1.0.0").publish();
332 Package::new("devdep
", "1.0.0").publish();
333 Package::new("build_target_dep
", "1.0.0").publish();
334 Package::new("build_host_dep
", "1.0.0")
335 .target_dep("targetdep
", "1.0", alternate())
336 .target_dep("hostdep
", "1.0", &rustc_host())
338 Package::new("pm_target
", "1.0.0")
341 Package::new("pm_host
", "1.0.0").proc_macro(true).publish();
352 [target
.'{alt}'
.dependencies
]
356 [target
.'{host}'
.dependencies
]
360 [target
.'{alt}'
.dev
-dependencies
]
363 [target
.'{alt}'
.build
-dependencies
]
364 build_target_dep
= "1.0"
366 [target
.'{host}'
.build
-dependencies
]
367 build_host_dep
= "1.0"
373 .file("src
/lib
.rs
", "")
374 .file("build
.rs
", "fn main() {}
")
380 foo v0
.1
.0 ([..]/foo
)
384 └── build_host_dep v1
.0
.0
390 p.cargo("tree
--target
")
394 foo v0
.1
.0 ([..]/foo
)
398 └── build_host_dep v1
.0
.0
406 p.cargo("tree
--target
")
410 foo v0
.1
.0 ([..]/foo
)
414 └── build_host_dep v1
.0
.0
420 p.cargo("tree
--target
=all
")
423 foo v0
.1
.0 ([..]/foo
)
429 ├── build_host_dep v1
.0
.0
431 │ └── targetdep v1
.0
.0
432 └── build_target_dep v1
.0
.0
442 Package::new("inner
-devdep
", "1.0.0").publish();
443 Package::new("inner
-builddep
", "1.0.0").publish();
444 Package::new("inner
-normal
", "1.0.0").publish();
445 Package::new("normaldep
", "1.0.0")
446 .dep("inner
-normal
", "1.0")
447 .dev_dep("inner
-devdep
", "1.0")
448 .build_dep("inner
-builddep
", "1.0")
450 Package::new("devdep
", "1.0.0")
451 .dep("inner
-normal
", "1.0")
452 .dev_dep("inner
-devdep
", "1.0")
453 .build_dep("inner
-builddep
", "1.0")
455 Package::new("builddep
", "1.0.0")
456 .dep("inner
-normal
", "1.0")
457 .dev_dep("inner
-devdep
", "1.0")
458 .build_dep("inner
-builddep
", "1.0")
478 .file("src
/lib
.rs
", "")
484 foo v0
.1
.0 ([..]/foo
)
486 └── inner
-normal v1
.0
.0
488 └── inner
-builddep v1
.0
.0
491 └── inner
-normal v1
.0
.0
493 └── inner
-builddep v1
.0
.0
496 └── inner
-normal v1
.0
.0
498 └── inner
-builddep v1
.0
.0
503 p.cargo("tree
-e no
-dev
")
506 foo v0
.1
.0 ([..]/foo
)
508 └── inner
-normal v1
.0
.0
510 └── inner
-builddep v1
.0
.0
513 └── inner
-normal v1
.0
.0
515 └── inner
-builddep v1
.0
.0
520 p.cargo("tree
-e normal
")
523 foo v0
.1
.0 ([..]/foo
)
525 └── inner
-normal v1
.0
.0
530 p.cargo("tree
-e dev
,build
")
533 foo v0
.1
.0 ([..]/foo
)
537 └── inner
-builddep v1
.0
.0
541 └── inner
-builddep v1
.0
.0
548 fn cyclic_dev_dep() {
549 // Cyclical dev-dependency and inverse flag.
559 dev
-dep
= { path = "dev-dep" }
562 .file("src
/lib
.rs
", "")
564 "dev
-dep
/Cargo
.toml
",
574 .file("dev
-dep
/src
/lib
.rs
", "")
580 foo v0
.1
.0 ([..]/foo
)
582 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
583 └── foo v0
.1
.0 ([..]/foo
) (*)
588 p.cargo("tree
--invert foo
")
591 foo v0
.1
.0 ([..]/foo
)
592 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
594 └── foo v0
.1
.0 ([..]/foo
) (*)
602 Package::new("b1
", "1.0.0").dep("c
", "1.0").publish();
603 Package::new("b2
", "1.0.0").dep("d
", "1.0").publish();
604 Package::new("c
", "1.0.0").publish();
605 Package::new("d
", "1.0.0").publish();
620 .file("src
/lib
.rs
", "")
626 foo v0
.1
.0 ([..]/foo
)
636 p.cargo("tree
--invert c
")
641 │ └── foo v0
.1
.0 ([..]/foo
)
642 └── foo v0
.1
.0 ([..]/foo
)
649 fn invert_with_build_dep() {
650 // -i for a common dependency between normal and build deps.
651 Package::new("common
", "1.0.0").publish();
652 Package::new("bdep
", "1.0.0").dep("common
", "1.0").publish();
668 .file("src
/lib
.rs
", "")
674 foo v0
.1
.0 ([..]/foo
)
683 p.cargo("tree
-i common
")
688 │
[build
-dependencies
]
689 │ └── foo v0
.1
.0 ([..]/foo
)
690 └── foo v0
.1
.0 ([..]/foo
)
698 let p = make_simple_proj();
700 p.cargo("tree
--prefix
=none
")
703 foo v0
.1
.0 ([..]/foo
)
719 let p = make_simple_proj();
721 p.cargo("tree
--prefix
=depth
")
724 0foo v0
.1
.0 ([..]/foo
)
740 let p = make_simple_proj();
742 p.cargo("tree
--no
-dedupe
")
745 foo v0
.1
.0 ([..]/foo
)
764 fn no_dedupe_cycle() {
765 // --no-dedupe with a dependency cycle
778 .file("src
/lib
.rs
", "")
790 .file("bar
/src
/lib
.rs
", "")
796 foo v0
.1
.0 ([..]/foo
)
798 └── bar v0
.1
.0 ([..]/foo
/bar
)
799 └── foo v0
.1
.0 ([..]/foo
) (*)
804 p.cargo("tree
--no
-dedupe
")
807 foo v0
.1
.0 ([..]/foo
)
809 └── bar v0
.1
.0 ([..]/foo
/bar
)
810 └── foo v0
.1
.0 ([..]/foo
) (*)
818 Package::new("dog
", "1.0.0").publish();
819 Package::new("dog
", "2.0.0").publish();
820 Package::new("cat
", "1.0.0").publish();
821 Package::new("cat
", "2.0.0").publish();
822 Package::new("dep
", "1.0.0")
842 dog1
= { version = "1.0", package = "dog" }
843 dog2
= { version = "2.0", package = "dog" }
846 .file("a
/src
/lib
.rs
", "")
859 .file("b
/src
/lib
.rs
", "")
865 a v0
.1
.0 ([..]/foo
/a
)
875 b v0
.1
.0 ([..]/foo
/b
)
884 p.cargo("tree
-p a
-d
")
888 └── a v0
.1
.0 ([..]/foo
/a
)
891 └── a v0
.1
.0 ([..]/foo
/a
)
896 p.cargo("tree
-p b
-d
")
901 └── b v0
.1
.0 ([..]/foo
/b
)
904 └── b v0
.1
.0 ([..]/foo
/b
)
912 let p = make_simple_proj();
913 p.cargo("tree
--charset ascii
")
916 foo v0
.1
.0 ([..]/foo
)
934 Package::new("dep
", "1.0.0").publish();
943 repository
= "https://github.com/rust-lang/cargo"
946 dep
= {version="1.0", optional=true}
954 .file("src
/lib
.rs
", "")
957 p.cargo("tree
--format
<<<{p}
>>>")
958 .with_stdout("<<<foo v0
.1
.0 ([..]/foo
)>>>")
961 p.cargo("tree
--format {}
")
964 [ERROR
] tree format `{}` not valid
967 unsupported pattern ``
973 p.cargo("tree
--format {p}
-{{hello}
}")
974 .with_stdout("foo v0
.1
.0 ([..]/foo
)-{hello}
")
977 p.cargo("tree
--format
")
979 .with_stdout("foo v0
.1
.0 ([..]/foo
) MIT https
://github.com/rust-lang/cargo")
982 p
.cargo("tree --format")
984 .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo")
987 p
.cargo("tree --all-features --format")
991 foo v0.1.0 ([..]/foo) [bar,default,dep,foo]
999 fn dev_dep_feature() {
1000 // -Zfeatures=dev_dep with optional dep
1001 Package
::new("optdep", "1.0.0").publish();
1002 Package
::new("bar", "1.0.0")
1003 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1014 bar = { version = "1.0", features = ["optdep"] }
1020 .file("src/lib.rs", "")
1026 foo v0.1.0 ([..]/foo)
1035 p
.cargo("tree -e normal")
1038 foo v0.1.0 ([..]/foo)
1045 p
.cargo("tree -Zfeatures=dev_dep")
1046 .masquerade_as_nightly_cargo()
1049 foo v0.1.0 ([..]/foo)
1058 p
.cargo("tree -e normal -Zfeatures=dev_dep")
1059 .masquerade_as_nightly_cargo()
1062 foo v0.1.0 ([..]/foo)
1070 fn host_dep_feature() {
1071 // -Zfeatures=host_dep with optional dep
1072 Package
::new("optdep", "1.0.0").publish();
1073 Package
::new("bar", "1.0.0")
1074 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1084 [build-dependencies]
1085 bar = { version = "1.0", features = ["optdep"] }
1091 .file("src/lib.rs", "")
1092 .file("build.rs", "fn main() {}")
1098 foo v0.1.0 ([..]/foo)
1101 [build-dependencies]
1107 p
.cargo("tree -Zfeatures=host_dep")
1108 .masquerade_as_nightly_cargo()
1111 foo v0.1.0 ([..]/foo)
1113 [build-dependencies]
1121 p
.cargo("tree -p bar")
1130 p
.cargo("tree -p bar -Zfeatures=host_dep")
1131 .masquerade_as_nightly_cargo()
1143 p
.cargo("tree -i optdep")
1148 └── foo v0.1.0 ([..]/foo)
1149 [build-dependencies]
1150 └── foo v0.1.0 ([..]/foo)
1155 p
.cargo("tree -i optdep -Zfeatures=host_dep")
1156 .masquerade_as_nightly_cargo()
1161 [build-dependencies]
1162 └── foo v0.1.0 ([..]/foo)
1167 // Check that -d handles duplicates with features.
1168 p
.cargo("tree -d -Zfeatures=host_dep")
1169 .masquerade_as_nightly_cargo()
1173 └── foo v0.1.0 ([..]/foo)
1176 [build-dependencies]
1177 └── foo v0.1.0 ([..]/foo)
1184 fn proc_macro_features() {
1185 // -Zfeatures=host_dep with a proc-macro
1186 Package
::new("optdep", "1.0.0").publish();
1187 Package
::new("somedep", "1.0.0")
1188 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1190 Package
::new("pm", "1.0.0")
1192 .feature_dep("somedep", "1.0", &["optdep"])
1207 .file("src/lib.rs", "")
1213 foo v0.1.0 ([..]/foo)
1215 │ └── somedep v1.0.0
1217 └── somedep v1.0.0 (*)
1222 // Note the missing (*)
1223 p
.cargo("tree -Zfeatures=host_dep")
1224 .masquerade_as_nightly_cargo()
1227 foo v0.1.0 ([..]/foo)
1229 │ └── somedep v1.0.0
1237 p
.cargo("tree -p somedep")
1246 p
.cargo("tree -p somedep -Zfeatures=host_dep")
1247 .masquerade_as_nightly_cargo()
1259 p
.cargo("tree -i somedep")
1263 ├── foo v0.1.0 ([..]/foo)
1265 └── foo v0.1.0 ([..]/foo)
1270 p
.cargo("tree -i somedep -Zfeatures=host_dep")
1271 .masquerade_as_nightly_cargo()
1275 └── foo v0.1.0 ([..]/foo)
1279 └── foo v0.1.0 ([..]/foo)
1286 fn itarget_opt_dep() {
1287 // -Zfeatures=itarget with optional dep
1288 Package
::new("optdep", "1.0.0").publish();
1289 Package
::new("common", "1.0.0")
1290 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1304 [target.'cfg(whatever)'.dependencies]
1305 common = { version = "1.0", features = ["optdep"] }
1309 .file("src/lib.rs", "")
1315 foo v1.0.0 ([..]/foo)
1322 p
.cargo("tree -Zfeatures=itarget")
1325 foo v1.0.0 ([..]/foo)
1329 .masquerade_as_nightly_cargo()
1334 fn ambiguous_name() {
1335 // -p that is ambiguous.
1336 Package
::new("dep", "1.0.0").publish();
1337 Package
::new("dep", "2.0.0").publish();
1338 Package
::new("bar", "1.0.0").dep("dep", "2.0").publish();
1352 .file("src/lib.rs", "")
1355 p
.cargo("tree -p dep")
1356 .with_stderr_contains(
1358 error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
1359 Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
1369 fn workspace_features_are_local() {
1370 // The features for workspace packages should be the same as `cargo build`
1371 // (i.e., the features selected depend on the "current" package).
1372 Package
::new("optdep", "1.0.0").publish();
1373 Package
::new("somedep", "1.0.0")
1374 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1381 members = ["a", "b"]
1392 somedep = {version="1.0", features=["optdep"]}
1395 .file("a/src/lib.rs", "")
1407 .file("b/src/lib.rs", "")
1413 a v0.1.0 ([..]/foo/a)
1417 b v0.1.0 ([..]/foo/b)
1418 └── somedep v1.0.0 (*)
1423 p
.cargo("tree -p a")
1426 a v0.1.0 ([..]/foo/a)
1433 p
.cargo("tree -p b")
1436 b v0.1.0 ([..]/foo/b)