cargo/tests/testsuite/metadata.rs
bors 77f2da7b92 Auto merge of #12914 - epage:metadata, r=weihanglo
fix(metadata): Stabilize id format as PackageIDSpec

### What does this PR try to resolve?

For tools integrating with cargo, `cargo metadata` is the primary interface.  Limitations include:
-  There isn't an unambiguous way to map a package entry from `cargo metadata`  to a parameter to pass to other `cargo` commands.  An `id` field exists but it is documented as an opaque string, useful only for comparisons with other `id`s within the document.
- There isn't an unambiguous way of taking user parameters (`--package`) and mapping them to `cargo metadata` entries.  `cargo pkgid` could help but it returns a `PackageIdSpec` which doesn't exist within the `cargo metadata` output.

This attempts to solve these problems by switching the `id` field from `PackageId` to `PackageIdSpec` which is a [publicly documented format](https://doc.rust-lang.org/cargo/reference/pkgid-spec.html), can be generated by `cargo pkgid`, and is accepted by most commands via the `--package` flag.

As the `"id"` field is documented as opaque, this technically isn't a breaking change though people could be parsing it.

For `cargo_metadata` they do [use a new type that documents it as opaque but publicly expose the inner `String`](https://docs.rs/cargo_metadata/latest/cargo_metadata/struct.PackageId.html).  The `String` wasn't publicly exposed due to a request by users but instead their `PackageId` type replaced using `String`s in the API in oli-obk/cargo_metadata#59 with no indication given as to why the `String` was still exposed.  However, you'll note that before that PR, they had `WorkspaceMember` that parsed `PackageId`.  This was introduced in oli-obk/cargo_metadata#26 without a motivation given.

**Note that `PackageIdSpec` has multiple representation that might uniquely identify a package and we can return any one of them.**

Fixes #7267

### How should we test and review this PR?

### Additional information

cc `@oli-obk`
2024-01-15 15:45:36 +00:00

4545 lines
136 KiB
Rust

//! Tests for the `cargo metadata` command.
use cargo_test_support::install::cargo_home;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, main_file, project, rustc_host};
use serde_json::json;
#[cargo_test]
fn cargo_metadata_simple() {
let p = project()
.file("src/foo.rs", "")
.file("Cargo.toml", &basic_bin_manifest("foo"))
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name": "foo",
"version": "0.5.0",
"id": "[..]foo#0.5.0",
"keywords": [],
"source": null,
"dependencies": [],
"edition": "2015",
"license": null,
"license_file": null,
"links": null,
"description": null,
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"homepage": null,
"documentation": null,
"targets": [
{
"kind": [
"bin"
],
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]/foo/src/foo.rs"
}
],
"features": {},
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": ["path+file:[..]foo#0.5.0"],
"workspace_default_members": ["path+file:[..]foo#0.5.0"],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]foo#0.5.0"
}
],
"root": "path+file:[..]foo#0.5.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_warns_on_implicit_version() {
let p = project()
.file("src/foo.rs", "")
.file("Cargo.toml", &basic_bin_manifest("foo"))
.build();
p.cargo("metadata").with_stderr("[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems").run();
p.cargo("metadata --format-version 1").with_stderr("").run();
}
#[cargo_test]
fn library_with_several_crate_types() {
let p = project()
.file("src/lib.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
[lib]
crate-type = ["lib", "staticlib"]
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"name": "foo",
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"version": "0.5.0",
"rust_version": null,
"id": "[..]foo#0.5.0",
"keywords": [],
"source": null,
"dependencies": [],
"edition": "2015",
"license": null,
"license_file": null,
"links": null,
"description": null,
"targets": [
{
"kind": [
"lib",
"staticlib"
],
"crate_types": [
"lib",
"staticlib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]/foo/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": ["path+file:[..]foo#0.5.0"],
"workspace_default_members": ["path+file:[..]foo#0.5.0"],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]foo#0.5.0"
}
],
"root": "path+file:[..]foo#0.5.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn library_with_features() {
let p = project()
.file("src/lib.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
[features]
default = ["default_feat"]
default_feat = []
optional_feat = []
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.5.0",
"id": "[..]foo#0.5.0",
"keywords": [],
"source": null,
"dependencies": [],
"edition": "2015",
"license": null,
"license_file": null,
"links": null,
"description": null,
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]/foo/src/lib.rs"
}
],
"features": {
"default": [
"default_feat"
],
"default_feat": [],
"optional_feat": []
},
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": ["path+file:[..]foo#0.5.0"],
"workspace_default_members": ["path+file:[..]foo#0.5.0"],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [
"default",
"default_feat"
],
"id": "path+file:[..]foo#0.5.0"
}
],
"root": "path+file:[..]foo#0.5.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_deps_and_version() {
let p = project()
.file("src/foo.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
authors = []
license = "MIT"
description = "foo"
[[bin]]
name = "foo"
[dependencies]
bar = "*"
[dev-dependencies]
foobar = "*"
"#,
)
.build();
Package::new("baz", "0.0.1").publish();
Package::new("foobar", "0.0.1").publish();
Package::new("bar", "0.0.1").dep("baz", "0.0.1").publish();
p.cargo("metadata -q --format-version 1")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [
{
"features": [],
"kind": null,
"name": "baz",
"optional": false,
"registry": null,
"rename": null,
"req": "^0.0.1",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"target": null,
"uses_default_features": true
}
],
"description": null,
"edition": "2015",
"features": {},
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "bar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]src/lib.rs"
}
],
"version": "0.0.1"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "baz",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "baz",
"src_path": "[..]src/lib.rs"
}
],
"version": "0.0.1"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [
{
"features": [],
"kind": null,
"name": "bar",
"optional": false,
"registry": null,
"rename": null,
"req": "*",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": "dev",
"name": "foobar",
"optional": false,
"registry": null,
"rename": null,
"req": "*",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"target": null,
"uses_default_features": true
}
],
"description": "foo",
"edition": "2015",
"features": {},
"id": "path+file:[..]foo#0.5.0",
"keywords": [],
"license": "MIT",
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"test": true,
"edition": "2015",
"kind": [
"bin"
],
"name": "foo",
"src_path": "[..]src/foo.rs"
}
],
"version": "0.5.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "foobar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "foobar",
"src_path": "[..]src/lib.rs"
}
],
"version": "0.0.1"
}
],
"resolve": {
"nodes": [
{
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1"
],
"deps": [
{
"dep_kinds": [
{
"kind": null,
"target": null
}
],
"name": "baz",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1"
}
],
"features": [],
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1"
},
{
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1"
],
"deps": [
{
"dep_kinds": [
{
"kind": null,
"target": null
}
],
"name": "bar",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1"
},
{
"dep_kinds": [
{
"kind": "dev",
"target": null
}
],
"name": "foobar",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1"
}
],
"features": [],
"id": "path+file:[..]foo#0.5.0"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1"
}
],
"root": "path+file:[..]foo#0.5.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_members": [
"path+file:[..]foo#0.5.0"
],
"workspace_default_members": [
"path+file:[..]foo#0.5.0"
],
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn example() {
let p = project()
.file("src/lib.rs", "")
.file("examples/ex.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[example]]
name = "ex"
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.1.0",
"id": "[..]foo#0.1.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"source": null,
"dependencies": [],
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]/foo/src/lib.rs"
},
{
"kind": [ "example" ],
"crate_types": [ "bin" ],
"doc": false,
"doctest": false,
"test": false,
"edition": "2015",
"name": "ex",
"src_path": "[..]/foo/examples/ex.rs"
}
],
"features": {},
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": [
"path+file:[..]foo#0.1.0"
],
"workspace_default_members": [
"path+file:[..]foo#0.1.0"
],
"resolve": {
"root": "path+file://[..]foo#0.1.0",
"nodes": [
{
"id": "path+file:[..]foo#0.1.0",
"features": [],
"dependencies": [],
"deps": []
}
]
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn example_lib() {
let p = project()
.file("src/lib.rs", "")
.file("examples/ex.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[example]]
name = "ex"
crate-type = ["rlib", "dylib"]
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.1.0",
"id": "[..]foo#0.1.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"source": null,
"dependencies": [],
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]/foo/src/lib.rs"
},
{
"kind": [ "example" ],
"crate_types": [ "rlib", "dylib" ],
"doc": false,
"doctest": false,
"test": false,
"edition": "2015",
"name": "ex",
"src_path": "[..]/foo/examples/ex.rs"
}
],
"features": {},
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": [
"path+file:[..]foo#0.1.0"
],
"workspace_default_members": [
"path+file:[..]foo#0.1.0"
],
"resolve": {
"root": "path+file://[..]foo#0.1.0",
"nodes": [
{
"id": "path+file:[..]foo#0.1.0",
"features": [],
"dependencies": [],
"deps": []
}
]
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn workspace_metadata() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
[workspace.metadata]
tool1 = "hello"
tool2 = [1, 2, 3]
[workspace.metadata.foo]
bar = 3
"#,
)
.file("bar/Cargo.toml", &basic_lib_manifest("bar"))
.file("bar/src/lib.rs", "")
.file("baz/Cargo.toml", &basic_lib_manifest("baz"))
.file("baz/src/lib.rs", "")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name": "bar",
"version": "0.5.0",
"id": "[..]bar#0.5.0",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"keywords": [],
"source": null,
"dependencies": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "bar",
"src_path": "[..]bar/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]bar/Cargo.toml",
"metadata": null,
"publish": null
},
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name": "baz",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.5.0",
"id": "[..]baz#0.5.0",
"keywords": [],
"source": null,
"dependencies": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "baz",
"src_path": "[..]baz/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]baz/Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": [
"path+file:[..]bar#0.5.0",
"path+file:[..]baz#0.5.0"
],
"workspace_default_members": [
"path+file:[..]bar#0.5.0",
"path+file:[..]baz#0.5.0"
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]bar#0.5.0"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]baz#0.5.0"
}
],
"root": null
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": {
"tool1": "hello",
"tool2": [1, 2, 3],
"foo": {
"bar": 3
}
}
}"#,
)
.run();
}
#[cargo_test]
fn workspace_metadata_with_dependencies_no_deps() {
let p = project()
// NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member.
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
"#,
)
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.5.0"
authors = ["wycats@example.com"]
[dependencies]
baz = { path = "../baz/" }
artifact = { path = "../artifact/", artifact = "bin" }
"#,
)
.file("bar/src/lib.rs", "")
.file("baz/Cargo.toml", &basic_lib_manifest("baz"))
.file("baz/src/lib.rs", "")
.file("artifact/Cargo.toml", &basic_bin_manifest("artifact"))
.file("artifact/src/main.rs", "fn main() {}")
.build();
p.cargo("metadata --no-deps -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name": "bar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.5.0",
"id": "[..]bar#0.5.0",
"keywords": [],
"source": null,
"license": null,
"dependencies": [
{
"features": [],
"kind": null,
"name": "artifact",
"optional": false,
"path": "[..]/foo/artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true,
"artifact": {
"kinds": [
"bin"
],
"lib": false,
"target": null
}
},
{
"features": [],
"kind": null,
"name": "baz",
"optional": false,
"path": "[..]/foo/baz",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
}
],
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "bar",
"src_path": "[..]bar/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]bar/Cargo.toml",
"metadata": null,
"publish": null
},
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file:[..]/foo/artifact#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/artifact/Cargo.toml",
"metadata": null,
"name": "artifact",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "artifact",
"src_path": "[..]/foo/artifact/src/main.rs",
"test": true
}
],
"version": "0.5.0"
},
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name": "baz",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.5.0",
"id": "[..]baz#0.5.0",
"keywords": [],
"source": null,
"dependencies": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"targets": [
{
"kind": [ "lib" ],
"crate_types": ["lib"],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "baz",
"src_path": "[..]baz/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]baz/Cargo.toml",
"metadata": null,
"publish": null
}
],
"workspace_members": [
"path+file:[..]bar#0.5.0",
"path+file:[..]/foo/artifact#0.5.0",
"path+file:[..]baz#0.5.0"
],
"workspace_default_members": [
"path+file:[..]bar#0.5.0",
"path+file:[..]/foo/artifact#0.5.0",
"path+file:[..]baz#0.5.0"
],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn workspace_metadata_with_dependencies_and_resolve() {
let alt_target = "wasm32-unknown-unknown";
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "artifact", "non-artifact", "bin-only-artifact"]
"#,
)
.file(
"bar/Cargo.toml",
&r#"
[package]
name = "bar"
version = "0.5.0"
authors = []
[build-dependencies]
artifact = { path = "../artifact/", artifact = "bin", target = "target" }
bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin", target = "$ALT_TARGET" }
non-artifact = { path = "../non-artifact" }
[dependencies]
artifact = { path = "../artifact/", artifact = ["cdylib", "staticlib", "bin:baz-name"], lib = true, target = "$ALT_TARGET" }
bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin:a-name" }
non-artifact = { path = "../non-artifact" }
[dev-dependencies]
artifact = { path = "../artifact/" }
non-artifact = { path = "../non-artifact" }
bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin:b-name" }
"#.replace("$ALT_TARGET", alt_target),
)
.file("bar/src/lib.rs", "")
.file("bar/build.rs", "fn main() {}")
.file(
"artifact/Cargo.toml",
r#"
[package]
name = "artifact"
version = "0.5.0"
authors = []
[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
[[bin]]
name = "bar-name"
[[bin]]
name = "baz-name"
"#,
)
.file("artifact/src/main.rs", "fn main() {}")
.file("artifact/src/lib.rs", "")
.file(
"bin-only-artifact/Cargo.toml",
r#"
[package]
name = "bin-only-artifact"
version = "0.5.0"
authors = []
[[bin]]
name = "a-name"
[[bin]]
name = "b-name"
"#,
)
.file("bin-only-artifact/src/main.rs", "fn main() {}")
.file("non-artifact/Cargo.toml",
r#"
[package]
name = "non-artifact"
version = "0.5.0"
authors = []
"#,
)
.file("non-artifact/src/lib.rs", "")
.build();
p.cargo("metadata -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
.with_json(
r#"
{
"metadata": null,
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/artifact#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/artifact/Cargo.toml",
"metadata": null,
"name": "artifact",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"staticlib",
"cdylib",
"rlib"
],
"doc": true,
"doctest": true,
"edition": "2015",
"kind": [
"staticlib",
"cdylib",
"rlib"
],
"name": "artifact",
"src_path": "[..]/foo/artifact/src/lib.rs",
"test": true
},
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "bar-name",
"src_path": "[..]/foo/artifact/src/main.rs",
"test": true
},
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "baz-name",
"src_path": "[..]/foo/artifact/src/main.rs",
"test": true
}
],
"version": "0.5.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [
{
"artifact": {
"kinds": [
"cdylib",
"staticlib",
"bin:baz-name"
],
"lib": true,
"target": "wasm32-unknown-unknown"
},
"features": [],
"kind": null,
"name": "artifact",
"optional": false,
"path": "[..]/foo/artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"artifact": {
"kinds": [
"bin:a-name"
],
"lib": false,
"target": null
},
"features": [],
"kind": null,
"name": "bin-only-artifact",
"optional": false,
"path": "[..]/foo/bin-only-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": null,
"name": "non-artifact",
"optional": false,
"path": "[..]/foo/non-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": "dev",
"name": "artifact",
"optional": false,
"path": "[..]/foo/artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"artifact": {
"kinds": [
"bin:b-name"
],
"lib": false,
"target": null
},
"features": [],
"kind": "dev",
"name": "bin-only-artifact",
"optional": false,
"path": "[..]/foo/bin-only-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": "dev",
"name": "non-artifact",
"optional": false,
"path": "[..]/foo/non-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"artifact": {
"kinds": [
"bin"
],
"lib": false,
"target": "target"
},
"features": [],
"kind": "build",
"name": "artifact",
"optional": false,
"path": "[..]/foo/artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"artifact": {
"kinds": [
"bin"
],
"lib": false,
"target": "wasm32-unknown-unknown"
},
"features": [],
"kind": "build",
"name": "bin-only-artifact",
"optional": false,
"path": "[..]/foo/bin-only-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": "build",
"name": "non-artifact",
"optional": false,
"path": "[..]/foo/non-artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
}
],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/bar#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/bar/Cargo.toml",
"metadata": null,
"name": "bar",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]/foo/bar/src/lib.rs",
"test": true
},
{
"crate_types": [
"bin"
],
"doc": false,
"doctest": false,
"edition": "2015",
"kind": [
"custom-build"
],
"name": "build-script-build",
"src_path": "[..]/foo/bar/build.rs",
"test": false
}
],
"version": "0.5.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/bin-only-artifact#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/bin-only-artifact/Cargo.toml",
"metadata": null,
"name": "bin-only-artifact",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "a-name",
"src_path": "[..]/foo/bin-only-artifact/src/main.rs",
"test": true
},
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "b-name",
"src_path": "[..]/foo/bin-only-artifact/src/main.rs",
"test": true
}
],
"version": "0.5.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/non-artifact#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/non-artifact/Cargo.toml",
"metadata": null,
"name": "non-artifact",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "non-artifact",
"src_path": "[..]/foo/non-artifact/src/lib.rs",
"test": true
}
],
"version": "0.5.0"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file://[..]/foo/artifact#0.5.0"
},
{
"dependencies": [
"path+file://[..]/foo/artifact#0.5.0",
"path+file://[..]/foo/bin-only-artifact#0.5.0",
"path+file://[..]/foo/non-artifact#0.5.0"
],
"deps": [
{
"dep_kinds": [
{
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"artifact": "cdylib",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"artifact": "staticlib",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"artifact": "bin",
"bin_name": "baz-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "baz_name",
"kind": null,
"target": null
},
{
"kind": "dev",
"target": null
},
{
"artifact": "bin",
"bin_name": "bar-name",
"compile_target": "<target>",
"extern_name": "bar_name",
"kind": "build",
"target": null
},
{
"artifact": "bin",
"bin_name": "baz-name",
"compile_target": "<target>",
"extern_name": "baz_name",
"kind": "build",
"target": null
}
],
"name": "artifact",
"pkg": "path+file://[..]/foo/artifact#0.5.0"
},
{
"dep_kinds": [
{
"artifact": "bin",
"bin_name": "a-name",
"extern_name": "a_name",
"kind": null,
"target": null
},
{
"artifact": "bin",
"bin_name": "b-name",
"extern_name": "b_name",
"kind": "dev",
"target": null
},
{
"artifact": "bin",
"bin_name": "a-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "a_name",
"kind": "build",
"target": null
},
{
"artifact": "bin",
"bin_name": "b-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "b_name",
"kind": "build",
"target": null
}
],
"name": "",
"pkg": "path+file://[..]/foo/bin-only-artifact#0.5.0"
},
{
"dep_kinds": [
{
"kind": null,
"target": null
},
{
"kind": "dev",
"target": null
},
{
"kind": "build",
"target": null
}
],
"name": "non_artifact",
"pkg": "path+file://[..]/foo/non-artifact#0.5.0"
}
],
"features": [],
"id": "path+file://[..]/foo/bar#0.5.0"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file://[..]/foo/bin-only-artifact#0.5.0"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file://[..]/foo/non-artifact#0.5.0"
}
],
"root": null
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_members": [
"path+file://[..]/foo/bar#0.5.0",
"path+file://[..]/foo/artifact#0.5.0",
"path+file://[..]/foo/bin-only-artifact#0.5.0",
"path+file://[..]/foo/non-artifact#0.5.0"
],
"workspace_default_members": [
"path+file://[..]/foo/bar#0.5.0",
"path+file://[..]/foo/artifact#0.5.0",
"path+file://[..]/foo/bin-only-artifact#0.5.0",
"path+file://[..]/foo/non-artifact#0.5.0"
],
"workspace_root": "[..]/foo"
}
"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_manifest() {
let p = project().file("Cargo.toml", "").build();
p.cargo("metadata --format-version 1")
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[..]`
Caused by:
virtual manifests must be configured with [workspace]",
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_authors_field() {
let p = project()
.file("src/foo.rs", "")
.file(
"Cargo.toml",
r#"
[package]
authors = ""
"#,
)
.build();
p.cargo("metadata")
.with_status(101)
.with_stderr(
r#"[ERROR] invalid type: string "", expected a vector of strings or workspace
--> Cargo.toml:3:27
|
3 | authors = ""
| ^^
|
"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_version_field() {
let p = project()
.file("src/foo.rs", "")
.file(
"Cargo.toml",
r#"
[package]
version = 1
"#,
)
.build();
p.cargo("metadata")
.with_status(101)
.with_stderr(
"\
[ERROR] invalid type: integer `1`, expected SemVer version
--> Cargo.toml:3:27
|
3 | version = 1
| ^
|
",
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_publish_field() {
let p = project()
.file("src/foo.rs", "")
.file(
"Cargo.toml",
r#"
[package]
publish = "foo"
"#,
)
.build();
p.cargo("metadata")
.with_status(101)
.with_stderr(
r#"[ERROR] invalid type: string "foo", expected a boolean, a vector of strings, or workspace
--> Cargo.toml:3:27
|
3 | publish = "foo"
| ^^^^^
|
"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_artifact_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
[dependencies]
artifact = { path = "artifact", artifact = "bin:notfound" }
"#,
)
.file("src/lib.rs", "")
.file("artifact/Cargo.toml", &basic_bin_manifest("artifact"))
.file("artifact/src/main.rs", "fn main() {}")
.build();
p.cargo("metadata -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
.with_status(101)
.with_stderr(
"\
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[ERROR] dependency `artifact` in package `foo` requires a `bin:notfound` artifact to be present.",
)
.run();
}
#[cargo_test]
fn cargo_metadata_with_invalid_duplicate_renamed_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
[dependencies]
bar = { path = "bar" }
baz = { path = "bar", package = "bar" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_lib_manifest("bar"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("metadata")
.with_status(101)
.with_stderr(
"\
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[ERROR] the crate `foo v0.5.0 ([..])` depends on crate `bar v0.5.0 ([..])` multiple times with different names",
)
.run();
}
const MANIFEST_OUTPUT: &str = r#"
{
"packages": [{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"name":"foo",
"version":"0.5.0",
"id":"path+file://[..]/foo#0.5.0",
"source":null,
"dependencies":[],
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"description": null,
"edition": "2015",
"targets":[{
"kind":["bin"],
"crate_types":["bin"],
"doc": true,
"doctest": false,
"test": true,
"edition": "2015",
"name":"foo",
"src_path":"[..]/foo/src/foo.rs"
}],
"features":{},
"manifest_path":"[..]Cargo.toml",
"metadata": null,
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null
}],
"workspace_members": [ "path+file:[..]foo#0.5.0" ],
"workspace_default_members": [ "path+file:[..]foo#0.5.0" ],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#;
#[cargo_test]
fn cargo_metadata_no_deps_path_to_cargo_toml_relative() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps --manifest-path foo/Cargo.toml")
.cwd(p.root().parent().unwrap())
.with_json(MANIFEST_OUTPUT)
.run();
}
#[cargo_test]
fn cargo_metadata_no_deps_path_to_cargo_toml_absolute() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps --manifest-path")
.arg(p.root().join("Cargo.toml"))
.cwd(p.root().parent().unwrap())
.with_json(MANIFEST_OUTPUT)
.run();
}
#[cargo_test]
fn cargo_metadata_no_deps_path_to_cargo_toml_parent_relative() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps --manifest-path foo")
.cwd(p.root().parent().unwrap())
.with_status(101)
.with_stderr(
"[ERROR] the manifest-path must be \
a path to a Cargo.toml file",
)
.run();
}
#[cargo_test]
fn cargo_metadata_no_deps_path_to_cargo_toml_parent_absolute() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps --manifest-path")
.arg(p.root())
.cwd(p.root().parent().unwrap())
.with_status(101)
.with_stderr(
"[ERROR] the manifest-path must be \
a path to a Cargo.toml file",
)
.run();
}
#[cargo_test]
fn cargo_metadata_no_deps_cwd() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps")
.with_json(MANIFEST_OUTPUT)
.run();
}
#[cargo_test]
fn cargo_metadata_bad_version() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.build();
p.cargo("metadata --no-deps --format-version 2")
.with_status(1)
.with_stderr_contains(
"\
error: invalid value '2' for '--format-version <VERSION>'
[possible values: 1]
",
)
.run();
}
#[cargo_test]
fn multiple_features() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []
[features]
a = []
b = []
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("metadata --features").arg("a b").run();
}
#[cargo_test]
fn package_metadata() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
categories = ["database"]
keywords = ["database"]
readme = "README.md"
repository = "https://github.com/rust-lang/cargo"
homepage = "https://rust-lang.org"
documentation = "https://doc.rust-lang.org/stable/std/"
[package.metadata.bar]
baz = "quux"
"#,
)
.file("README.md", "")
.file("src/lib.rs", "")
.build();
p.cargo("metadata --no-deps")
.with_json(
r#"
{
"packages": [
{
"authors": ["wycats@example.com"],
"categories": ["database"],
"default_run": null,
"name": "foo",
"readme": "README.md",
"repository": "https://github.com/rust-lang/cargo",
"rust_version": null,
"homepage": "https://rust-lang.org",
"documentation": "https://doc.rust-lang.org/stable/std/",
"version": "0.1.0",
"id": "[..]foo#0.1.0",
"keywords": ["database"],
"source": null,
"dependencies": [],
"edition": "2015",
"license": null,
"license_file": null,
"links": null,
"description": null,
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]foo/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]foo/Cargo.toml",
"metadata": {
"bar": {
"baz": "quux"
}
},
"publish": null
}
],
"workspace_members": ["[..]foo#0.1.0"],
"workspace_default_members": ["[..]foo#0.1.0"],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn package_publish() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
categories = ["database"]
keywords = ["database"]
readme = "README.md"
repository = "https://github.com/rust-lang/cargo"
publish = ["my-registry"]
"#,
)
.file("README.md", "")
.file("src/lib.rs", "")
.build();
p.cargo("metadata --no-deps")
.with_json(
r#"
{
"packages": [
{
"authors": ["wycats@example.com"],
"categories": ["database"],
"default_run": null,
"name": "foo",
"readme": "README.md",
"repository": "https://github.com/rust-lang/cargo",
"rust_version": null,
"homepage": null,
"documentation": null,
"version": "0.1.0",
"id": "[..]foo#0.1.0",
"keywords": ["database"],
"source": null,
"dependencies": [],
"edition": "2015",
"license": null,
"license_file": null,
"links": null,
"description": null,
"targets": [
{
"kind": [ "lib" ],
"crate_types": [ "lib" ],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"name": "foo",
"src_path": "[..]foo/src/lib.rs"
}
],
"features": {},
"manifest_path": "[..]foo/Cargo.toml",
"metadata": null,
"publish": ["my-registry"]
}
],
"workspace_members": ["[..]foo#0.1.0"],
"workspace_default_members": ["[..]foo#0.1.0"],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn cargo_metadata_path_to_cargo_toml_project() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar"]
"#,
)
.file("bar/Cargo.toml", &basic_lib_manifest("bar"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("package --manifest-path")
.arg(p.root().join("bar/Cargo.toml"))
.cwd(p.root().parent().unwrap())
.run();
p.cargo("metadata --manifest-path")
.arg(p.root().join("target/package/bar-0.5.0/Cargo.toml"))
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "[..]#bar@0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "bar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]src/lib.rs"
}
],
"version": "0.5.0"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "[..]#bar@0.5.0"
}
],
"root": "path+file:[..]#bar@0.5.0"
},
"target_directory": "[..]",
"version": 1,
"workspace_members": [
"path+file:[..]#bar@0.5.0"
],
"workspace_default_members": [
"path+file:[..]#bar@0.5.0"
],
"workspace_root": "[..]",
"metadata": null
}
"#,
)
.run();
}
#[cargo_test]
fn package_edition_2018() {
let p = project()
.file("src/lib.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
edition = "2018"
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2018",
"features": {},
"id": "path+file:[..]#0.1.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2018",
"kind": [
"lib"
],
"name": "foo",
"src_path": "[..]src/lib.rs"
}
],
"version": "0.1.0"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]#0.1.0"
}
],
"root": "path+file:[..]#0.1.0"
},
"target_directory": "[..]",
"version": 1,
"workspace_members": [
"path+file:[..]#0.1.0"
],
"workspace_default_members": [
"path+file:[..]#0.1.0"
],
"workspace_root": "[..]",
"metadata": null
}
"#,
)
.run();
}
#[cargo_test]
fn package_default_run() {
let p = project()
.file("src/lib.rs", "")
.file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#)
.file("src/bin/b.rs", r#"fn main() { println!("hello B"); }"#)
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
edition = "2018"
default-run = "a"
"#,
)
.build();
let json = p.cargo("metadata").run_json();
assert_eq!(json["packages"][0]["default_run"], json!("a"));
}
#[cargo_test]
fn package_rust_version() {
let p = project()
.file("src/lib.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
edition = "2018"
rust-version = "1.56"
"#,
)
.build();
let json = p.cargo("metadata").run_json();
assert_eq!(json["packages"][0]["rust_version"], json!("1.56"));
}
#[cargo_test]
fn target_edition_2018() {
let p = project()
.file("src/lib.rs", "")
.file("src/main.rs", "")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = ["wycats@example.com"]
edition = "2015"
[lib]
edition = "2018"
"#,
)
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "path+file:[..]#0.1.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]Cargo.toml",
"metadata": null,
"publish": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2018",
"kind": [
"lib"
],
"name": "foo",
"src_path": "[..]src/lib.rs"
},
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"test": true,
"edition": "2015",
"kind": [
"bin"
],
"name": "foo",
"src_path": "[..]src/main.rs"
}
],
"version": "0.1.0"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "path+file:[..]#0.1.0"
}
],
"root": "path+file:[..]#0.1.0"
},
"target_directory": "[..]",
"version": 1,
"workspace_members": [
"path+file:[..]#0.1.0"
],
"workspace_default_members": [
"path+file:[..]#0.1.0"
],
"workspace_root": "[..]",
"metadata": null
}
"#,
)
.run();
}
#[cargo_test]
fn rename_dependency() {
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.2.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = { version = "0.1.0" }
baz = { version = "0.2.0", package = "bar" }
"#,
)
.file("src/lib.rs", "extern crate bar; extern crate baz;")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]",
"metadata": null,
"publish": null,
"name": "bar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]"
}
],
"version": "0.1.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]",
"metadata": null,
"publish": null,
"name": "bar",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]"
}
],
"version": "0.2.0"
},
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [
{
"features": [],
"kind": null,
"name": "bar",
"optional": false,
"rename": null,
"registry": null,
"req": "^0.1.0",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": null,
"name": "bar",
"optional": false,
"rename": "baz",
"registry": null,
"req": "^0.2.0",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"target": null,
"uses_default_features": true
}
],
"description": null,
"edition": "2015",
"features": {},
"id": "[..]foo#0.0.1",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]",
"metadata": null,
"publish": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "foo",
"src_path": "[..]"
}
],
"version": "0.0.1"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0"
},
{
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0",
"registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0"
],
"deps": [
{
"dep_kinds": [
{
"kind": null,
"target": null
}
],
"name": "bar",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0"
},
{
"dep_kinds": [
{
"kind": null,
"target": null
}
],
"name": "baz",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0"
}
],
"features": [],
"id": "[..]foo#0.0.1"
}
],
"root": "[..]foo#0.0.1"
},
"target_directory": "[..]",
"version": 1,
"workspace_members": [
"[..]foo#0.0.1"
],
"workspace_default_members": [
"[..]foo#0.0.1"
],
"workspace_root": "[..]",
"metadata": null
}"#,
)
.run();
}
#[cargo_test]
fn metadata_links() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.5.0"
links = "a"
"#,
)
.file("src/lib.rs", "")
.file("build.rs", "fn main() {}")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"authors": [],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"edition": "2015",
"features": {},
"id": "[..]foo#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": "a",
"manifest_path": "[..]/foo/Cargo.toml",
"metadata": null,
"publish": null,
"name": "foo",
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"test": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "foo",
"src_path": "[..]/foo/src/lib.rs"
},
{
"crate_types": [
"bin"
],
"doc": false,
"doctest": false,
"test": false,
"edition": "2015",
"kind": [
"custom-build"
],
"name": "build-script-build",
"src_path": "[..]/foo/build.rs"
}
],
"version": "0.5.0"
}
],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "[..]foo#0.5.0"
}
],
"root": "[..]foo#0.5.0"
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_members": [
"[..]foo#0.5.0"
],
"workspace_default_members": [
"[..]foo#0.5.0"
],
"workspace_root": "[..]/foo",
"metadata": null
}
"#,
)
.run()
}
#[cargo_test]
fn deps_with_bin_only() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bdep = { path = "bdep" }
"#,
)
.file("src/lib.rs", "")
.file("bdep/Cargo.toml", &basic_bin_manifest("bdep"))
.file("bdep/src/main.rs", "fn main() {}")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": [
{
"name": "foo",
"version": "0.1.0",
"id": "[..]foo#0.1.0",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies": [
{
"name": "bdep",
"source": null,
"req": "*",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"path": "[..]/foo/bdep",
"features": [],
"target": null,
"registry": null
}
],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "foo",
"src_path": "[..]/foo/src/lib.rs",
"edition": "2015",
"doc": true,
"doctest": true,
"test": true
}
],
"features": {},
"manifest_path": "[..]/foo/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
],
"workspace_members": [
"[..]foo#0.1.0"
],
"workspace_default_members": [
"[..]foo#0.1.0"
],
"resolve": {
"nodes": [
{
"id": "[..]foo#0.1.0",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "[..]foo#0.1.0"
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]foo",
"metadata": null
}
"#,
)
.run();
}
#[cargo_test]
fn filter_platform() {
// Testing the --filter-platform flag.
Package::new("normal-dep", "0.0.1").publish();
Package::new("host-dep", "0.0.1").publish();
Package::new("alt-dep", "0.0.1").publish();
Package::new("cfg-dep", "0.0.1").publish();
// Just needs to be a valid target that is different from host.
// Presumably nobody runs these tests on wasm. 🙃
let alt_target = "wasm32-unknown-unknown";
let host_target = rustc_host();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
normal-dep = "0.0.1"
[target.{}.dependencies]
host-dep = "0.0.1"
[target.{}.dependencies]
alt-dep = "0.0.1"
[target.'cfg(foobar)'.dependencies]
cfg-dep = "0.0.1"
"#,
host_target, alt_target
),
)
.file("src/lib.rs", "")
.build();
let alt_dep = r#"
{
"name": "alt-dep",
"version": "0.0.1",
"id": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"license": null,
"license_file": null,
"description": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"dependencies": [],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "alt-dep",
"src_path": "[..]/alt-dep-0.0.1/src/lib.rs",
"edition": "2015",
"test": true,
"doc": true,
"doctest": true
}
],
"features": {},
"manifest_path": "[..]/alt-dep-0.0.1/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
"#;
let cfg_dep = r#"
{
"name": "cfg-dep",
"version": "0.0.1",
"id": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"license": null,
"license_file": null,
"description": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"dependencies": [],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "cfg-dep",
"src_path": "[..]/cfg-dep-0.0.1/src/lib.rs",
"edition": "2015",
"test": true,
"doc": true,
"doctest": true
}
],
"features": {},
"manifest_path": "[..]/cfg-dep-0.0.1/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
"#;
let host_dep = r#"
{
"name": "host-dep",
"version": "0.0.1",
"id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"license": null,
"license_file": null,
"description": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"dependencies": [],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "host-dep",
"src_path": "[..]/host-dep-0.0.1/src/lib.rs",
"edition": "2015",
"test": true,
"doc": true,
"doctest": true
}
],
"features": {},
"manifest_path": "[..]/host-dep-0.0.1/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
"#;
let normal_dep = r#"
{
"name": "normal-dep",
"version": "0.0.1",
"id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"license": null,
"license_file": null,
"description": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"dependencies": [],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "normal-dep",
"src_path": "[..]/normal-dep-0.0.1/src/lib.rs",
"edition": "2015",
"test": true,
"doc": true,
"doctest": true
}
],
"features": {},
"manifest_path": "[..]/normal-dep-0.0.1/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
"#;
// The dependencies are stored in sorted order by target and then by name.
// Since the testsuite may run on different targets, this needs to be
// sorted before it can be compared.
let mut foo_deps = serde_json::json!([
{
"name": "normal-dep",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": null,
"registry": null
},
{
"name": "cfg-dep",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": "cfg(foobar)",
"registry": null
},
{
"name": "alt-dep",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": alt_target,
"registry": null
},
{
"name": "host-dep",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": host_target,
"registry": null
}
]);
foo_deps.as_array_mut().unwrap().sort_by(|a, b| {
// This really should be `rename`, but not needed here.
// Also, sorting on `name` isn't really necessary since this test
// only has one package per target, but leaving it here to be safe.
let a = (a["target"].as_str(), a["name"].as_str());
let b = (b["target"].as_str(), b["name"].as_str());
a.cmp(&b)
});
let foo = r#"
{
"name": "foo",
"version": "0.1.0",
"id": "path+file:[..]foo#0.1.0",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies":
$FOO_DEPS,
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "foo",
"src_path": "[..]/foo/src/lib.rs",
"edition": "2015",
"test": true,
"doc": true,
"doctest": true
}
],
"features": {},
"manifest_path": "[..]/foo/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"default_run": null,
"keywords": [],
"readme": null,
"repository": null,
"rust_version": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null
}
"#
.replace("$ALT_TRIPLE", alt_target)
.replace("$HOST_TRIPLE", host_target)
.replace("$FOO_DEPS", &foo_deps.to_string());
// We're going to be checking that we don't download excessively,
// so we need to ensure that downloads will happen.
let clear = || {
cargo_home().join("registry/cache").rm_rf();
cargo_home().join("registry/src").rm_rf();
p.build_dir().rm_rf();
};
// Normal metadata, no filtering, returns *everything*.
p.cargo("metadata")
.with_stderr_unordered(
"\
[UPDATING] [..]
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[DOWNLOADING] crates ...
[DOWNLOADED] normal-dep v0.0.1 [..]
[DOWNLOADED] host-dep v0.0.1 [..]
[DOWNLOADED] alt-dep v0.0.1 [..]
[DOWNLOADED] cfg-dep v0.0.1 [..]
",
)
.with_json(
&r#"
{
"packages": [
$ALT_DEP,
$CFG_DEP,
$FOO,
$HOST_DEP,
$NORMAL_DEP
],
"workspace_members": [
"path+file:[..]foo#0.1.0"
],
"workspace_default_members": [
"path+file:[..]foo#0.1.0"
],
"resolve": {
"nodes": [
{
"id": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "path+file:[..]foo#0.1.0",
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1"
],
"deps": [
{
"name": "alt_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "$ALT_TRIPLE"
}
]
},
{
"name": "cfg_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "cfg(foobar)"
}
]
},
{
"name": "host_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "$HOST_TRIPLE"
}
]
},
{
"name": "normal_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "path+file:[..]foo#0.1.0"
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}
"#
.replace("$ALT_TRIPLE", alt_target)
.replace("$HOST_TRIPLE", host_target)
.replace("$ALT_DEP", alt_dep)
.replace("$CFG_DEP", cfg_dep)
.replace("$HOST_DEP", host_dep)
.replace("$NORMAL_DEP", normal_dep)
.replace("$FOO", &foo),
)
.run();
clear();
// Filter on alternate, removes cfg and host.
p.cargo("metadata --filter-platform")
.arg(alt_target)
.with_stderr_unordered(
"\
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[DOWNLOADING] crates ...
[DOWNLOADED] normal-dep v0.0.1 [..]
[DOWNLOADED] host-dep v0.0.1 [..]
[DOWNLOADED] alt-dep v0.0.1 [..]
",
)
.with_json(
&r#"
{
"packages": [
$ALT_DEP,
$FOO,
$NORMAL_DEP
],
"workspace_members": "{...}",
"workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
"id": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "path+file:[..]foo#0.1.0",
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1"
],
"deps": [
{
"name": "alt_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "$ALT_TRIPLE"
}
]
},
{
"name": "normal_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "path+file:[..]foo#0.1.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]foo",
"metadata": null
}
"#
.replace("$ALT_TRIPLE", alt_target)
.replace("$ALT_DEP", alt_dep)
.replace("$NORMAL_DEP", normal_dep)
.replace("$FOO", &foo),
)
.run();
clear();
// Filter on host, removes alt and cfg.
p.cargo("metadata --filter-platform")
.arg(&host_target)
.with_stderr_unordered(
"\
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[DOWNLOADING] crates ...
[DOWNLOADED] normal-dep v0.0.1 [..]
[DOWNLOADED] host-dep v0.0.1 [..]
",
)
.with_json(
&r#"
{
"packages": [
$FOO,
$HOST_DEP,
$NORMAL_DEP
],
"workspace_members": "{...}",
"workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
"id": "path+file:[..]foo#0.1.0",
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1"
],
"deps": [
{
"name": "host_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "$HOST_TRIPLE"
}
]
},
{
"name": "normal_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "path+file:[..]foo#0.1.0"
},
"target_directory": "[..]foo/target",
"version": 1,
"workspace_root": "[..]foo",
"metadata": null
}
"#
.replace("$HOST_TRIPLE", host_target)
.replace("$HOST_DEP", host_dep)
.replace("$NORMAL_DEP", normal_dep)
.replace("$FOO", &foo),
)
.run();
clear();
// Filter host with cfg, removes alt only
p.cargo("metadata --filter-platform")
.arg(&host_target)
.env("RUSTFLAGS", "--cfg=foobar")
.with_stderr_unordered(
"\
[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems
[DOWNLOADING] crates ...
[DOWNLOADED] normal-dep v0.0.1 [..]
[DOWNLOADED] host-dep v0.0.1 [..]
[DOWNLOADED] cfg-dep v0.0.1 [..]
",
)
.with_json(
&r#"
{
"packages": [
$CFG_DEP,
$FOO,
$HOST_DEP,
$NORMAL_DEP
],
"workspace_members": "{...}",
"workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
"id": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "path+file:[..]/foo#0.1.0",
"dependencies": [
"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1"
],
"deps": [
{
"name": "cfg_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "cfg(foobar)"
}
]
},
{
"name": "host_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": "$HOST_TRIPLE"
}
]
},
{
"name": "normal_dep",
"pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "path+file:[..]/foo#0.1.0"
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null
}
"#
.replace("$HOST_TRIPLE", host_target)
.replace("$CFG_DEP", cfg_dep)
.replace("$HOST_DEP", host_dep)
.replace("$NORMAL_DEP", normal_dep)
.replace("$FOO", &foo),
)
.run();
}
#[cargo_test]
fn dep_kinds() {
Package::new("bar", "0.1.0").publish();
Package::new("winapi", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[dev-dependencies]
bar = "0.1"
[build-dependencies]
bar = "0.1"
[target.'cfg(windows)'.dependencies]
winapi = "0.1"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": "{...}",
"workspace_members": "{...}",
"workspace_default_members": "{...}",
"target_directory": "{...}",
"version": 1,
"workspace_root": "{...}",
"metadata": null,
"resolve": {
"nodes": [
{
"id": "[..]#bar@0.1.0",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "[..]foo#0.1.0",
"dependencies": [
"[..]#bar@0.1.0",
"[..]#winapi@0.1.0"
],
"deps": [
{
"name": "bar",
"pkg": "[..]#bar@0.1.0",
"dep_kinds": [
{
"kind": null,
"target": null
},
{
"kind": "dev",
"target": null
},
{
"kind": "build",
"target": null
}
]
},
{
"name": "winapi",
"pkg": "[..]#winapi@0.1.0",
"dep_kinds": [
{
"kind": null,
"target": "cfg(windows)"
}
]
}
],
"features": []
},
{
"id": "[..]#winapi@0.1.0",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": "[..]foo#0.1.0"
}
}
"#,
)
.run();
}
#[cargo_test]
fn dep_kinds_workspace() {
// Check for bug with duplicate dep kinds in a workspace.
// If different members select different features for the same package,
// they show up multiple times in the resolver `deps`.
//
// Here:
// foo -> dep
// bar -> foo[feat1] -> dep
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[features]
feat1 = []
[dependencies]
dep = { path="dep" }
[workspace]
members = ["bar"]
"#,
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[dependencies]
foo = { path="..", features=["feat1"] }
"#,
)
.file("bar/src/lib.rs", "")
.file("dep/Cargo.toml", &basic_lib_manifest("dep"))
.file("dep/src/lib.rs", "")
.build();
p.cargo("metadata")
.with_json(
r#"
{
"packages": "{...}",
"workspace_members": "{...}",
"workspace_default_members": "{...}",
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"metadata": null,
"resolve": {
"nodes": [
{
"id": "path+file://[..]/foo/bar#0.1.0",
"dependencies": [
"path+file://[..]/foo#0.1.0"
],
"deps": [
{
"name": "foo",
"pkg": "path+file://[..]/foo#0.1.0",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "path+file://[..]/foo/dep#0.5.0",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "path+file://[..]/foo#0.1.0",
"dependencies": [
"path+file://[..]/foo/dep#0.5.0"
],
"deps": [
{
"name": "dep",
"pkg": "path+file://[..]/foo/dep#0.5.0",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": [
"feat1"
]
}
],
"root": "path+file://[..]/foo#0.1.0"
}
}
"#,
)
.run();
}
// Creating non-utf8 path is an OS-specific pain, so let's run this only on
// linux, where arbitrary bytes work.
#[cfg(target_os = "linux")]
#[cargo_test]
fn cargo_metadata_non_utf8() {
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
use std::path::PathBuf;
let base = PathBuf::from(OsString::from_vec(vec![255]));
let p = project()
.no_manifest()
.file(base.join("./src/lib.rs"), "")
.file(base.join("./Cargo.toml"), &basic_lib_manifest("foo"))
.build();
p.cargo("metadata")
.cwd(p.root().join(base))
.arg("--format-version")
.arg("1")
.with_stderr("error: path contains invalid UTF-8 characters")
.with_status(101)
.run();
}
// TODO: Consider using this test instead of the version without the 'artifact' suffix or merge them because they should be pretty much the same.
#[cargo_test]
fn workspace_metadata_with_dependencies_no_deps_artifact() {
let p = project()
// NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member.
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
"#,
)
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.5.0"
authors = ["wycats@example.com"]
[dependencies]
baz = { path = "../baz/" }
baz-renamed = { path = "../baz/" }
artifact = { path = "../artifact/", artifact = "bin" }
"#,
)
.file("bar/src/lib.rs", "")
.file("baz/Cargo.toml", &basic_lib_manifest("baz"))
.file("baz/src/lib.rs", "")
.file("artifact/Cargo.toml", &basic_bin_manifest("artifact"))
.file("artifact/src/main.rs", "fn main() {}")
.build();
p.cargo("metadata --no-deps -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
.with_json(
r#"
{
"metadata": null,
"packages": [
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [
{
"artifact": {
"kinds": [
"bin"
],
"lib": false,
"target": null
},
"features": [],
"kind": null,
"name": "artifact",
"optional": false,
"path": "[..]/foo/artifact",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": null,
"name": "baz",
"optional": false,
"path": "[..]/foo/baz",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
},
{
"features": [],
"kind": null,
"name": "baz-renamed",
"optional": false,
"path": "[..]/foo/baz",
"registry": null,
"rename": null,
"req": "*",
"source": null,
"target": null,
"uses_default_features": true
}
],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/bar#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/bar/Cargo.toml",
"metadata": null,
"name": "bar",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "bar",
"src_path": "[..]/foo/bar/src/lib.rs",
"test": true
}
],
"version": "0.5.0"
},
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/artifact#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/artifact/Cargo.toml",
"metadata": null,
"name": "artifact",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"bin"
],
"doc": true,
"doctest": false,
"edition": "2015",
"kind": [
"bin"
],
"name": "artifact",
"src_path": "[..]/foo/artifact/src/main.rs",
"test": true
}
],
"version": "0.5.0"
},
{
"authors": [
"wycats@example.com"
],
"categories": [],
"default_run": null,
"dependencies": [],
"description": null,
"documentation": null,
"edition": "2015",
"features": {},
"homepage": null,
"id": "path+file://[..]/foo/baz#0.5.0",
"keywords": [],
"license": null,
"license_file": null,
"links": null,
"manifest_path": "[..]/foo/baz/Cargo.toml",
"metadata": null,
"name": "baz",
"publish": null,
"readme": null,
"repository": null,
"rust_version": null,
"source": null,
"targets": [
{
"crate_types": [
"lib"
],
"doc": true,
"doctest": true,
"edition": "2015",
"kind": [
"lib"
],
"name": "baz",
"src_path": "[..]/foo/baz/src/lib.rs",
"test": true
}
],
"version": "0.5.0"
}
],
"resolve": null,
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_members": [
"path+file://[..]/foo/bar#0.5.0",
"path+file://[..]/foo/artifact#0.5.0",
"path+file://[..]/foo/baz#0.5.0"
],
"workspace_default_members": [
"path+file://[..]/foo/bar#0.5.0",
"path+file://[..]/foo/artifact#0.5.0",
"path+file://[..]/foo/baz#0.5.0"
],
"workspace_root": "[..]/foo"
}
"#,
)
.run();
}
#[cargo_test]
fn versionless_packages() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
"#,
)
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
[dependencies]
foobar = "0.0.1"
baz = { path = "../baz/" }
"#,
)
.file("bar/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
[dependencies]
foobar = "0.0.1"
"#,
)
.file("baz/src/lib.rs", "")
.build();
Package::new("foobar", "0.0.1").publish();
p.cargo("metadata -q --format-version 1")
.with_json(
r#"
{
"packages": [
{
"name": "bar",
"version": "0.0.0",
"id": "[..]bar#0.0.0",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies": [
{
"name": "baz",
"source": null,
"req": "*",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": null,
"registry": null,
"path": "[..]/baz"
},
{
"name": "foobar",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": null,
"registry": null
}
],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "bar",
"src_path": "[..]/bar/src/lib.rs",
"edition": "2015",
"doc": true,
"doctest": true,
"test": true
}
],
"features": {},
"manifest_path": "[..]/bar/Cargo.toml",
"metadata": null,
"publish": [],
"authors": [],
"categories": [],
"keywords": [],
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null,
"default_run": null,
"rust_version": null
},
{
"name": "baz",
"version": "0.0.0",
"id": "[..]baz#0.0.0",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies": [
{
"name": "foobar",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.0.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [],
"target": null,
"registry": null
}
],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "baz",
"src_path": "[..]/baz/src/lib.rs",
"edition": "2015",
"doc": true,
"doctest": true,
"test": true
}
],
"features": {},
"manifest_path": "[..]/baz/Cargo.toml",
"metadata": null,
"publish": [],
"authors": [],
"categories": [],
"keywords": [],
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null,
"default_run": null,
"rust_version": null
},
{
"name": "foobar",
"version": "0.0.1",
"id": "[..]#foobar@0.0.1",
"license": null,
"license_file": null,
"description": null,
"source": "registry+https://github.com/rust-lang/crates.io-index",
"dependencies": [],
"targets": [
{
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "foobar",
"src_path": "[..]/foobar-0.0.1/src/lib.rs",
"edition": "2015",
"doc": true,
"doctest": true,
"test": true
}
],
"features": {},
"manifest_path": "[..]/foobar-0.0.1/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"keywords": [],
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"edition": "2015",
"links": null,
"default_run": null,
"rust_version": null
}
],
"workspace_members": [
"[..]bar#0.0.0",
"[..]baz#0.0.0"
],
"workspace_default_members": [
"[..]bar#0.0.0",
"[..]baz#0.0.0"
],
"resolve": {
"nodes": [
{
"id": "[..]bar#0.0.0",
"dependencies": [
"[..]baz#0.0.0",
"[..]#foobar@0.0.1"
],
"deps": [
{
"name": "baz",
"pkg": "[..]baz#0.0.0",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
},
{
"name": "foobar",
"pkg": "[..]#foobar@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "[..]baz#0.0.0",
"dependencies": [
"[..]#foobar@0.0.1"
],
"deps": [
{
"name": "foobar",
"pkg": "[..]#foobar@0.0.1",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "[..]#foobar@0.0.1",
"dependencies": [],
"deps": [],
"features": []
}
],
"root": null
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]",
"metadata": null
}
"#,
)
.run();
}