|
@@ -1,8 +1,8 @@
|
|
|
-use std::collections::HashSet;
|
|
|
+use std::collections::{HashMap, HashSet};
|
|
|
|
|
|
use proc_macro2::{Ident, Span};
|
|
|
|
|
|
-use btrun::{Activate, End};
|
|
|
+use btrun::End;
|
|
|
|
|
|
use crate::{
|
|
|
error::MaybeErr,
|
|
@@ -12,13 +12,61 @@ use crate::{
|
|
|
|
|
|
impl Protocol {
|
|
|
pub(crate) fn validate(&self) -> syn::Result<()> {
|
|
|
- self.all_states_declared_and_used()
|
|
|
- .combine(self.match_receivers_and_senders())
|
|
|
- .combine(self.no_undeliverable_msgs())
|
|
|
- .combine(self.valid_replies())
|
|
|
- .combine(self.msg_sent_or_received())
|
|
|
+ let validator = ProtocolValidator::new(self);
|
|
|
+ validator
|
|
|
+ .all_states_declared_and_used()
|
|
|
+ .combine(validator.receivers_and_senders_matched())
|
|
|
+ .combine(validator.no_undeliverable_msgs())
|
|
|
+ .combine(validator.replies_expected())
|
|
|
+ .combine(validator.msg_sent_or_received())
|
|
|
+ .combine(validator.clients_only_receive_replies())
|
|
|
.into()
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+struct ProtocolValidator<'a> {
|
|
|
+ protocol: &'a Protocol,
|
|
|
+ actors_by_states: HashMap<&'a Ident, &'a Ident>,
|
|
|
+ client_actors: HashSet<&'a Ident>,
|
|
|
+}
|
|
|
+
|
|
|
+impl<'a> ProtocolValidator<'a> {
|
|
|
+ fn new(protocol: &'a Protocol) -> Self {
|
|
|
+ let mut actors_by_states: HashMap<&Ident, &Ident> = HashMap::new();
|
|
|
+ for actor_def in protocol.actor_defs.iter() {
|
|
|
+ for state in actor_def.states.as_ref().iter() {
|
|
|
+ actors_by_states.insert(state, &actor_def.actor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let client_actors: HashSet<&Ident> = protocol
|
|
|
+ .transitions
|
|
|
+ .iter()
|
|
|
+ .filter(|transition| transition.in_msg().is_none())
|
|
|
+ .map(|transition| actors_by_states.get(&transition.in_state.state_trait))
|
|
|
+ .filter(|option| option.is_some())
|
|
|
+ .map(|option| *option.unwrap())
|
|
|
+ .collect();
|
|
|
+ Self {
|
|
|
+ protocol,
|
|
|
+ actors_by_states,
|
|
|
+ client_actors,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns the [Ident] for the actor that the given state is a part of.
|
|
|
+ fn actor(&self, state: &Ident) -> Option<&Ident> {
|
|
|
+ self.actors_by_states.get(state).copied()
|
|
|
+ }
|
|
|
+
|
|
|
+ fn is_client(&self, actor: &Ident) -> bool {
|
|
|
+ self.client_actors.contains(actor)
|
|
|
+ }
|
|
|
+
|
|
|
+ fn is_client_state(&self, state: &State) -> bool {
|
|
|
+ self.actor(&state.state_trait)
|
|
|
+ .map(|actor| self.is_client(actor))
|
|
|
+ .unwrap_or(false)
|
|
|
+ }
|
|
|
|
|
|
const UNDECLARED_STATE_ERR: &str = "State was not declared.";
|
|
|
const UNUSED_STATE_ERR: &str = "State was declared but never used.";
|
|
@@ -26,15 +74,15 @@ impl Protocol {
|
|
|
/// Verifies that every state which is used has been declared, except for the End state.
|
|
|
fn all_states_declared_and_used(&self) -> MaybeErr {
|
|
|
let end = Ident::new(End::ident(), Span::call_site());
|
|
|
- let declared: HashSet<&Ident> = self
|
|
|
- .states_def
|
|
|
- .states
|
|
|
- .as_ref()
|
|
|
- .iter()
|
|
|
- .chain([&end].into_iter())
|
|
|
- .collect();
|
|
|
+ let mut declared: HashSet<&Ident> = HashSet::new();
|
|
|
+ declared.insert(&end);
|
|
|
+ for actor_def in self.protocol.actor_defs.iter() {
|
|
|
+ for state in actor_def.states.as_ref().iter() {
|
|
|
+ declared.insert(state);
|
|
|
+ }
|
|
|
+ }
|
|
|
let mut used: HashSet<&Ident> = HashSet::with_capacity(declared.len());
|
|
|
- for transition in self.transitions.iter() {
|
|
|
+ for transition in self.protocol.transitions.iter() {
|
|
|
let in_state = &transition.in_state;
|
|
|
used.insert(&in_state.state_trait);
|
|
|
used.extend(in_state.owned_states.as_ref().iter());
|
|
@@ -46,7 +94,7 @@ impl Protocol {
|
|
|
used.extend(out_states.owned_states.as_ref().iter());
|
|
|
}
|
|
|
// We don't have to check the states referred to in out_msgs because the
|
|
|
- // match_receivers_and_senders method ensures that each of these exists in a receiver
|
|
|
+ // receivers_and_senders_matched method ensures that each of these exists in a receiver
|
|
|
// position.
|
|
|
}
|
|
|
let undeclared: MaybeErr = used
|
|
@@ -65,19 +113,13 @@ impl Protocol {
|
|
|
const UNMATCHED_RECEIVER_ERR: &str = "No sender found for message type.";
|
|
|
|
|
|
/// Ensures that the recipient state for every sent message has a receiving transition
|
|
|
- /// defined, and every receiver has a sender (except for the Activate message which is sent
|
|
|
- /// by the runtime).
|
|
|
- fn match_receivers_and_senders(&self) -> MaybeErr {
|
|
|
+ /// defined, and every receiver has a sender.
|
|
|
+ fn receivers_and_senders_matched(&self) -> MaybeErr {
|
|
|
let mut senders: HashSet<(&State, &Message)> = HashSet::new();
|
|
|
let mut receivers: HashSet<(&State, &Message)> = HashSet::new();
|
|
|
- for transition in self.transitions.iter() {
|
|
|
+ for transition in self.protocol.transitions.iter() {
|
|
|
if let Some(msg) = transition.in_msg() {
|
|
|
receivers.insert((&transition.in_state, msg));
|
|
|
- if msg.msg_type == Activate::ident() {
|
|
|
- // The Activate message is sent by the run time, so a sender is created to
|
|
|
- // represent it.
|
|
|
- senders.insert((&transition.in_state, msg));
|
|
|
- }
|
|
|
}
|
|
|
for dest in transition.out_msgs.as_ref().iter() {
|
|
|
let dest_state = match &dest.state {
|
|
@@ -106,7 +148,7 @@ impl Protocol {
|
|
|
/// reply.
|
|
|
fn no_undeliverable_msgs(&self) -> MaybeErr {
|
|
|
let mut err = MaybeErr::none();
|
|
|
- for transition in self.transitions.iter() {
|
|
|
+ for transition in self.protocol.transitions.iter() {
|
|
|
let mut allowed_states: Option<HashSet<&Ident>> = None;
|
|
|
for dest in transition.out_msgs.as_ref().iter() {
|
|
|
if dest.msg.is_reply() {
|
|
@@ -145,10 +187,10 @@ impl Protocol {
|
|
|
const MULTIPLE_REPLIES_ERR: &str =
|
|
|
"Only a single reply can be sent in response to any message.";
|
|
|
|
|
|
- /// Verifies that replies are only sent in response to messages.
|
|
|
- fn valid_replies(&self) -> MaybeErr {
|
|
|
+ /// Verifies that exactly one reply is sent in response to a previously sent message.
|
|
|
+ fn replies_expected(&self) -> MaybeErr {
|
|
|
let mut err = MaybeErr::none();
|
|
|
- for transition in self.transitions.iter() {
|
|
|
+ for transition in self.protocol.transitions.iter() {
|
|
|
let replies: Vec<_> = transition
|
|
|
.out_msgs
|
|
|
.as_ref()
|
|
@@ -189,7 +231,8 @@ impl Protocol {
|
|
|
/// this is that if no message is sent or received, then the state transition is unobserved by
|
|
|
/// other actors, and so should not be in a protocol.
|
|
|
fn msg_sent_or_received(&self) -> MaybeErr {
|
|
|
- self.transitions
|
|
|
+ self.protocol
|
|
|
+ .transitions
|
|
|
.iter()
|
|
|
.filter(|transition| {
|
|
|
transition.in_msg().is_none() && transition.out_msgs.as_ref().is_empty()
|
|
@@ -197,6 +240,29 @@ impl Protocol {
|
|
|
.map(|transition| syn::Error::new(transition.span(), Self::NO_MSG_SENT_OR_RECEIVED_ERR))
|
|
|
.collect()
|
|
|
}
|
|
|
+
|
|
|
+ const CLIENT_RECEIVED_NON_REPLY_ERR: &str =
|
|
|
+ "A client actor cannot receive a message which is not a reply.";
|
|
|
+
|
|
|
+ /// A client is any actor with a state that sends at least one message when not handling an
|
|
|
+ /// incoming message. Such actors are not allowed to receive any message which are not replies.
|
|
|
+ fn clients_only_receive_replies(&self) -> MaybeErr {
|
|
|
+ self.protocol
|
|
|
+ .transitions
|
|
|
+ .iter()
|
|
|
+ .filter(|transition| {
|
|
|
+ if let Some(msg) = transition.in_msg() {
|
|
|
+ if !msg.is_reply() {
|
|
|
+ return self.is_client_state(&transition.in_state);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ false
|
|
|
+ })
|
|
|
+ .map(|transition| {
|
|
|
+ syn::Error::new(transition.span(), Self::CLIENT_RECEIVED_NON_REPLY_ERR)
|
|
|
+ })
|
|
|
+ .collect()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#[cfg(test)]
|
|
@@ -224,19 +290,34 @@ mod tests {
|
|
|
const STATE_NAME: &str = "Init";
|
|
|
Protocol::new(
|
|
|
NameDef::new("Test"),
|
|
|
- ActorDef::new("actor", [STATE_NAME]),
|
|
|
- [Transition::new(
|
|
|
- State::new(STATE_NAME, []),
|
|
|
- Some(Message::new("Activate", false, [])),
|
|
|
- [State::new("End", [])],
|
|
|
- [],
|
|
|
- )],
|
|
|
+ [
|
|
|
+ ActorDef::new("server", [STATE_NAME]),
|
|
|
+ ActorDef::new("client", ["Client"]),
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ Transition::new(
|
|
|
+ State::new("Client", []),
|
|
|
+ None,
|
|
|
+ [State::new("End", [])],
|
|
|
+ [Dest::new(
|
|
|
+ DestinationState::Service(State::new(STATE_NAME, [])),
|
|
|
+ Message::new("Msg", false, []),
|
|
|
+ )],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new(STATE_NAME, []),
|
|
|
+ Some(Message::new("Msg", false, [])),
|
|
|
+ [State::new("End", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
)
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_ok() {
|
|
|
- let result = min_protocol().all_states_declared_and_used();
|
|
|
+ let protocol = min_protocol();
|
|
|
+ let result = ProtocolValidator::new(&protocol).all_states_declared_and_used();
|
|
|
|
|
|
assert_ok!(result);
|
|
|
}
|
|
@@ -244,9 +325,9 @@ mod tests {
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_end_not_used_ok() {
|
|
|
const STATE_NAME: &str = "Init";
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Test"),
|
|
|
- ActorDef::new("actor", [STATE_NAME]),
|
|
|
+ [ActorDef::new("actor", [STATE_NAME])],
|
|
|
[Transition::new(
|
|
|
State::new(STATE_NAME, []),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -254,6 +335,7 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
@@ -262,9 +344,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_undeclared_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeclared"),
|
|
|
- ActorDef::new("actor", ["Init"]),
|
|
|
+ [ActorDef::new("actor", ["Init"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -272,17 +354,18 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNDECLARED_STATE_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_undeclared_out_state_owned_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeclared"),
|
|
|
- ActorDef::new("actor", ["Init", "Next"]),
|
|
|
+ [ActorDef::new("actor", ["Init", "Next"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -290,17 +373,18 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNDECLARED_STATE_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_undeclared_in_state_owned_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeclared"),
|
|
|
- ActorDef::new("actor", ["Init", "Next"]),
|
|
|
+ [ActorDef::new("actor", ["Init", "Next"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", ["Undeclared"]),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -308,17 +392,18 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNDECLARED_STATE_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn all_states_declared_and_used_unused_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Unused"),
|
|
|
- ActorDef::new("actor", ["Init", "Extra"]),
|
|
|
+ [ActorDef::new("actor", ["Init", "Extra"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -326,74 +411,48 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNUSED_STATE_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNUSED_STATE_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn match_receivers_and_senders_ok() {
|
|
|
- let result = min_protocol().match_receivers_and_senders();
|
|
|
+ fn receivers_and_senders_matched_ok() {
|
|
|
+ let protocol = min_protocol();
|
|
|
+ let result = ProtocolValidator::new(&protocol).receivers_and_senders_matched();
|
|
|
|
|
|
assert_ok!(result);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn match_receivers_and_senders_send_activate_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ fn receivers_and_senders_matched_unmatched_sender_err() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Unbalanced"),
|
|
|
- ActorDef::new("actor", ["First", "Second"]),
|
|
|
- [
|
|
|
- Transition::new(
|
|
|
- State::new("First", []),
|
|
|
- Some(Message::new("Activate", false, [])),
|
|
|
- [State::new("First", [])],
|
|
|
- [Dest::new(
|
|
|
- DestinationState::Individual(State::new("Second", [])),
|
|
|
- Message::new("Activate", false, []),
|
|
|
- )],
|
|
|
- ),
|
|
|
- Transition::new(
|
|
|
- State::new("Second", []),
|
|
|
- Some(Message::new("Activate", false, [])),
|
|
|
- [State::new("Second", [])],
|
|
|
- [],
|
|
|
- ),
|
|
|
- ],
|
|
|
- );
|
|
|
-
|
|
|
- let result = input.match_receivers_and_senders();
|
|
|
-
|
|
|
- assert_ok!(result);
|
|
|
- }
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn match_receivers_and_senders_unmatched_sender_err() {
|
|
|
- let input = Protocol::new(
|
|
|
- NameDef::new("Unbalanced"),
|
|
|
- ActorDef::new("actor", ["Init", "Other"]),
|
|
|
+ [ActorDef::new("actor", ["Init"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
- Some(Message::new("Activate", false, [])),
|
|
|
+ None,
|
|
|
[State::new("Init", [])],
|
|
|
[Dest::new(
|
|
|
- DestinationState::Individual(State::new("Other", [])),
|
|
|
- Message::new("Activate", false, []),
|
|
|
+ DestinationState::Service(State::new("Init", [])),
|
|
|
+ Message::new("Msg", false, []),
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
- let result = input.match_receivers_and_senders();
|
|
|
+ let result = input.receivers_and_senders_matched();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNMATCHED_SENDER_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNMATCHED_SENDER_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn match_receivers_and_senders_unmatched_receiver_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ fn receivers_and_senders_matched_unmatched_receiver_err() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Unbalanced"),
|
|
|
- ActorDef::new("actor", ["Init"]),
|
|
|
+ [ActorDef::new("actor", ["Init"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
Some(Message::new("NotExists", false, [])),
|
|
@@ -401,24 +460,26 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
- let result = input.match_receivers_and_senders();
|
|
|
+ let result = input.receivers_and_senders_matched();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNMATCHED_RECEIVER_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNMATCHED_RECEIVER_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn no_undeliverable_msgs_ok() {
|
|
|
- let result = min_protocol().no_undeliverable_msgs();
|
|
|
+ let protocol = min_protocol();
|
|
|
+ let result = ProtocolValidator::new(&protocol).no_undeliverable_msgs();
|
|
|
|
|
|
assert_ok!(result);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn no_undeliverable_msgs_reply_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeliverable"),
|
|
|
- ActorDef::new("actor", ["Listening", "Client"]),
|
|
|
+ [ActorDef::new("actor", ["Listening", "Client"])],
|
|
|
[Transition::new(
|
|
|
State::new("Listening", []),
|
|
|
Some(Message::new("Msg", false, [])),
|
|
@@ -429,6 +490,7 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
@@ -437,9 +499,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn no_undeliverable_msgs_service_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeliverable"),
|
|
|
- ActorDef::new("actor", ["Client", "Server"]),
|
|
|
+ [ActorDef::new("actor", ["Client", "Server"])],
|
|
|
[Transition::new(
|
|
|
State::new("Client", []),
|
|
|
None,
|
|
@@ -450,6 +512,7 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
@@ -458,9 +521,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn no_undeliverable_msgs_owned_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeliverable"),
|
|
|
- ActorDef::new("actor", ["FileClient", "FileHandle"]),
|
|
|
+ [ActorDef::new("actor", ["FileClient", "FileHandle"])],
|
|
|
[Transition::new(
|
|
|
State::new("FileClient", ["FileHandle"]),
|
|
|
None,
|
|
@@ -471,6 +534,7 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
@@ -479,9 +543,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn no_undeliverable_msgs_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Undeliverable"),
|
|
|
- ActorDef::new("actor", ["Client", "Server"]),
|
|
|
+ [ActorDef::new("actor", ["Client", "Server"])],
|
|
|
[Transition::new(
|
|
|
State::new("Client", []),
|
|
|
None,
|
|
@@ -492,17 +556,18 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_err!(result, Protocol::UNDELIVERABLE_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::UNDELIVERABLE_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn valid_replies_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ fn replies_expected_ok() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("ValidReplies"),
|
|
|
- ActorDef::new("actor", ["Client", "Server"]),
|
|
|
+ [ActorDef::new("actor", ["Client", "Server"])],
|
|
|
[Transition::new(
|
|
|
State::new("Server", []),
|
|
|
Some(Message::new("Msg", false, [])),
|
|
@@ -513,17 +578,18 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
- let result = input.valid_replies();
|
|
|
+ let result = input.replies_expected();
|
|
|
|
|
|
assert_ok!(result);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn valid_replies_invalid_reply_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ fn replies_expected_invalid_reply_err() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("ValidReplies"),
|
|
|
- ActorDef::new("actor", ["Client", "Server"]),
|
|
|
+ [ActorDef::new("actor", ["Client", "Server"])],
|
|
|
[Transition::new(
|
|
|
State::new("Client", []),
|
|
|
None,
|
|
@@ -534,17 +600,18 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
- let result = input.valid_replies();
|
|
|
+ let result = input.replies_expected();
|
|
|
|
|
|
- assert_err!(result, Protocol::INVALID_REPLY_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::INVALID_REPLY_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
- fn valid_replies_multiple_replies_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ fn replies_expected_multiple_replies_err() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("ValidReplies"),
|
|
|
- ActorDef::new("actor", ["Client", "OtherClient", "Server"]),
|
|
|
+ [ActorDef::new("actor", ["Client", "OtherClient", "Server"])],
|
|
|
[Transition::new(
|
|
|
State::new("Server", []),
|
|
|
Some(Message::new("Msg", false, [])),
|
|
@@ -561,17 +628,18 @@ mod tests {
|
|
|
],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
- let result = input.valid_replies();
|
|
|
+ let result = input.replies_expected();
|
|
|
|
|
|
- assert_err!(result, Protocol::MULTIPLE_REPLIES_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::MULTIPLE_REPLIES_ERR);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn msg_sent_or_received_msg_received_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Test"),
|
|
|
- ActorDef::new("actor", ["Init"]),
|
|
|
+ [ActorDef::new("actor", ["Init"])],
|
|
|
[Transition::new(
|
|
|
State::new("Init", []),
|
|
|
Some(Message::new("Activate", false, [])),
|
|
@@ -579,6 +647,7 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.msg_sent_or_received();
|
|
|
|
|
@@ -587,9 +656,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn msg_sent_or_received_msg_sent_ok() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Test"),
|
|
|
- ActorDef::new("actor", ["First", "Second"]),
|
|
|
+ [ActorDef::new("actor", ["First", "Second"])],
|
|
|
[Transition::new(
|
|
|
State::new("First", []),
|
|
|
None,
|
|
@@ -600,6 +669,7 @@ mod tests {
|
|
|
)],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.msg_sent_or_received();
|
|
|
|
|
@@ -608,9 +678,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn msg_sent_or_received_neither_err() {
|
|
|
- let input = Protocol::new(
|
|
|
+ let protocol = Protocol::new(
|
|
|
NameDef::new("Test"),
|
|
|
- ActorDef::new("actor", ["First"]),
|
|
|
+ [ActorDef::new("actor", ["First"])],
|
|
|
[Transition::new(
|
|
|
State::new("First", []),
|
|
|
None,
|
|
@@ -618,9 +688,112 @@ mod tests {
|
|
|
[],
|
|
|
)],
|
|
|
);
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
let result = input.msg_sent_or_received();
|
|
|
|
|
|
- assert_err!(result, Protocol::NO_MSG_SENT_OR_RECEIVED_ERR);
|
|
|
+ assert_err!(result, ProtocolValidator::NO_MSG_SENT_OR_RECEIVED_ERR);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn clients_only_receive_replies_ok() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
+ NameDef::new("ClientReplies"),
|
|
|
+ [
|
|
|
+ ActorDef::new("client", ["Client", "Waiting"]),
|
|
|
+ ActorDef::new("server", ["Init", "Listening"]),
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ Transition::new(
|
|
|
+ State::new("Init", []),
|
|
|
+ Some(Message::new("Activate", false, [])),
|
|
|
+ [State::new("Listening", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Client", []),
|
|
|
+ None,
|
|
|
+ [State::new("Waiting", [])],
|
|
|
+ [Dest::new(
|
|
|
+ DestinationState::Service(State::new("Listening", [])),
|
|
|
+ Message::new("Ping", false, []),
|
|
|
+ )],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Listening", []),
|
|
|
+ Some(Message::new("Ping", false, [])),
|
|
|
+ [State::new("Listening", [])],
|
|
|
+ [Dest::new(
|
|
|
+ DestinationState::Individual(State::new("Waiting", [])),
|
|
|
+ Message::new("Ping", true, []),
|
|
|
+ )],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Waiting", []),
|
|
|
+ Some(Message::new("Ping", true, [])),
|
|
|
+ [State::new("Client", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
+
|
|
|
+ let result = input.clients_only_receive_replies();
|
|
|
+
|
|
|
+ assert_ok!(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn clients_only_receive_replies_err() {
|
|
|
+ let protocol = Protocol::new(
|
|
|
+ NameDef::new("ClientReplies"),
|
|
|
+ [
|
|
|
+ ActorDef::new("client", ["Client", "Waiting"]),
|
|
|
+ ActorDef::new("server", ["Init", "Listening"]),
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ Transition::new(
|
|
|
+ State::new("Init", []),
|
|
|
+ Some(Message::new("Activate", false, [])),
|
|
|
+ [State::new("Listening", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Client", []),
|
|
|
+ None,
|
|
|
+ [State::new("Waiting", [])],
|
|
|
+ [Dest::new(
|
|
|
+ DestinationState::Service(State::new("Listening", [])),
|
|
|
+ Message::new("Ping", false, []),
|
|
|
+ )],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Listening", []),
|
|
|
+ Some(Message::new("Ping", false, [])),
|
|
|
+ [State::new("Listening", [])],
|
|
|
+ [Dest::new(
|
|
|
+ DestinationState::Individual(State::new("Waiting", [])),
|
|
|
+ Message::new("Ping", true, []),
|
|
|
+ )],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Waiting", []),
|
|
|
+ Some(Message::new("Ping", true, [])),
|
|
|
+ [State::new("Client", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ Transition::new(
|
|
|
+ State::new("Client", []),
|
|
|
+ Some(Message::new("Activate", false, [])),
|
|
|
+ [State::new("Client", [])],
|
|
|
+ [],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ let input = ProtocolValidator::new(&protocol);
|
|
|
+
|
|
|
+ let result = input.clients_only_receive_replies();
|
|
|
+
|
|
|
+ assert_err!(result, ProtocolValidator::CLIENT_RECEIVED_NON_REPLY_ERR);
|
|
|
}
|
|
|
}
|