repositories / smith
smith
There are many coding harnesses - but this one is fast
owned by admin
xtask/tests/e2e_dependency.rs
Raw//! Dependency report CLI behavior (`SMH-SPEC-SPEC0001`).
use std::{fs, path::PathBuf, time::Duration};
fn workspace_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
#[test]
fn e2e_deps_rejects_invalid_arguments() {
let mut command = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"));
let output = command
.current_dir(workspace_root())
.args(["deps", "--unknown"])
.timeout(Duration::from_secs(10))
.output()
.unwrap();
assert_eq!(output.status.code(), Some(1));
assert!(String::from_utf8_lossy(&output.stderr).contains("usage: cargo x deps [--offline]"));
}
#[test]
fn e2e_dependency_resolution_rejects_invalid_mode_without_mutating_lockfile() {
let root = workspace_root();
let lockfile = root.join("Cargo.lock");
let before = fs::read(&lockfile).unwrap();
let output = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(root)
.args(["deps", "--verify", "unknown", "-p", "smith-core"])
.timeout(Duration::from_secs(10))
.output()
.unwrap();
assert_eq!(output.status.code(), Some(1));
assert!(String::from_utf8_lossy(&output.stderr).contains("usage: cargo x deps --verify"));
assert_eq!(fs::read(&lockfile).unwrap(), before);
}
#[test]
fn e2e_dependency_resolution_rejects_missing_or_invalid_target_without_mutating_lockfile() {
let root = workspace_root();
let lockfile = root.join("Cargo.lock");
let before = fs::read(&lockfile).unwrap();
for arguments in [
vec!["deps", "--verify", "locked", "--target"],
vec!["deps", "--verify", "locked", "--target", ""],
vec![
"deps",
"--verify",
"locked",
"--target",
"x86_64-unknown-linux-gnu",
"--unknown",
],
] {
let output = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(&root)
.args(arguments)
.timeout(Duration::from_secs(10))
.output()
.unwrap();
assert_eq!(output.status.code(), Some(1));
assert!(String::from_utf8_lossy(&output.stderr).contains("usage: cargo x deps --verify"));
}
let invalid_target = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(&root)
.args([
"deps",
"--verify",
"locked",
"--target",
"not-a-rust-target",
])
.timeout(Duration::from_secs(120))
.output()
.unwrap();
assert_eq!(invalid_target.status.code(), Some(1));
assert!(String::from_utf8_lossy(&invalid_target.stderr).contains("not-a-rust-target"));
assert_eq!(fs::read(&lockfile).unwrap(), before);
}
#[test]
fn e2e_default_resolution_checks_host_despite_ambient_build_target() {
let root = workspace_root();
let before = fs::read(root.join("Cargo.lock")).unwrap();
assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(&root)
.env("CARGO_BUILD_TARGET", "not-a-rust-target")
.args(["deps", "--verify", "locked", "-p", "smith-core"])
.timeout(Duration::from_secs(120))
.assert()
.success();
assert_eq!(fs::read(root.join("Cargo.lock")).unwrap(), before);
}
#[test]
fn e2e_dependency_resolution_scopes_locked_check_without_rewriting_lockfile() {
let root = workspace_root();
let lockfile = root.join("Cargo.lock");
let before = fs::read(&lockfile).unwrap();
let native_target = String::from_utf8(
assert_cmd::Command::new("rustc")
.arg("-vV")
.timeout(Duration::from_secs(10))
.output()
.unwrap()
.stdout,
)
.unwrap()
.lines()
.find_map(|line| line.strip_prefix("host: "))
.unwrap()
.to_owned();
for arguments in [
vec![
"deps",
"--verify",
"locked",
"-p",
"smith-core",
"--target",
&native_target,
],
vec![
"deps",
"--verify",
"locked",
"--target",
&native_target,
"--package",
"smith-core",
],
] {
let output = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(&root)
.args(arguments)
.timeout(Duration::from_secs(120))
.assert()
.success()
.get_output()
.stdout
.clone();
assert!(String::from_utf8_lossy(&output).contains(&format!("target {native_target}")));
}
assert_eq!(fs::read(&lockfile).unwrap(), before);
}
#[test]
#[cfg(unix)]
fn e2e_deps_offline_report_uses_cargo_protocol_without_registry_cache() {
use std::{
os::unix::fs::PermissionsExt,
sync::atomic::{AtomicUsize, Ordering},
};
static SCRATCH_COUNTER: AtomicUsize = AtomicUsize::new(0);
let root = workspace_root();
let lockfile = root.join("Cargo.lock");
let before = fs::read(&lockfile).unwrap();
let scratch = Scratch(std::env::temp_dir().join(format!(
"smith-dependency-e2e-{}-{}",
std::process::id(),
SCRATCH_COUNTER.fetch_add(1, Ordering::Relaxed)
)));
fs::create_dir(&scratch.0).unwrap();
let bin = scratch.0.join("bin");
let fixtures = scratch.0.join("fixtures");
let cargo_home = scratch.0.join("cargo-home");
fs::create_dir(&bin).unwrap();
fs::create_dir(&fixtures).unwrap();
fs::create_dir(&cargo_home).unwrap();
let helper = bin.join("cargo");
fs::copy(
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/cargo-offline.sh"),
&helper,
)
.unwrap();
fs::set_permissions(&helper, fs::Permissions::from_mode(0o755)).unwrap();
write_metadata_fixtures(&fixtures);
let mut paths = vec![bin];
paths.extend(std::env::split_paths(&std::env::var_os("PATH").unwrap()));
let output = assert_cmd::Command::new(env!("CARGO_BIN_EXE_xtask"))
.current_dir(&root)
.env("PATH", std::env::join_paths(paths).unwrap())
.env("CARGO_HOME", &cargo_home)
.env("SMITH_METADATA", fixtures.join("workspace.json"))
.env("SMITH_FIXTURES", &fixtures)
.args(["deps", "--offline"])
.timeout(Duration::from_secs(120))
.assert()
.success()
.get_output()
.stdout
.clone();
let report = String::from_utf8(output).unwrap();
assert_eq!(
report,
concat!(
"Offline registry-cache evidence only; upstream freshness is unverified.\n",
"Crates.io only: git, path, and alternate registries excluded; compatibility resolves with default features disabled.\n",
"member | scope | target | dependency | requirement | locked | latest compatible | latest stable | constraint reason\n",
"smith-fixture | normal | all-targets | ureq | ~3.4 | 3.4.1 | 3.4.1 | 3.5.0 | smith-harness, http stack; tilde pin: the chunk-gap timeout uses ureq::unversioned\n",
"smith-fixture | normal | all-targets | wasmtime | ^49.0.2 | 49.0.2 | 49.0.2 | 50.0.0 | smith-harness: Wasmtime hosts components; guest wit-bindgen must align with its component tooling release, not independently chase latest. Wasmi or Wasmer remain alternatives only after component compatibility and Smith workload benchmarks justify replacing Wasmtime. smith-harness, wasm plugin engine\n",
"smith-fixture | normal | all-targets | wit-bindgen | =0.62.0 | 0.62.0 | 0.62.0 | 0.63.0 | plugins/echo: guest component bindings aligned with Wasmtime's release set.\n",
)
);
assert_eq!(fs::read(&lockfile).unwrap(), before);
}
fn write_metadata_fixtures(directory: &std::path::Path) {
let registry = "registry+https://github.com/rust-lang/crates.io-index";
let workspace_id = "smith-fixture 0.0.0 (path+file:///fixture)";
let dependencies = [
("ureq", "~3.4", "3.4.1", "ureq"),
("wasmtime", "^49.0.2", "49.0.2", "wasmtime"),
("wit-bindgen", "=0.62.0", "0.62.0", "wit_bindgen"),
];
let workspace_dependencies = dependencies
.iter()
.map(|(name, requirement, _, _)| {
serde_json::json!({
"name": name,
"source": registry,
"req": requirement,
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": false,
"features": []
})
})
.collect::<Vec<_>>();
let packages = std::iter::once(serde_json::json!({
"id": workspace_id,
"name": "smith-fixture",
"version": "0.0.0",
"source": null,
"dependencies": workspace_dependencies
}))
.chain(dependencies.iter().map(|(name, _, locked, _)| {
serde_json::json!({
"id": format!("{name} {locked} ({registry})"),
"name": name,
"version": locked,
"source": registry,
"dependencies": []
})
}))
.collect::<Vec<_>>();
let edges = dependencies
.iter()
.map(|(name, _, locked, edge)| {
serde_json::json!({
"name": edge,
"pkg": format!("{name} {locked} ({registry})"),
"dep_kinds": [{"kind": null, "target": null}]
})
})
.collect::<Vec<_>>();
let metadata = serde_json::json!({
"packages": packages,
"workspace_members": [workspace_id],
"resolve": {"nodes": [{"id": workspace_id, "deps": edges}]}
});
fs::write(
directory.join("workspace.json"),
serde_json::to_vec(&metadata).unwrap(),
)
.unwrap();
for (name, _, compatible, _) in dependencies {
let latest = match name {
"ureq" => "3.5.0",
"wasmtime" => "50.0.0",
"wit-bindgen" => "0.63.0",
_ => unreachable!(),
};
for (label, version) in [("compatible", compatible), ("latest", latest)] {
let package = serde_json::json!({
"id": format!("{name} {version} ({registry})"),
"name": name,
"version": version,
"source": registry,
"dependencies": []
});
let metadata = serde_json::json!({
"packages": [package],
"workspace_members": [],
"resolve": {"nodes": []}
});
fs::write(
directory.join(format!("{name}-{label}.json")),
serde_json::to_vec(&metadata).unwrap(),
)
.unwrap();
}
}
}
struct Scratch(PathBuf);
impl Drop for Scratch {
fn drop(&mut self) {
fs::remove_dir_all(&self.0).unwrap();
}
}