fix: align interface macros with canonical values

This commit is contained in:
2026-09-29 06:11:07 +09:00
parent 7f4e0e4460
commit 2d524723a4
14 changed files with 740 additions and 528 deletions
+45 -50
View File
@@ -1,14 +1,14 @@
use std::cell::{Cell, RefCell};
use std::collections::BTreeMap;
use wip_host::{
CallErrorKind, CallRequest, InterfaceRegistry, InterfaceTarget, PublishedObject, Validator,
WipObject,
CallErrorKind, CallRequest, InterfaceRegistry, InterfaceTarget, ObjectId, PublishedObject,
Validator, WipObject,
};
use wip_interface::{
CodecError, HostError, NamedValue, OperationResult, TypeDeclaration, TypeExpr, Value, WipType,
interface,
CodecError, HostError, OperationResult, TypeDeclaration, TypeExpr, Value, WipType, interface,
};
use wip_protocol::{ObjectId, ProtocolErrorCategory};
use wip_protocol::ProtocolErrorCode;
#[interface]
pub trait Reader {
@@ -143,7 +143,7 @@ fn request(
reference: &wip_host::InterfaceRef,
interface_validator: Option<&[u8]>,
operation: &str,
arguments: Vec<NamedValue>,
arguments: BTreeMap<String, Value>,
) -> CallRequest {
CallRequest {
object: ObjectId(object.into()),
@@ -170,7 +170,7 @@ fn registry_exposes_opaque_validated_descriptor_observations() {
assert!(registry.resolve("wip-interface:unknown:0").is_none());
let observation = registry.observe(reader.reference()).unwrap();
assert_eq!(observation.reference, *reader.reference());
assert_eq!(observation.descriptor.name, reader.reference().as_str());
assert_eq!(observation.descriptor, ReaderDefinition::descriptor());
assert_eq!(observation.validator, None);
observation.descriptor.validate().unwrap();
@@ -207,15 +207,18 @@ fn publication_is_explicit_ordered_qualified_and_request_scoped() {
reader.reference().as_str().to_owned()
]
);
wip_protocol::InterfaceObservation {
object: object.clone(),
descriptors: vec![
registry.observe(writer.reference()).unwrap().descriptor,
registry.observe(reader.reference()).unwrap().descriptor,
],
}
.validate()
.unwrap();
registry
.observe(writer.reference())
.unwrap()
.descriptor
.validate()
.unwrap();
registry
.observe(reader.reference())
.unwrap()
.descriptor
.validate()
.unwrap();
assert!(!format!("{object:?}").contains("private/backend/path"));
let writer_result = publication
@@ -225,7 +228,7 @@ fn publication_is_explicit_ordered_qualified_and_request_scoped() {
writer.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap();
let reader_result = publication
@@ -235,11 +238,11 @@ fn publication_is_explicit_ordered_qualified_and_request_scoped() {
reader.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap();
assert_eq!(writer_result.value, Some(Value::String("writer".into())));
assert_eq!(reader_result.value, Some(Value::String("reader".into())));
assert_eq!(writer_result.value, Value::String("writer".into()));
assert_eq!(reader_result.value, Value::String("reader".into()));
assert_eq!(publication.implementation().calls.get(), 2);
assert_eq!(
publication
@@ -267,13 +270,13 @@ fn implemented_but_unexposed_interface_is_not_a_member() {
hidden.reference(),
None,
"hidden",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(error.kind(), CallErrorKind::InterfaceMismatch);
assert_eq!(
error.protocol_error().category,
ProtocolErrorCategory::InterfaceNotFound
error.protocol_error().code,
ProtocolErrorCode::InterfaceMismatch
);
assert_eq!(publication.implementation().calls.get(), 0);
}
@@ -282,7 +285,8 @@ fn implemented_but_unexposed_interface_is_not_a_member() {
fn zero_interface_objects_are_valid() {
let publication = PublishedObject::new(Document::new("empty"));
let object = publication.protocol_object();
assert_eq!(object.id, ObjectId("empty".into()));
assert_eq!(object.name, "empty");
assert_eq!(object.r#ref.as_deref(), Some("empty"));
assert!(object.interfaces.is_empty());
object.validate().unwrap();
}
@@ -316,13 +320,13 @@ fn operation_and_argument_failures_are_mapped_without_execution() {
reader.reference(),
None,
"missing",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(missing.kind(), CallErrorKind::OperationNotFound);
assert_eq!(
missing.protocol_error().category,
ProtocolErrorCategory::OperationNotFound
missing.protocol_error().code,
ProtocolErrorCode::OperationNotFound
);
let invalid = publication
@@ -332,16 +336,13 @@ fn operation_and_argument_failures_are_mapped_without_execution() {
reader.reference(),
None,
"add",
vec![NamedValue {
name: "left".into(),
value: Value::String("wrong".into()),
}],
BTreeMap::from([("left".into(), Value::String("wrong".into()))]),
))
.unwrap_err();
assert_eq!(invalid.kind(), CallErrorKind::InvalidArguments);
assert_eq!(
invalid.protocol_error().category,
ProtocolErrorCategory::InvalidArguments
invalid.protocol_error().code,
ProtocolErrorCode::InvalidArguments
);
assert_eq!(publication.implementation().calls.get(), 0);
}
@@ -361,14 +362,11 @@ fn invalid_implementation_result_is_internal_and_not_returned() {
broken.reference(),
None,
"broken",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(error.kind(), CallErrorKind::InvalidResult);
assert_eq!(
error.protocol_error().category,
ProtocolErrorCategory::Internal
);
assert_eq!(error.protocol_error().code, ProtocolErrorCode::Internal);
assert_eq!(publication.implementation().calls.get(), 1);
}
@@ -387,7 +385,7 @@ fn object_validator_missing_and_mismatch_are_distinct_and_prevent_execution() {
reader.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(missing.kind(), CallErrorKind::ValidatorRequired);
@@ -399,7 +397,7 @@ fn object_validator_missing_and_mismatch_are_distinct_and_prevent_execution() {
reader.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(mismatch.kind(), CallErrorKind::ValidatorMismatch);
@@ -412,7 +410,7 @@ fn object_validator_missing_and_mismatch_are_distinct_and_prevent_execution() {
reader.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap();
assert_eq!(result.validator, Some(Validator::new(b"object-v1")));
@@ -439,7 +437,7 @@ fn interface_validator_missing_and_mismatch_are_distinct_and_prevent_execution()
writer.reference(),
None,
"label",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(missing.kind(), CallErrorKind::InterfaceValidatorRequired);
@@ -451,7 +449,7 @@ fn interface_validator_missing_and_mismatch_are_distinct_and_prevent_execution()
writer.reference(),
Some(b"schema-v0"),
"label",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(mismatch.kind(), CallErrorKind::InterfaceValidatorMismatch);
@@ -464,10 +462,10 @@ fn interface_validator_missing_and_mismatch_are_distinct_and_prevent_execution()
writer.reference(),
Some(b"schema-v1"),
"label",
vec![],
BTreeMap::new(),
))
.unwrap();
assert_eq!(result.value, Some(Value::String("writer".into())));
assert_eq!(result.value, Value::String("writer".into()));
}
#[test]
@@ -496,12 +494,9 @@ fn host_failures_map_to_internal_without_becoming_domain_values() {
failing.reference(),
None,
"fail",
vec![],
BTreeMap::new(),
))
.unwrap_err();
assert_eq!(error.kind(), CallErrorKind::Implementation);
assert_eq!(
error.protocol_error().category,
ProtocolErrorCategory::Internal
);
assert_eq!(error.protocol_error().code, ProtocolErrorCode::Internal);
}
@@ -1,6 +1,5 @@
use wip_host::{InterfaceRegistry, PublishedObject, WipObject};
use wip_host::{InterfaceRegistry, ObjectId, PublishedObject, WipObject};
use wip_interface::{OperationResult, interface};
use wip_protocol::ObjectId;
#[interface]
pub trait Search {
@@ -1,27 +1,27 @@
error[E0277]: the trait bound `Object: Search` is not satisfied
--> tests/ui/unimplemented_interface.rs:21:58
--> tests/ui/unimplemented_interface.rs:20:58
|
21 | let _published = PublishedObject::new(Object).expose(&search).unwrap();
20 | let _published = PublishedObject::new(Object).expose(&search).unwrap();
| ------ ^^^^^^^ unsatisfied trait bound
| |
| required by a bound introduced by this call
|
help: the trait `Search` is not implemented for `Object`
--> tests/ui/unimplemented_interface.rs:10:1
--> tests/ui/unimplemented_interface.rs:9:1
|
10 | struct Object;
9 | struct Object;
| ^^^^^^^^^^^^^
help: this trait has no implementations, consider adding one
--> tests/ui/unimplemented_interface.rs:6:1
|
6 | pub trait Search {
| ^^^^^^^^^^^^^^^^
note: required for `SearchDefinition` to implement `InterfaceImplementation<Object>`
--> tests/ui/unimplemented_interface.rs:5:1
|
5 | #[interface]
5 | pub trait Search {
| ^^^^^^^^^^^^^^^^
note: required for `SearchDefinition` to implement `InterfaceImplementation<Object>`
--> tests/ui/unimplemented_interface.rs:4:1
|
4 | #[interface]
| ^^^^^^^^^^^^
6 | pub trait Search {
5 | pub trait Search {
| ^^^^^^
note: required by a bound in `PublishedObject::<T>::expose`
--> src/lib.rs