plugin/handler-rust-toolchain-wasm/tests/native_wasm_agree.rs
//! The rust-toolchain half of the native-vs-wasm agreement guard.
//!
//! Same standard as the Skidbladnir pair — the comparisons come from
//! `holger_plugin_host::agreement`, so both handler pairs are held to one
//! implementation of the assertions rather than two that can drift.
//!
//! It fails, never skips, on a missing or stale module.
use std::path::PathBuf;
use holger_handler_rust_toolchain::RustToolchainHandler;
use holger_plugin_host::agreement::Surfaces;
use traits::{ArtifactFormat, ArtifactId};
const WASM: &str = "holger_handler_rust_toolchain_wasm.wasm";
const REPO: &str = "toolchains";
fn source_dirs() -> Vec<PathBuf> {
let m = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
vec![
m.join("src"),
m.join("../handler-rust-toolchain/src"),
m.join("../handler-bundle-core/src"),
m.join("../abi/src"),
]
}
fn surfaces() -> Surfaces {
Surfaces::build(REPO, RustToolchainHandler::new(), WASM, &source_dirs())
}
fn id(name: &str, version: &str) -> ArtifactId {
ArtifactId {
namespace: None,
name: name.into(),
version: version.into(),
}
}
#[test]
fn both_surfaces_report_the_same_identity() {
surfaces().assert_identity("rust-toolchain", ArtifactFormat::Znippy, true);
}
/// The hyphenated-name case, which is where a naive `split('-')` would diverge
/// between two implementations.
#[test]
fn a_hyphenated_bundle_name_resolves_the_same_on_both_surfaces() {
let s = surfaces();
let body = b"\x00toolchain,bundle:\xff".to_vec();
s.seed("rust-dev-rhel8-1.97.1.znippy", &body);
s.assert_fetch(&id("rust-dev-rhel8", "1.97.1"), Some(&body));
// MEASURED, not assumed: the flat `{name}-{version}.znippy` key is
// many-to-one, so ("rust", "dev-rhel8-1.97.1") addresses the SAME blob. Both
// surfaces must agree on that too — an alias that resolved on one side and
// 404'd on the other would be a real ABI defect, and asserting a miss here
// would have been asserting something false.
s.assert_fetch(&id("rust", "dev-rhel8-1.97.1"), Some(&body));
// What the last-hyphen split actually decides is the CANONICAL direction:
// reading a key back out of the store yields one coordinate, and it is the
// one with the hyphens kept in the name.
s.assert_list(None, 10, &[("rust-dev-rhel8", "1.97.1", body.len() as i64)]);
s.assert_coordinate(
"/toolchains/rust-dev-rhel8/1.97.1",
Some(("rust-dev-rhel8", "1.97.1")),
);
// A coordinate comes from PATH SEGMENTS, so the alias is a different
// coordinate here even though it is the same blob — on both surfaces.
s.assert_coordinate(
"/toolchains/rust/dev-rhel8-1.97.1",
Some(("rust", "dev-rhel8-1.97.1")),
);
}
/// The shared classifier, whose components here are DERIVED from the path (a
/// crate directory, a target triple) rather than a fixed set.
#[test]
fn the_shared_classifier_answers_identically_through_http() {
let s = surfaces();
s.seed("rust-dev-rhel8-1.97.1.znippy", b"sealed");
for (path, kind, component) in [
(
"vendor/serde-1.0.203/src/lib.rs",
"vendor-crate",
"serde-1.0.203",
),
(
"toolchain/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd.rlib",
"rust-std",
"x86_64-unknown-linux-gnu",
),
("toolchain/bin/rustc", "toolchain-bin", "rustc"),
("manifest/toolchain.pins.json", "toolchain-pins", "-"),
("manifest/vendor.lock", "vendor-lock", "-"),
("cargo-config/config.toml", "cargo-config", "-"),
] {
let want = format!("kind\t{kind}\ncomponent\t{component}\nencrypted\tfalse");
s.assert_http(
"GET",
&format!("/{REPO}/rust-dev-rhel8/1.97.1/classify/{path}"),
b"",
200,
Some(want.as_bytes()),
);
}
s.assert_http(
"GET",
&format!("/{REPO}/rust-dev-rhel8/1.97.1/classify/README.md"),
b"",
404,
None,
);
}
/// The name predicate is what keeps a Skidbladnir bundle out of this
/// repository's listing — and both surfaces must apply it identically.
#[test]
fn only_rust_dev_bundles_are_listed_on_both_surfaces() {
let s = surfaces();
s.seed("rust-dev-rhel8-1.97.1.znippy", b"aaa");
s.seed("rust-dev-rhel9-1.98.0.znippy", b"bbbb");
s.seed("tillsynia-20260706.znippy", b"not mine");
s.assert_list(
None,
10,
&[
("rust-dev-rhel8", "1.97.1", 3),
("rust-dev-rhel9", "1.98.0", 4),
],
);
s.assert_list(Some("rhel9"), 10, &[("rust-dev-rhel9", "1.98.0", 4)]);
}
#[test]
fn the_bundle_download_carries_the_same_status_headers_and_body() {
let s = surfaces();
let body = b"\x00sealed:toolchain,bytes\xff".to_vec();
s.seed("rust-dev-rhel8-1.97.1.znippy", &body);
let (headers, _) = s.assert_http(
"GET",
&format!("/{REPO}/rust-dev-rhel8/1.97.1"),
b"",
200,
Some(&body),
);
let ct = headers
.iter()
.find(|(k, _)| k == "content-type")
.expect("no content-type");
assert_eq!(ct.1, "application/vnd.znippy.bundle");
s.assert_http(
"GET",
&format!("/{REPO}/rust-dev-rhel8/nope"),
b"",
404,
None,
);
}
#[test]
fn a_write_on_one_surface_is_readable_on_the_other() {
let s = surfaces();
s.assert_put_crosses(&id("rust-dev-rhel8", "2.0.0"), b"\x00fresh,toolchain:\xff");
}