blob: 956f45107db2a9a3792cf91537efe1b3e29ad0f3 [file] [log] [blame]
extern crate cargo_bazel;
extern crate serde_json;
extern crate tempfile;
use anyhow::{ensure, Context, Result};
use cargo_bazel::cli::{splice, SpliceOptions};
use serde_json::{json, Value};
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::PathBuf;
fn setup_cargo_env() -> Result<(PathBuf, PathBuf)> {
let cargo = std::fs::canonicalize(PathBuf::from(
env::var("CARGO").context("CARGO environment variable must be set.")?,
))
.unwrap();
let rustc = std::fs::canonicalize(PathBuf::from(
env::var("RUSTC").context("RUSTC environment variable must be set.")?,
))
.unwrap();
ensure!(cargo.exists());
ensure!(rustc.exists());
// If $RUSTC is a relative path it can cause issues with
// `cargo_metadata::MetadataCommand`. Just to be on the safe side, we make
// both of these env variables absolute paths.
if cargo != PathBuf::from(env::var("CARGO").unwrap()) {
env::set_var("CARGO", cargo.as_os_str());
}
if rustc != PathBuf::from(env::var("RUSTC").unwrap()) {
env::set_var("RUSTC", rustc.as_os_str());
}
let cargo_home = PathBuf::from(
env::var("TEST_TMPDIR").context("TEST_TMPDIR environment variable must be set.")?,
)
.join("cargo_home");
env::set_var("CARGO_HOME", cargo_home.as_os_str());
fs::create_dir_all(&cargo_home)?;
println!("$RUSTC={}", rustc.display());
println!("$CARGO={}", cargo.display());
println!("$CARGO_HOME={}", cargo_home.display());
Ok((cargo, rustc))
}
fn run(repository_name: &str, manifests: HashMap<String, String>, lockfile: &str) -> Value {
let (cargo, rustc) = setup_cargo_env().unwrap();
let scratch = tempfile::tempdir().unwrap();
let runfiles = runfiles::Runfiles::create().unwrap();
/*
let manifest_path = scratch.path().join("Cargo.toml");
fs::copy(
runfiles.rlocation(manifest),
manifest_path,
)
.unwrap();
*/
let splicing_manifest = scratch.path().join("splicing_manifest.json");
fs::write(
&splicing_manifest,
serde_json::to_string(&json!({
"manifests": manifests,
"direct_packages": {},
"resolver_version": "2"
}))
.unwrap(),
)
.unwrap();
let config = scratch.path().join("config.json");
fs::write(
&config,
serde_json::to_string(&json!({
"generate_binaries": false,
"generate_build_scripts": false,
"rendering": {
"repository_name": repository_name,
"regen_command": "//crate_universe:cargo_integration_test"
},
"supported_platform_triples": [
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
]
}))
.unwrap(),
)
.unwrap();
splice(SpliceOptions {
splicing_manifest,
cargo_lockfile: Some(runfiles.rlocation(lockfile)),
repin: None,
workspace_dir: None,
output_dir: scratch.path().join("out"),
dry_run: false,
cargo_config: None,
config,
cargo,
rustc,
})
.unwrap();
let metadata = serde_json::from_str::<Value>(
&fs::read_to_string(scratch.path().join("out").join("metadata.json")).unwrap(),
)
.unwrap();
metadata
}
// See crate_universe/test_data/metadata/target_features/Cargo.toml for input.
#[test]
fn feature_generator() {
// This test case requires network access to build pull crate metadata
// so that we can actually run `cargo tree`. However, RBE (and perhaps
// other environments) disallow or don't support this. In those cases,
// we just skip this test case.
use std::net::ToSocketAddrs;
if "github.com:443".to_socket_addrs().is_err() {
eprintln!("This test case requires network access. Skipping!");
return;
}
let runfiles = runfiles::Runfiles::create().unwrap();
let metadata = run(
"target_feature_test",
HashMap::from([(
runfiles
.rlocation(
"rules_rust/crate_universe/test_data/metadata/target_features/Cargo.toml",
)
.to_string_lossy()
.to_string(),
"//:test_input".to_string(),
)]),
"rules_rust/crate_universe/test_data/metadata/target_features/Cargo.lock",
);
assert_eq!(
metadata["metadata"]["cargo-bazel"]["features"]["wgpu-hal 0.14.1"],
json!({
"selects": {
"x86_64-apple-darwin": [
"block", "foreign-types", "metal",
],
"x86_64-pc-windows-msvc": [
"ash", "bit-set", "dx11", "dx12", "gpu-alloc",
"gpu-descriptor", "libloading", "native", "range-alloc",
"renderdoc", "renderdoc-sys", "smallvec", "vulkan",
],
"x86_64-unknown-linux-gnu": [
"ash", "egl", "gles", "glow", "gpu-alloc",
"gpu-descriptor", "libloading", "renderdoc", "renderdoc-sys",
"smallvec", "vulkan",
],
},
"common": [
"default",
],
})
);
}
// See crate_universe/test_data/metadata/target_cfg_features/Cargo.toml for input.
#[test]
fn feature_generator_cfg_features() {
// This test case requires network access to build pull crate metadata
// so that we can actually run `cargo tree`. However, RBE (and perhaps
// other environments) disallow or don't support this. In those cases,
// we just skip this test case.
use std::net::ToSocketAddrs;
if "github.com:443".to_socket_addrs().is_err() {
eprintln!("This test case requires network access. Skipping!");
return;
}
let runfiles = runfiles::Runfiles::create().unwrap();
let metadata = run(
"target_cfg_features_test",
HashMap::from([(
runfiles
.rlocation(
"rules_rust/crate_universe/test_data/metadata/target_cfg_features/Cargo.toml",
)
.to_string_lossy()
.to_string(),
"//:test_input".to_string(),
)]),
"rules_rust/crate_universe/test_data/metadata/target_cfg_features/Cargo.lock",
);
assert_eq!(
metadata["metadata"]["cargo-bazel"]["features"],
json!({
"target_cfg_features 0.1.0": {
"common": [],
"selects": {}
},
"autocfg 1.1.0": {
"common": [],
"selects": {}
},
"pin-project-lite 0.2.9": {
"common": [],
"selects": {}
},
"tokio 1.25.0": {
"common": ["default"],
"selects": {
// Note: "x86_64-pc-windows-msvc" is *not* here, despite
// being included in `supported_platform_triples` above!
"x86_64-apple-darwin": ["fs"],
"x86_64-unknown-linux-gnu": ["fs"]
}
}
})
);
}
#[test]
fn feature_generator_workspace() {
// This test case requires network access to build pull crate metadata
// so that we can actually run `cargo tree`. However, RBE (and perhaps
// other environments) disallow or don't support this. In those cases,
// we just skip this test case.
use std::net::ToSocketAddrs;
if "github.com:443".to_socket_addrs().is_err() {
eprintln!("This test case requires network access. Skipping!");
return;
}
let runfiles = runfiles::Runfiles::create().unwrap();
let metadata = run(
"workspace_test",
HashMap::from([
(
runfiles
.rlocation("rules_rust/crate_universe/test_data/metadata/workspace/Cargo.toml")
.to_string_lossy()
.to_string(),
"//:test_input".to_string(),
),
(
runfiles
.rlocation(
"rules_rust/crate_universe/test_data/metadata/workspace/child/Cargo.toml",
)
.to_string_lossy()
.to_string(),
"//crate_universe:test_data/metadata/workspace/child/Cargo.toml".to_string(),
),
]),
"rules_rust/crate_universe/test_data/metadata/workspace/Cargo.lock",
);
assert!(!metadata["metadata"]["cargo-bazel"]["features"]["wgpu 0.14.0"].is_null());
}
#[test]
fn feature_generator_crate_combined_features() {
// This test case requires network access to build pull crate metadata
// so that we can actually run `cargo tree`. However, RBE (and perhaps
// other environments) disallow or don't support this. In those cases,
// we just skip this test case.
use std::net::ToSocketAddrs;
if "github.com:443".to_socket_addrs().is_err() {
eprintln!("This test case requires network access. Skipping!");
return;
}
let runfiles = runfiles::Runfiles::create().unwrap();
let metadata = run(
"crate_combined_features",
HashMap::from([
(
runfiles
.rlocation("rules_rust/crate_universe/test_data/metadata/crate_combined_features/Cargo.toml")
.to_string_lossy()
.to_string(),
"//:test_input".to_string(),
)
]),
"rules_rust/crate_universe/test_data/metadata/crate_combined_features/Cargo.lock",
);
// serde appears twice in the list of dependencies, with and without derive features
assert_eq!(
metadata["metadata"]["cargo-bazel"]["features"]["serde 1.0.158"]["common"],
json!(["default", "derive", "serde_derive", "std"])
);
}