all protocols are tested
Konnor Andrews 2024-04-20
parent 5cae837 · commit da80a28
-rw-r--r--src/build/builders/debug.rs6
-rw-r--r--src/protocol/visitor/tag.rs2
-rw-r--r--src/protocol/visitor/value.rs4
-rw-r--r--src/walk/walkers/core/struct.rs5
-rw-r--r--src/walk/walkers/core/tag.rs3
-rw-r--r--tests/common/protocol.rs1
-rw-r--r--tests/common/protocol/recoverable.rs57
-rw-r--r--tests/protocol_visitor_recoverable.rs68
-rw-r--r--tests/protocol_visitor_request_hint.rs5
-rw-r--r--tests/protocol_visitor_sequence.rs5
-rw-r--r--tests/protocol_visitor_tag.rs102
-rw-r--r--tests/protocol_visitor_value.rs4
-rw-r--r--tests/protocol_walker_hint.rs11
13 files changed, 250 insertions, 23 deletions
diff --git a/src/build/builders/debug.rs b/src/build/builders/debug.rs
index cb447b6..b0b8003 100644
--- a/src/build/builders/debug.rs
+++ b/src/build/builders/debug.rs
@@ -5,10 +5,12 @@ use crate::{
any_trait,
effect::{Effect, Future},
protocol::{
- self, visitor::{
+ self,
+ visitor::{
DynSequenceScope, RequestHint, RequestHintProto, Sequence, Tag, TagDyn, TagProto,
Value, ValueProto, VisitResult,
- }, DynVisitor
+ },
+ DynVisitor,
},
protocol::{visitor::SequenceProto, DynWalker},
DynWalkerObjSafe, Flow,
diff --git a/src/protocol/visitor/tag.rs b/src/protocol/visitor/tag.rs
index dbedd22..67ac325 100644
--- a/src/protocol/visitor/tag.rs
+++ b/src/protocol/visitor/tag.rs
@@ -8,7 +8,7 @@ use crate::{
DynVisitor,
},
symbol::Symbol,
- DynWalkerObjSafe, DynWalkerAdapter, DynWalkerError, WalkerTypes,
+ DynWalkerAdapter, DynWalkerError, DynWalkerObjSafe, WalkerTypes,
};
use super::VisitResult;
diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs
index 8e902ab..e549935 100644
--- a/src/protocol/visitor/value.rs
+++ b/src/protocol/visitor/value.rs
@@ -100,7 +100,9 @@ pub fn visit_value<'a, 'ctx, T: Send + TypeName::LowerType<'a, 'ctx>, E: Effect>
where
TypeName::HigherRanked<'a, 'ctx, T>: TypeName::MemberType,
{
- if let Some(object) = visitor.0.upcast_mut::<ValueProto<TypeName::HigherRanked<'a, 'ctx, T>, E>>()
+ if let Some(object) = visitor
+ .0
+ .upcast_mut::<ValueProto<TypeName::HigherRanked<'a, 'ctx, T>, E>>()
{
// Allow the visitor to give a hint if it wants.
object.visit(value)
diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs
index 8fe0ce0..6a8119d 100644
--- a/src/walk/walkers/core/struct.rs
+++ b/src/walk/walkers/core/struct.rs
@@ -12,7 +12,10 @@ use crate::{
RecoverableKnown, RecoverableProto, RecoverableScope, SequenceKnown, SequenceProto,
SequenceScope, TagConst, TagDyn, TagError, TagHint, TagKnown, TagProto, ValueKnown,
ValueProto, VisitResult,
- }, walker::hint::{Hint, MetaKnown}, walker::hint::{HintMeta, HintProto, MetaHint}, DynVisitor, DynWalker
+ },
+ walker::hint::{Hint, MetaKnown},
+ walker::hint::{HintMeta, HintProto, MetaHint},
+ DynVisitor, DynWalker,
},
Flow, Status, WalkerTypes, TAG_FIELD_NAMES, TAG_MAP, TAG_STRUCT, TAG_TYPE_ID, TAG_TYPE_NAME,
};
diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs
index f20b449..29a450e 100644
--- a/src/walk/walkers/core/tag.rs
+++ b/src/walk/walkers/core/tag.rs
@@ -8,7 +8,8 @@ use crate::{
protocol::{
visitor::{
visit_request_hint, visit_value, SequenceProto, SequenceScope, TagError, VisitResult,
- }, DynVisitor, DynWalker
+ },
+ DynVisitor, DynWalker,
},
Flow, WalkerTypes,
};
diff --git a/tests/common/protocol.rs b/tests/common/protocol.rs
index ab619e0..38c0c61 100644
--- a/tests/common/protocol.rs
+++ b/tests/common/protocol.rs
@@ -1,4 +1,5 @@
pub mod hint;
+pub mod recoverable;
pub mod request_hint;
pub mod sequence;
pub mod tag;
diff --git a/tests/common/protocol/recoverable.rs b/tests/common/protocol/recoverable.rs
new file mode 100644
index 0000000..f1dab5c
--- /dev/null
+++ b/tests/common/protocol/recoverable.rs
@@ -0,0 +1,57 @@
+use mockall::mock;
+use treaty::{
+ any::{any_trait, TypeName},
+ effect::{Effect, Future},
+ protocol::{
+ visitor::{DynRecoverableScope, Recoverable, RecoverableProto, RecoverableScope},
+ DynWalker,
+ },
+ protocol::{
+ visitor::{
+ DynSequenceScope, RequestHint, RequestHintProto, Sequence, SequenceProto,
+ SequenceScope, Value, ValueProto, VisitResult,
+ },
+ DynVisitor,
+ },
+ Flow, Status,
+};
+
+pub type RecoverableScopeFactory<E> =
+ for<'a, 'ctx> fn(
+ &'ctx (),
+ DynRecoverableScope<'a, 'ctx, E>,
+ ) -> VisitResult<DynRecoverableScope<'a, 'ctx, E>>;
+
+mock! {
+ pub RecoverableVisitor<E> {
+ pub fn visit(&mut self) -> RecoverableScopeFactory<E>;
+ }
+}
+
+any_trait! {
+ impl['ctx, E] MockRecoverableVisitor<E> = [
+ RecoverableProto<E>
+ ] where
+ E: Effect,
+}
+
+impl<'ctx, E: Effect> Recoverable<'ctx, E> for MockRecoverableVisitor<E> {
+ fn visit<'a>(
+ &'a mut self,
+ scope: DynRecoverableScope<'a, 'ctx, E>,
+ ) -> Future<'a, VisitResult<DynRecoverableScope<'a, 'ctx, E>>, E> {
+ E::ready(self.visit()(&(), scope))
+ }
+}
+
+mock! {
+ pub RecoverableScopeVisitor<E> {
+ pub fn new_walk<'a, 'ctx>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Status;
+ }
+}
+
+impl<'ctx, E: Effect> RecoverableScope<'ctx, E> for MockRecoverableScopeVisitor<E> {
+ fn new_walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Status, E> {
+ E::ready(self.new_walk(visitor))
+ }
+}
diff --git a/tests/protocol_visitor_recoverable.rs b/tests/protocol_visitor_recoverable.rs
new file mode 100644
index 0000000..07ec092
--- /dev/null
+++ b/tests/protocol_visitor_recoverable.rs
@@ -0,0 +1,68 @@
+use common::protocol::recoverable::MockRecoverableVisitor;
+use treaty::{
+ any::OwnedStatic,
+ effect::Blocking,
+ protocol::{
+ visitor::{Recoverable, ValueProto, VisitResult},
+ DynVisitor,
+ },
+ Flow,
+};
+
+use crate::common::{
+ builder::MockBuilder,
+ protocol::recoverable::{MockRecoverableScopeVisitor, RecoverableScopeFactory},
+};
+
+mod common;
+
+/// Tests that the recoverable protocol allows multiple walks by the visitor.
+#[test]
+fn recoverable_can_be_visited() {
+ let mut mock = MockRecoverableVisitor::<Blocking>::new();
+
+ // Expect a visit using the rescoverable protocol.
+ mock.expect_visit().once().return_const(
+ (|(), scope| {
+ let mut visitor = MockBuilder::<(), (), ()>::new();
+
+ // Expect that the visitor gets used.
+ visitor.expect_traits().times(2).return_const(None);
+
+ // Attempt to walk once.
+ assert_eq!(
+ scope.new_walk(DynVisitor(&mut visitor)).into_inner(),
+ Ok(())
+ );
+
+ // Attempt to walk twice.
+ assert_eq!(
+ scope.new_walk(DynVisitor(&mut visitor)).into_inner(),
+ Ok(())
+ );
+
+ // We are done.
+ VisitResult::Control(Flow::Done)
+ }) as RecoverableScopeFactory<Blocking>,
+ );
+
+ let visitor: &mut dyn Recoverable<Blocking> = &mut mock;
+
+ let mut scope = MockRecoverableScopeVisitor::new();
+
+ // Expect two walks of the recoverable walker.
+ scope.expect_new_walk().times(2).returning(|visitor| {
+ // Attempt to use the visitor.
+ assert!(visitor
+ .upcast::<ValueProto<OwnedStatic<i32>, Blocking>>()
+ .is_none());
+
+ Ok(())
+ });
+
+ // Visit using the recoverable protocol.
+ assert!(matches!(
+ visitor.visit(&mut scope).into_inner(),
+ VisitResult::Control(Flow::Done)
+ ));
+}
diff --git a/tests/protocol_visitor_request_hint.rs b/tests/protocol_visitor_request_hint.rs
index 234d64f..06f811f 100644
--- a/tests/protocol_visitor_request_hint.rs
+++ b/tests/protocol_visitor_request_hint.rs
@@ -14,6 +14,7 @@ use treaty::{
protocol::{
visitor::{RequestHint, RequestHintProto, ValueKnown, ValueProto, VisitResult},
walker::hint::HintProto,
+ DynWalker,
},
Flow,
};
@@ -28,7 +29,7 @@ fn hints_can_be_requested() {
// We will request a hint from the visitor.
mock.expect_request_hint().once().return_const(
- (|_, walker| {
+ (|_, mut walker| {
// Lookup the value protocol on the walker.
let obj = walker
.upcast_mut::<HintProto<ValueProto<OwnedStatic<i32>, Blocking>>>()
@@ -75,7 +76,7 @@ fn hints_can_be_requested() {
// Request a hint from the visitor.
assert!(matches!(
- visitor.request_hint(&mut mock).into_inner(),
+ visitor.request_hint(DynWalker(&mut mock)).into_inner(),
VisitResult::Control(Flow::Done)
));
}
diff --git a/tests/protocol_visitor_sequence.rs b/tests/protocol_visitor_sequence.rs
index 52433dc..1b74c3f 100644
--- a/tests/protocol_visitor_sequence.rs
+++ b/tests/protocol_visitor_sequence.rs
@@ -6,7 +6,10 @@ use common::protocol::sequence::{
use treaty::{
any::{OwnedStatic, TypeNameId},
effect::Blocking,
- protocol::{visitor::{Sequence, SequenceProto, ValueProto, VisitResult}, DynVisitor},
+ protocol::{
+ visitor::{Sequence, SequenceProto, ValueProto, VisitResult},
+ DynVisitor,
+ },
Flow,
};
diff --git a/tests/protocol_visitor_tag.rs b/tests/protocol_visitor_tag.rs
index 9e92ff6..eb24523 100644
--- a/tests/protocol_visitor_tag.rs
+++ b/tests/protocol_visitor_tag.rs
@@ -1,40 +1,64 @@
+use std::any::TypeId;
+
use common::protocol::tag::MockTagVisitor;
use treaty::{
+ any::{OwnedStatic, TypeNameId},
effect::Blocking,
- protocol::visitor::{Tag, TagDyn, VisitResult},
+ protocol::{
+ visitor::{Tag, TagConst, TagDyn, TagProto, ValueProto, VisitResult},
+ DynVisitor,
+ },
symbol::Symbol,
DynWalkerAdapter, Flow,
};
-use crate::common::walker::MockWalker;
+use crate::common::{builder::MockBuilder, walker::MockWalker};
mod common;
+/// Tests that the tag protocol can be visited with a value walker.
#[test]
-fn demo() {
+fn tag_can_be_visited() {
let mut mock = MockTagVisitor::<TagDyn, Blocking>::new();
+ // Expect a visit with the tag protocol.
mock.expect_visit()
.once()
.returning(|TagDyn(kind), walker| {
+ // The kind should be test.
assert_eq!(kind, Symbol::new("test"));
-
+
+ let mut builder = MockBuilder::<(), (), ()>::new();
+
+ // Expect that the builder is attempted to be used by the walker for the value.
+ builder.expect_traits().once().return_const(None);
+
+ // Walk the value of the tag.
+ walker.walk(DynVisitor(&mut builder));
+
+ // We are done.
VisitResult::Control(Flow::Done)
});
+ // Use the tag protocol trait.
let visitor: &mut dyn Tag<TagDyn, Blocking> = &mut mock;
let mut walker = MockWalker::<(), ()>::new();
- walker.expect_walk()
- .once()
- .returning(|visitor| {
-
- Ok(())
- });
+ // Expect the tag value to be walked.
+ walker.expect_walk().once().returning(|visitor| {
+ // Attempt to use the visitor.
+ assert!(visitor
+ .upcast::<ValueProto<OwnedStatic<i32>, Blocking>>()
+ .is_none());
+ Ok(())
+ });
+
+ // We need to use the adapter to make the walker object safe to pass to the protocol.
let mut walker = DynWalkerAdapter::new(walker);
+ // Visit the tag protocol for kind test with the value walker.
assert!(matches!(
visitor
.visit(TagDyn(Symbol::new("test")), &mut walker)
@@ -42,3 +66,61 @@ fn demo() {
VisitResult::Control(Flow::Done)
));
}
+
+/// Checks that compile time tag symbols work.
+#[test]
+fn const_tag_can_be_visited() {
+ const TEST: u64 = Symbol::new("test").to_int();
+
+ let mut mock = MockTagVisitor::<TagConst<TEST>, Blocking>::new();
+
+ // Expect a visit with the tag protocol.
+ mock.expect_visit().once().returning(|TagConst, walker| {
+ let mut builder = MockBuilder::<(), (), ()>::new();
+
+ // Expect that the builder is attempted to be used by the walker for the value.
+ builder.expect_traits().once().return_const(None);
+
+ // Walk the value of the tag.
+ walker.walk(DynVisitor(&mut builder));
+
+ // We are done.
+ VisitResult::Control(Flow::Done)
+ });
+
+ // Use the tag protocol trait.
+ let visitor: &mut dyn Tag<TagConst<TEST>, Blocking> = &mut mock;
+
+ let mut walker = MockWalker::<(), ()>::new();
+
+ // Expect the tag value to be walked.
+ walker.expect_walk().once().returning(|visitor| {
+ // Attempt to use the visitor.
+ assert!(visitor
+ .upcast::<ValueProto<OwnedStatic<i32>, Blocking>>()
+ .is_none());
+
+ Ok(())
+ });
+
+ // We need to use the adapter to make the walker object safe to pass to the protocol.
+ let mut walker = DynWalkerAdapter::new(walker);
+
+ // Visit the tag protocol for kind test with the value walker.
+ assert!(matches!(
+ visitor.visit(TagConst, &mut walker).into_inner(),
+ VisitResult::Control(Flow::Done)
+ ));
+}
+
+#[test]
+fn tag_proto() {
+ // The type id of the higher ranked type.
+ let id = TypeId::of::<TagProto<TagDyn, Blocking>>();
+
+ // The type id for the lifetime containing value protocol trait object.
+ let name_id = TypeNameId::of_lower::<dyn Tag<TagDyn, Blocking> + Send + Sync>();
+
+ // They should be the same.
+ assert_eq!(id, name_id.into_type_id());
+}
diff --git a/tests/protocol_visitor_value.rs b/tests/protocol_visitor_value.rs
index 8ca591c..374ed99 100644
--- a/tests/protocol_visitor_value.rs
+++ b/tests/protocol_visitor_value.rs
@@ -12,7 +12,9 @@ use treaty::{
},
effect::Blocking,
protocol::{
- visitor::{visit_value, Value, ValueKnown, ValueProto, VisitResult}, walker::hint::Hint, DynVisitor
+ visitor::{visit_value, Value, ValueKnown, ValueProto, VisitResult},
+ walker::hint::Hint,
+ DynVisitor,
},
Flow,
};
diff --git a/tests/protocol_walker_hint.rs b/tests/protocol_walker_hint.rs
index 6f39590..d15d345 100644
--- a/tests/protocol_walker_hint.rs
+++ b/tests/protocol_walker_hint.rs
@@ -6,7 +6,8 @@ use treaty::{
effect::{Blocking, Effect, Future, Spin},
hkt::higher_ranked_type,
protocol::{
- walker::hint::{self, Hint, HintMeta, HintProto, Meta, MetaKnown}, DynVisitor
+ walker::hint::{self, Hint, HintMeta, HintProto, Meta, MetaKnown},
+ DynVisitor,
},
Flow,
};
@@ -236,7 +237,9 @@ fn hint_can_have_temp_mutable_borrow() {
// We can call known to get what the walker knows about the protocol.
assert_eq!(
- walker.hint(DynVisitor(&mut visitor), Hint(&mut temp)).into_inner(),
+ walker
+ .hint(DynVisitor(&mut visitor), Hint(&mut temp))
+ .into_inner(),
Flow::Done
);
@@ -284,7 +287,9 @@ fn hint_can_have_context_borrow() {
// We can call known to get what the walker knows about the protocol.
assert_eq!(
- walker.hint(DynVisitor(&mut visitor), Hint(&context)).into_inner(),
+ walker
+ .hint(DynVisitor(&mut visitor), Hint(&context))
+ .into_inner(),
Flow::Done
);
}