use std::any::TypeId;
use common::{
protocol::{
hint::MockHintWalker,
request_hint::{MockRequestHintVisitor, RequestHintFactory},
},
walker::MockWalker,
};
use mockall::predicate::eq;
use treaty::{
any::{OwnedStatic, TypeNameId},
effect::blocking::Blocking,
protocol::{
visitor::{RequestHint, RequestHintProto, ValueKnown, ValueProto, VisitResult},
walker::hint::HintProto,
DynWalker,
},
Flow,
};
use crate::common::protocol::hint::KnownFactory;
mod common;
#[test]
fn hints_can_be_requested() {
let mut mock = MockRequestHintVisitor::<Blocking>::new();
// We will request a hint from the visitor.
mock.expect_request_hint().once().return_const(
(|_, mut walker| {
// Lookup the value protocol on the walker.
let obj = walker
.upcast_mut::<HintProto<ValueProto<OwnedStatic<i32>, Blocking>>>()
.unwrap();
// Get the known for the value protocol.
assert_eq!(
obj.known(&()).value(),
Ok(ValueKnown {
preview: Some(&OwnedStatic(42))
})
);
// We are done.
VisitResult::Control(Flow::Done)
}) as RequestHintFactory,
);
// This mock becomes the visitor.
let visitor: &mut dyn RequestHint<Blocking> = &mut mock;
let mut mock = MockWalker::<(), ()>::new();
// The visitor will lookup the value protocol on the walker.
mock.expect_traits_mut()
.once()
.with(eq(TypeNameId::of::<
HintProto<ValueProto<OwnedStatic<i32>, Blocking>>,
>()))
.returning(|_id| {
let mut mock = MockHintWalker::<ValueProto<OwnedStatic<i32>, Blocking>>::new();
// Expect to give a known for the value protocol to the visitor.
mock.expect_known().once().return_const(
(|_, ()| {
Ok(ValueKnown {
preview: Some(&OwnedStatic(42)),
})
}) as KnownFactory<ValueProto<OwnedStatic<i32>, Blocking>>,
);
Some(Box::new(mock))
});
// Request a hint from the visitor.
assert!(matches!(
visitor.request_hint(DynWalker(&mut mock)).value(),
VisitResult::Control(Flow::Done)
));
}
#[test]
fn request_hint_proto() {
// The type id of the higher ranked type.
let id = TypeId::of::<RequestHintProto<Blocking>>();
// The type id for the lifetime containing value protocol trait object.
let name_id = TypeNameId::of_lower::<dyn RequestHint<Blocking> + Send + Sync>();
// They should be the same.
assert_eq!(id, name_id.into_type_id());
}