plugin/handler-skidbladnir-wasm/tests/native_wasm_agree.rs
//! The guard that makes "the wasm handler reuses the native code" checkable.
//!
//! It loads the REAL `.wasm` through the REAL host and asserts that, over the
//! same store and the same requests, it answers exactly as the linked
//! `SkidbladnirHandler` does — status, headers, body, coordinates, listing rows.
//!
//! It is deliberately impossible to pass without a fresh module: a missing or
//! stale `.wasm` panics with the build command rather than skipping. A skip here
//! would be a permanent green.
//!
//! The comparisons themselves live in `holger_plugin_host::agreement`, shared
//! with the rust-toolchain guard, so the two handler pairs are held to one
//! standard rather than two hand-written ones that can drift.
use std::path::PathBuf;
use holger_handler_skidbladnir::SkidbladnirHandler;
use holger_plugin_host::agreement::Surfaces;
use traits::{ArtifactFormat, ArtifactId};
const WASM: &str = "holger_handler_skidbladnir_wasm.wasm";
const REPO: &str = "bundles";
/// Every crate whose logic ends up inside the module. Listing only this crate's
/// `src/` would make the staleness check blind to a change in the handler — which
/// is where all the logic actually is.
fn source_dirs() -> Vec<PathBuf> {
let m = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
vec![
m.join("src"),
m.join("../handler-skidbladnir/src"),
m.join("../handler-bundle-core/src"),
m.join("../abi/src"),
]
}
fn surfaces() -> Surfaces {
Surfaces::build(REPO, SkidbladnirHandler::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("skidbladnir", ArtifactFormat::Znippy, true);
}
#[test]
fn both_surfaces_fetch_the_same_bytes() {
let s = surfaces();
// Bytes chosen to break a JSON wire format: NUL, a separator, non-ASCII.
let body = b"\x00tillsynia,bundle:\xc3\xa5\xc3\xa4\xc3\xb6\xff".to_vec();
s.seed("tillsynia-20260706.znippy", &body);
s.assert_fetch(&id("tillsynia", "20260706"), Some(&body));
s.assert_fetch(&id("tillsynia", "nosuchversion"), None);
}
#[test]
fn an_empty_bundle_is_not_a_missing_bundle_on_either_surface() {
let s = surfaces();
s.seed("empty-1.znippy", b"");
// The distinction znippy's JSON row format cannot make, asserted end to end.
s.assert_fetch(&id("empty", "1"), Some(b""));
s.assert_fetch(&id("gone", "1"), None);
}
#[test]
fn both_surfaces_resolve_the_same_coordinates() {
let s = surfaces();
s.assert_coordinate(
"/bundles/tillsynia/20260706",
Some(("tillsynia", "20260706")),
);
s.assert_coordinate(
"/bundles/tillsynia/20260706/classify/s3/doc.pdf",
Some(("tillsynia", "20260706")),
);
s.assert_coordinate("/bundles/", None);
s.assert_coordinate("/bundles/only-one-segment", None);
}
/// The route that puts the SHARED classifier on the wire. Both surfaces reach
/// `znippy_plugin_skidbladnir::member::classify`; if the wasm crate held its own
/// copy, this is where it would show.
#[test]
fn the_shared_classifier_answers_identically_through_http() {
let s = surfaces();
s.seed("tillsynia-20260706.znippy", b"sealed");
for (path, kind, component, encrypted) in [
("s3/2026/07/protokoll-123.pdf", "s3-blob", "minio", false),
("dbdump/njord.dump", "dbdump", "postgres", false),
(
"app/njord-mail-server.oci.tar",
"image",
"mail-server",
false,
),
("infra/talos/talos-1.13.iso", "talos-iso", "infra", false),
(
"njordconf/chart/njord-0.1.0.tgz",
"helm-chart",
"platform",
false,
),
("secrets/secrets.age", "secret", "secrets", true),
("lakespec.json", "lakespec", "-", false),
] {
let want = format!("kind\t{kind}\ncomponent\t{component}\nencrypted\t{encrypted}");
s.assert_http(
"GET",
&format!("/{REPO}/tillsynia/20260706/classify/{path}"),
b"",
200,
Some(want.as_bytes()),
);
}
// A path neither surface claims must 404 on both, not classify as something.
s.assert_http(
"GET",
&format!("/{REPO}/tillsynia/20260706/classify/README.md"),
b"",
404,
None,
);
}
#[test]
fn the_bundle_download_carries_the_same_status_headers_and_body() {
let s = surfaces();
let body = b"\x00sealed,bundle:bytes\xff".to_vec();
s.seed("tillsynia-20260706.znippy", &body);
let (headers, _) = s.assert_http(
"GET",
&format!("/{REPO}/tillsynia/20260706"),
b"",
200,
Some(&body),
);
// Assert the header VALUES, not just that the two agree — two identically
// empty header lists would agree.
let ct = headers
.iter()
.find(|(k, _)| k == "content-type")
.expect("no content-type");
assert_eq!(ct.1, "application/vnd.znippy.bundle");
let cl = headers
.iter()
.find(|(k, _)| k == "content-length")
.expect("no content-length");
assert_eq!(cl.1, body.len().to_string());
s.assert_http("GET", &format!("/{REPO}/tillsynia/nope"), b"", 404, None);
s.assert_http(
"DELETE",
&format!("/{REPO}/tillsynia/20260706"),
b"",
405,
None,
);
}
#[test]
fn both_surfaces_list_the_same_rows_in_the_same_order() {
let s = surfaces();
s.seed("tillsynia-20260706.znippy", b"aaa");
s.seed("other-1.0.znippy", b"bb");
s.seed("not-a-bundle.txt", b"ignored");
s.assert_list(
None,
10,
&[("other", "1.0", 2), ("tillsynia", "20260706", 3)],
);
s.assert_list(Some("till"), 10, &[("tillsynia", "20260706", 3)]);
s.assert_list(None, 1, &[("other", "1.0", 2)]);
}
/// The strongest form of "same store, same key scheme": a write through one
/// surface is readable through the other.
#[test]
fn a_write_on_one_surface_is_readable_on_the_other() {
let s = surfaces();
s.assert_put_crosses(&id("newbundle", "9.9"), b"\x00fresh,bytes:\xff");
}
#[test]
fn a_put_with_an_empty_coordinate_is_refused_by_both() {
let s = surfaces();
s.assert_put_refused(&id("", "1.0"), "empty bundle name");
s.assert_put_refused(&id("x", ""), "empty version");
}