behavior_actors/
requirements.rs1use behavior::{
4 BirthProtocol, EndpointAddress, LogicalDeliveryProtocols, NoBirthProtocols, Protocol,
5};
6
7impl<P> LogicalDeliveryProtocols
8 for crate::ReplyDeliveries<behavior::Delivery<P>, behavior::EstablishedDelivery<P>>
9where
10 P: Protocol,
11 P::Addr: EndpointAddress,
12{
13 type Protocols = BirthProtocol<P, NoBirthProtocols>;
14}
15
16impl<T> LogicalDeliveryProtocols for crate::HeterogeneousShutdownSends<T> {
17 type Protocols = NoBirthProtocols;
18}
19
20#[cfg(test)]
21mod tests {
22 use super::*;
23 use behavior::{
24 Actions, Behavior, BehaviorActed, Births, ChildChoice, MailAddr, Never, NoBirths, Protocol,
25 User,
26 };
27
28 struct RootProtocol;
29 struct SharedProtocol;
30 struct LeafProtocol;
31 struct ExternalProtocol;
32 macro_rules! protocol {
33 ($protocol:ty) => {
34 impl Protocol for $protocol {
35 type Addr = MailAddr;
36 type Msg = ();
37 }
38 };
39 }
40
41 protocol!(RootProtocol);
42 protocol!(SharedProtocol);
43 protocol!(LeafProtocol);
44 protocol!(ExternalProtocol);
45
46 struct Leaf;
47 struct Primary;
48 struct Fallback;
49 struct Root;
50
51 macro_rules! behavior {
52 ($behavior:ty, $protocol:ty, $birth:ty, $sends:ty) => {
53 impl Behavior for $behavior {
54 type Protocol = $protocol;
55 type Event = User<MailAddr, ()>;
56 type Sends = $sends;
57 type Ph = Never;
58 type Error = Never;
59 type Birth = $birth;
60
61 fn transition(
62 &mut self,
63 _: behavior::ActiveTurn,
64 _: Self::Event,
65 ) -> BehaviorActed<Self> {
66 Ok(Actions::cont())
67 }
68 }
69 };
70 }
71
72 behavior!(Leaf, LeafProtocol, NoBirths, Vec<Never>);
73 behavior!(Primary, SharedProtocol, Births<Leaf>, Vec<Never>);
74 behavior!(Fallback, SharedProtocol, NoBirths, Vec<Never>);
75 behavior!(
76 Root,
77 RootProtocol,
78 Births<ChildChoice<Primary, ChildChoice<Fallback, Never>>>,
79 Vec<behavior::Delivery<ExternalProtocol>>
80 );
81 #[test]
82 fn transitive_births_preserve_every_protocol_occurrence_and_exclude_sends() {
83 type Requirements = <Root as behavior::BirthProtocols>::Protocols;
84
85 fn contains<P: Protocol, Position, Product: behavior::BirthProtocolAt<P, Position>>() {}
86
87 contains::<RootProtocol, behavior::BirthProtocolHead, Requirements>();
88 contains::<
89 SharedProtocol,
90 behavior::BirthProtocolTail<behavior::BirthProtocolHead>,
91 Requirements,
92 >();
93 contains::<
94 LeafProtocol,
95 behavior::BirthProtocolTail<behavior::BirthProtocolTail<behavior::BirthProtocolHead>>,
96 Requirements,
97 >();
98 contains::<
99 SharedProtocol,
100 behavior::BirthProtocolTail<
101 behavior::BirthProtocolTail<
102 behavior::BirthProtocolTail<behavior::BirthProtocolHead>,
103 >,
104 >,
105 Requirements,
106 >();
107 }
108
109 #[test]
110 fn transparent_wrapper_preserves_inner_transitive_requirements_once() {
111 type Wrapped = crate::StopOnShutdown<Primary>;
112 type Requirements = <Wrapped as behavior::BirthProtocols>::Protocols;
113 type Expected =
114 BirthProtocol<SharedProtocol, BirthProtocol<LeafProtocol, NoBirthProtocols>>;
115
116 trait Same<T> {}
117 impl<T> Same<T> for T {}
118 fn exact<T: Same<Expected>>() {}
119 exact::<Requirements>();
120 }
121
122 #[test]
123 fn independently_projected_products_compose_without_losing_occurrences() {
124 type LeafRequirements = <Leaf as behavior::BirthProtocols>::Protocols;
125 type FallbackRequirements = <Fallback as behavior::BirthProtocols>::Protocols;
126 type Combined =
127 <LeafRequirements as behavior::BirthProtocolProduct>::Append<FallbackRequirements>;
128 type Expected =
129 BirthProtocol<LeafProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
130
131 trait Same<T> {}
132 impl<T> Same<T> for T {}
133 fn exact<T: Same<Expected>>() {}
134 exact::<Combined>();
135 }
136
137 #[test]
138 fn logical_projection_follows_named_lanes_and_excludes_nonlogical_lanes() {
139 type Named = crate::DeliveryOutcomes<
140 Vec<behavior::Delivery<ExternalProtocol>>,
141 Vec<behavior::Delivery<SharedProtocol>>,
142 >;
143 type NamedActual = <Named as LogicalDeliveryProtocols>::Protocols;
144 type NamedExpected =
145 BirthProtocol<ExternalProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
146 trait Same<T> {}
147 impl<T> Same<T> for T {}
148 fn exact<T: Same<Expected>, Expected>() {}
149
150 exact::<NamedActual, NamedExpected>();
151 }
152
153 #[test]
154 fn lease_and_presence_products_keep_both_wrapper_orders() {
155 type Lease = crate::LeaseSends<
156 Vec<behavior::Delivery<SharedProtocol>>,
157 behavior::InterpreterRequests<crate::ScheduleAfter>,
158 >;
159 type Presence = crate::PresenceSends<
160 Vec<behavior::Delivery<ExternalProtocol>>,
161 behavior::InterpreterRequests<crate::ScheduleAfter>,
162 >;
163 type PresenceFirst =
164 <behavior::SendLayer<Lease, Presence> as LogicalDeliveryProtocols>::Protocols;
165 type LeaseFirst =
166 <behavior::SendLayer<Presence, Lease> as LogicalDeliveryProtocols>::Protocols;
167 type PresenceFirstExpected =
168 BirthProtocol<ExternalProtocol, BirthProtocol<SharedProtocol, NoBirthProtocols>>;
169 type LeaseFirstExpected =
170 BirthProtocol<SharedProtocol, BirthProtocol<ExternalProtocol, NoBirthProtocols>>;
171
172 trait Same<T> {}
173 impl<T> Same<T> for T {}
174 fn exact<T: Same<Expected>, Expected>() {}
175
176 exact::<PresenceFirst, PresenceFirstExpected>();
177 exact::<LeaseFirst, LeaseFirstExpected>();
178 }
179
180 #[test]
181 fn wrapper_projection_preserves_root_and_transitive_logical_occurrences() {
182 type Wrapped = crate::StopOnShutdown<Root>;
183 type Actual = <Wrapped as behavior::LogicalHostRequirements>::LogicalHosts;
184 type Expected = BirthProtocol<ExternalProtocol, NoBirthProtocols>;
185
186 trait Same<T> {}
187 impl<T> Same<T> for T {}
188 fn exact<T: Same<Expected>>() {}
189
190 exact::<Actual>();
191 }
192}