use packr::{parse_pact, InterfaceImpl};
#[test]
fn handler_hash_matches_actor_hash_for_record_interface() {
let src = r#"
interface podman {
@package: string = "theater:simple"
record mount-spec {
source: string,
target: string,
read-only: bool,
}
record container-spec {
image: string,
name: string,
mounts: list<mount-spec>,
}
exports {
run: func(spec: container-spec) -> result<string, string>
stop: func(name: string) -> result<_, string>
}
}
"#;
let pact = parse_pact(src).expect("parse pact");
let iface = InterfaceImpl::from_pact(&pact);
let handler_hash = iface.hash();
use packr_abi::{
hash_function, hash_interface, hash_list, hash_record, hash_result, Binding, HASH_BOOL,
HASH_STRING,
};
let mount_spec_hash = hash_record(&[
("read-only", HASH_BOOL),
("source", HASH_STRING),
("target", HASH_STRING),
]);
let container_spec_hash = hash_record(&[
("image", HASH_STRING),
("mounts", hash_list(&mount_spec_hash)),
("name", HASH_STRING),
]);
let run_hash = hash_function(
&[container_spec_hash],
&[hash_result(&HASH_STRING, &HASH_STRING)],
);
let stop_hash = hash_function(&[HASH_STRING], &[hash_result(&HASH_BOOL, &HASH_STRING)]);
let mut bindings = vec![
Binding {
name: "run",
hash: run_hash,
},
Binding {
name: "stop",
hash: stop_hash,
},
];
bindings.sort_by(|a, b| a.name.cmp(b.name));
let actor_hash = hash_interface("theater:simple/podman", &[], &bindings);
assert_eq!(
handler_hash.as_bytes(),
actor_hash.as_bytes(),
"handler hash and actor hash must agree for record-using interfaces"
);
}