mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
714 lines
15 KiB
Rust
714 lines
15 KiB
Rust
//! Tests for cargo-sbom precursor files.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use crate::prelude::*;
|
|
use cargo_test_support::basic_bin_manifest;
|
|
use cargo_test_support::cargo_test;
|
|
use cargo_test_support::compare::assert_e2e;
|
|
use cargo_test_support::project;
|
|
use cargo_test_support::registry::Package;
|
|
use snapbox::IntoData;
|
|
|
|
const SBOM_FILE_EXTENSION: &str = ".cargo-sbom.json";
|
|
|
|
fn append_sbom_suffix(link: &PathBuf) -> PathBuf {
|
|
let mut link_buf = link.clone().into_os_string();
|
|
link_buf.push(SBOM_FILE_EXTENSION);
|
|
PathBuf::from(link_buf)
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn warn_without_passing_unstable_flag() {
|
|
let p = project()
|
|
.file("Cargo.toml", &basic_bin_manifest("foo"))
|
|
.file("src/main.rs", r#"fn main() {}"#)
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.with_stderr_data(
|
|
"\
|
|
[WARNING] ignoring 'sbom' config, pass `-Zsbom` to enable it\n\
|
|
[COMPILING] foo v0.5.0 ([..])\n\
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]\n",
|
|
)
|
|
.run();
|
|
|
|
let file = append_sbom_suffix(&p.bin("foo"));
|
|
assert!(!file.exists());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn simple() {
|
|
let p = project()
|
|
.file("Cargo.toml", &basic_bin_manifest("foo"))
|
|
.file("src/main.rs", r#"fn main() {}"#)
|
|
.build();
|
|
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
let file = append_sbom_suffix(&p.bin("foo"));
|
|
let output = std::fs::read_to_string(file).unwrap();
|
|
// The expected test does contain the "rustc" section
|
|
// but other tests omit them for brevity.
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.5.0",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": {
|
|
"commit_hash": "{...}",
|
|
"host": "[HOST_TARGET]",
|
|
"verbose_version": "{...}",
|
|
"version": "{...}",
|
|
"workspace_wrapper": null,
|
|
"wrapper": null
|
|
},
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn with_multiple_crate_types() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.2.3"
|
|
|
|
[lib]
|
|
crate-type = ["dylib", "rlib"]
|
|
"#,
|
|
)
|
|
.file("src/main.rs", r#"fn main() { let _i = foo::give_five(); }"#)
|
|
.file("src/lib.rs", r#"pub fn give_five() -> i32 { 5 }"#)
|
|
.build();
|
|
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
assert_eq!(
|
|
3,
|
|
p.glob(p.target_debug_dir().join("*.cargo-sbom.json"))
|
|
.count()
|
|
);
|
|
|
|
let sbom_path = append_sbom_suffix(&p.dylib("foo"));
|
|
assert!(sbom_path.is_file());
|
|
|
|
let output = std::fs::read_to_string(sbom_path).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#1.2.3",
|
|
"kind": [
|
|
"dylib",
|
|
"rlib"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn with_simple_build_script() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
build = "build.rs"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "#[cfg(foo)] fn main() {}")
|
|
.file(
|
|
"build.rs",
|
|
r#"fn main() {
|
|
println!("cargo::rustc-check-cfg=cfg(foo)");
|
|
println!("cargo::rustc-cfg=foo");
|
|
}"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
let path = append_sbom_suffix(&p.bin("foo"));
|
|
assert!(path.is_file());
|
|
|
|
let output = std::fs::read_to_string(path).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 1,
|
|
"kind": "build"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.1",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.1",
|
|
"kind": [
|
|
"custom-build"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn with_build_dependencies() {
|
|
Package::new("baz", "0.1.0").publish();
|
|
Package::new("bar", "0.1.0")
|
|
.build_dep("baz", "0.1.0")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
build = "build.rs"
|
|
|
|
[build-dependencies]
|
|
baz = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "pub fn bar() -> i32 { 2 }")
|
|
.file(
|
|
"build.rs",
|
|
r#"fn main() {
|
|
println!("cargo::rustc-check-cfg=cfg(foo)");
|
|
println!("cargo::rustc-cfg=foo");
|
|
}"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
|
|
[dependencies]
|
|
bar = "0.1.0"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() { let _i = bar::bar(); }")
|
|
.build();
|
|
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
let path = append_sbom_suffix(&p.bin("foo"));
|
|
let output = std::fs::read_to_string(path).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 1,
|
|
"kind": "build"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0",
|
|
"kind": [
|
|
"lib"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 2,
|
|
"kind": "normal"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0",
|
|
"kind": [
|
|
"custom-build"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#baz@0.1.0",
|
|
"kind": [
|
|
"lib"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 0,
|
|
"kind": "normal"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.1",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
}
|
|
],
|
|
"root": 3,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn crate_uses_different_features_for_build_and_normal_dependencies() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
b = { path = "b/", features = ["f1"] }
|
|
|
|
[build-dependencies]
|
|
b = { path = "b/", features = ["f2"] }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() { b::f1(); }
|
|
"#,
|
|
)
|
|
.file(
|
|
"build.rs",
|
|
r#"
|
|
fn main() { b::f2(); }
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
|
|
[features]
|
|
f1 = []
|
|
f2 = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"b/src/lib.rs",
|
|
r#"
|
|
#[cfg(feature = "f1")]
|
|
pub fn f1() {}
|
|
|
|
#[cfg(feature = "f2")]
|
|
pub fn f2() {}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
let path = append_sbom_suffix(&p.bin("a"));
|
|
assert!(path.is_file());
|
|
let output = std::fs::read_to_string(path).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 1,
|
|
"kind": "build"
|
|
},
|
|
{
|
|
"index": 3,
|
|
"kind": "normal"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#a@0.1.0",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 2,
|
|
"kind": "normal"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#a@0.1.0",
|
|
"kind": [
|
|
"custom-build"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [
|
|
"f2"
|
|
],
|
|
"id": "path+[ROOTURL]/foo/b#0.0.1",
|
|
"kind": [
|
|
"lib"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [
|
|
"f1"
|
|
],
|
|
"id": "path+[ROOTURL]/foo/b#0.0.1",
|
|
"kind": [
|
|
"lib"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn artifact_dep() {
|
|
Package::new("bar", "0.5.0")
|
|
.file("src/main.rs", "fn main() {}")
|
|
.file("Cargo.toml", &basic_bin_manifest("bar"))
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
edition = "2021"
|
|
|
|
[lib]
|
|
crate-type = ["dylib"]
|
|
|
|
[dependencies]
|
|
bar = { version = "0.5.0", artifact = "bin" }
|
|
|
|
[build-dependencies]
|
|
bar = { version = "0.5.0", artifact = "bin" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("build.rs", r#"
|
|
fn main() {
|
|
let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into();
|
|
assert!(&bar.is_file());
|
|
}"#)
|
|
.build();
|
|
p.cargo("build -Z bindeps -Z sbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["bindeps", "sbom"])
|
|
.run();
|
|
|
|
let output = std::fs::read_to_string(append_sbom_suffix(&p.dylib("foo"))).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.5.0",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 0,
|
|
"kind": "normal"
|
|
},
|
|
{
|
|
"index": 0,
|
|
"kind": "build"
|
|
},
|
|
{
|
|
"index": 2,
|
|
"kind": "build"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.0",
|
|
"kind": [
|
|
"dylib"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.0",
|
|
"kind": [
|
|
"custom-build"
|
|
]
|
|
}
|
|
],
|
|
"root": 1,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn proc_macro() {
|
|
Package::new("noop", "0.0.1")
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "noop"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
|
|
[lib]
|
|
proc-macro = true
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
extern crate proc_macro;
|
|
use proc_macro::TokenStream;
|
|
|
|
#[proc_macro_derive(Noop)]
|
|
pub fn noop(_input: TokenStream) -> TokenStream {
|
|
"".parse().unwrap()
|
|
}
|
|
"#,
|
|
)
|
|
.publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
noop = "0.0.1"
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
#[macro_use]
|
|
extern crate noop;
|
|
|
|
#[derive(Noop)]
|
|
struct X;
|
|
|
|
fn main() {}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("build -Z sbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.run();
|
|
|
|
let output = std::fs::read_to_string(append_sbom_suffix(&p.bin("foo"))).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [
|
|
{
|
|
"index": 1,
|
|
"kind": "build"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.0.1",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#noop@0.0.1",
|
|
"kind": [
|
|
"proc-macro"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn workspace_wrapper() {
|
|
let wrapper = project()
|
|
.at("wrapper")
|
|
.file("Cargo.toml", &basic_bin_manifest("wrapper"))
|
|
.file(
|
|
"src/main.rs",
|
|
r#"
|
|
fn main() {
|
|
let mut args = std::env::args().skip(1);
|
|
if let Some(sbom) = std::env::var_os("CARGO_SBOM_PATH") {
|
|
for sbom in std::env::split_paths(&sbom) {
|
|
eprintln!("found sbom");
|
|
assert!(sbom.exists());
|
|
}
|
|
}
|
|
let status = std::process::Command::new(&args.next().unwrap())
|
|
.args(args).status().unwrap();
|
|
std::process::exit(status.code().unwrap_or(1));
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
wrapper.cargo("build").run();
|
|
|
|
let p = project()
|
|
.file("Cargo.toml", &basic_bin_manifest("foo"))
|
|
.file("src/main.rs", r#"fn main() {}"#)
|
|
.build();
|
|
p.cargo("build -Zsbom")
|
|
.env("CARGO_BUILD_SBOM", "true")
|
|
.env("RUSTC_WRAPPER", wrapper.bin("wrapper"))
|
|
.masquerade_as_nightly_cargo(&["sbom"])
|
|
.with_stderr_data(snapbox::str![[r#"
|
|
[COMPILING] foo v0.5.0 ([ROOT]/foo)
|
|
found sbom
|
|
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let file = append_sbom_suffix(&p.bin("foo"));
|
|
let output = std::fs::read_to_string(file).unwrap();
|
|
assert_e2e().eq(
|
|
output,
|
|
snapbox::str![[r#"
|
|
{
|
|
"crates": [
|
|
{
|
|
"dependencies": [],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#0.5.0",
|
|
"kind": [
|
|
"bin"
|
|
]
|
|
}
|
|
],
|
|
"root": 0,
|
|
"rustc": "{...}",
|
|
"target": "[HOST_TARGET]",
|
|
"version": 1
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
);
|
|
}
|