|
@@ -1,97 +1,65 @@
|
|
-use std::collections::{HashMap, HashSet};
|
|
|
|
|
|
+use std::collections::HashSet;
|
|
|
|
|
|
use proc_macro2::{Ident, Span};
|
|
use proc_macro2::{Ident, Span};
|
|
|
|
|
|
use btrun::End;
|
|
use btrun::End;
|
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
- error::MaybeErr,
|
|
|
|
|
|
+ error::{self, MaybeErr},
|
|
|
|
+ model::ProtocolModel,
|
|
parsing::{DestinationState, GetSpan, Message, State},
|
|
parsing::{DestinationState, GetSpan, Message, State},
|
|
- Protocol,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-impl Protocol {
|
|
|
|
|
|
+impl ProtocolModel {
|
|
|
|
+ #[allow(dead_code)]
|
|
pub(crate) fn validate(&self) -> syn::Result<()> {
|
|
pub(crate) fn validate(&self) -> syn::Result<()> {
|
|
- 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())
|
|
|
|
|
|
+ self.all_states_declared_and_used()
|
|
|
|
+ .combine(self.receivers_and_senders_matched())
|
|
|
|
+ .combine(self.no_undeliverable_msgs())
|
|
|
|
+ .combine(self.replies_expected())
|
|
|
|
+ .combine(self.clients_only_receive_replies())
|
|
.into()
|
|
.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.";
|
|
|
|
-
|
|
|
|
- /// Verifies that every state which is used has been declared, except for the End state.
|
|
|
|
|
|
+ /// Verifies that every state which is declared is actually used.
|
|
fn all_states_declared_and_used(&self) -> MaybeErr {
|
|
fn all_states_declared_and_used(&self) -> MaybeErr {
|
|
let end = Ident::new(End::ident(), Span::call_site());
|
|
let end = Ident::new(End::ident(), Span::call_site());
|
|
let mut declared: HashSet<&Ident> = HashSet::new();
|
|
let mut declared: HashSet<&Ident> = HashSet::new();
|
|
declared.insert(&end);
|
|
declared.insert(&end);
|
|
- for actor_def in self.protocol.actor_defs.iter() {
|
|
|
|
|
|
+ for actor_def in self.def().actor_defs.iter() {
|
|
for state in actor_def.states.as_ref().iter() {
|
|
for state in actor_def.states.as_ref().iter() {
|
|
declared.insert(state);
|
|
declared.insert(state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let mut used: HashSet<&Ident> = HashSet::with_capacity(declared.len());
|
|
let mut used: HashSet<&Ident> = HashSet::with_capacity(declared.len());
|
|
- for transition in self.protocol.transitions.iter() {
|
|
|
|
|
|
+ for transition in self.def().transitions.iter() {
|
|
let in_state = &transition.in_state;
|
|
let in_state = &transition.in_state;
|
|
used.insert(&in_state.state_trait);
|
|
used.insert(&in_state.state_trait);
|
|
- used.extend(in_state.owned_states.as_ref().iter());
|
|
|
|
|
|
+ used.extend(
|
|
|
|
+ in_state
|
|
|
|
+ .owned_states
|
|
|
|
+ .as_ref()
|
|
|
|
+ .iter()
|
|
|
|
+ .map(|ident| ident.as_ref()),
|
|
|
|
+ );
|
|
if let Some(in_msg) = transition.in_msg() {
|
|
if let Some(in_msg) = transition.in_msg() {
|
|
- used.extend(in_msg.owned_states.as_ref().iter());
|
|
|
|
|
|
+ used.extend(
|
|
|
|
+ in_msg
|
|
|
|
+ .owned_states
|
|
|
|
+ .as_ref()
|
|
|
|
+ .iter()
|
|
|
|
+ .map(|ident| ident.as_ref()),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
for out_states in transition.out_states.as_ref().iter() {
|
|
for out_states in transition.out_states.as_ref().iter() {
|
|
used.insert(&out_states.state_trait);
|
|
used.insert(&out_states.state_trait);
|
|
- used.extend(out_states.owned_states.as_ref().iter());
|
|
|
|
|
|
+ used.extend(
|
|
|
|
+ out_states
|
|
|
|
+ .owned_states
|
|
|
|
+ .as_ref()
|
|
|
|
+ .iter()
|
|
|
|
+ .map(|ident| ident.as_ref()),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
// We don't have to check the states referred to in out_msgs because the
|
|
// We don't have to check the states referred to in out_msgs because the
|
|
// receivers_and_senders_matched method ensures that each of these exists in a receiver
|
|
// receivers_and_senders_matched method ensures that each of these exists in a receiver
|
|
@@ -99,25 +67,23 @@ impl<'a> ProtocolValidator<'a> {
|
|
}
|
|
}
|
|
let undeclared: MaybeErr = used
|
|
let undeclared: MaybeErr = used
|
|
.difference(&declared)
|
|
.difference(&declared)
|
|
- .map(|ident| syn::Error::new(ident.span(), Self::UNDECLARED_STATE_ERR))
|
|
|
|
|
|
+ .map(|ident| syn::Error::new(ident.span(), error::msgs::UNDECLARED_STATE_ERR))
|
|
.collect();
|
|
.collect();
|
|
let unused: MaybeErr = declared
|
|
let unused: MaybeErr = declared
|
|
.difference(&used)
|
|
.difference(&used)
|
|
.filter(|ident| **ident != End::ident())
|
|
.filter(|ident| **ident != End::ident())
|
|
- .map(|ident| syn::Error::new(ident.span(), Self::UNUSED_STATE_ERR))
|
|
|
|
|
|
+ .map(|ident| syn::Error::new(ident.span(), error::msgs::UNUSED_STATE_ERR))
|
|
.collect();
|
|
.collect();
|
|
undeclared.combine(unused)
|
|
undeclared.combine(unused)
|
|
}
|
|
}
|
|
|
|
|
|
- const UNMATCHED_SENDER_ERR: &str = "No receiver found for message type.";
|
|
|
|
- const UNMATCHED_RECEIVER_ERR: &str = "No sender found for message type.";
|
|
|
|
-
|
|
|
|
/// Ensures that the recipient state for every sent message has a receiving transition
|
|
/// Ensures that the recipient state for every sent message has a receiving transition
|
|
- /// defined, and every receiver has a sender.
|
|
|
|
|
|
+ /// defined, and every receiver has a sender. Note that each message isn't required to have a
|
|
|
|
+ /// unique sender or a unique receiver, just that at least one of each much be defined.
|
|
fn receivers_and_senders_matched(&self) -> MaybeErr {
|
|
fn receivers_and_senders_matched(&self) -> MaybeErr {
|
|
let mut senders: HashSet<(&State, &Message)> = HashSet::new();
|
|
let mut senders: HashSet<(&State, &Message)> = HashSet::new();
|
|
let mut receivers: HashSet<(&State, &Message)> = HashSet::new();
|
|
let mut receivers: HashSet<(&State, &Message)> = HashSet::new();
|
|
- for transition in self.protocol.transitions.iter() {
|
|
|
|
|
|
+ for transition in self.def().transitions.iter() {
|
|
if let Some(msg) = transition.in_msg() {
|
|
if let Some(msg) = transition.in_msg() {
|
|
receivers.insert((&transition.in_state, msg));
|
|
receivers.insert((&transition.in_state, msg));
|
|
}
|
|
}
|
|
@@ -131,24 +97,23 @@ impl<'a> ProtocolValidator<'a> {
|
|
}
|
|
}
|
|
let extra_senders: MaybeErr = senders
|
|
let extra_senders: MaybeErr = senders
|
|
.difference(&receivers)
|
|
.difference(&receivers)
|
|
- .map(|pair| syn::Error::new(pair.1.msg_type.span(), Self::UNMATCHED_SENDER_ERR))
|
|
|
|
|
|
+ .map(|pair| syn::Error::new(pair.1.msg_type.span(), error::msgs::UNMATCHED_SENDER_ERR))
|
|
.collect();
|
|
.collect();
|
|
let extra_receivers: MaybeErr = receivers
|
|
let extra_receivers: MaybeErr = receivers
|
|
.difference(&senders)
|
|
.difference(&senders)
|
|
- .map(|pair| syn::Error::new(pair.1.msg_type.span(), Self::UNMATCHED_RECEIVER_ERR))
|
|
|
|
|
|
+ .map(|pair| {
|
|
|
|
+ syn::Error::new(pair.1.msg_type.span(), error::msgs::UNMATCHED_RECEIVER_ERR)
|
|
|
|
+ })
|
|
.collect();
|
|
.collect();
|
|
extra_senders.combine(extra_receivers)
|
|
extra_senders.combine(extra_receivers)
|
|
}
|
|
}
|
|
|
|
|
|
- const UNDELIVERABLE_ERR: &str =
|
|
|
|
- "Receiver must either be a service, an owned state, or an out state, or the message must be a reply.";
|
|
|
|
-
|
|
|
|
/// Checks that messages are only sent to destinations which are either services, states
|
|
/// Checks that messages are only sent to destinations which are either services, states
|
|
/// which are owned by the sender, listed in the output states, or that the message is a
|
|
/// which are owned by the sender, listed in the output states, or that the message is a
|
|
/// reply.
|
|
/// reply.
|
|
fn no_undeliverable_msgs(&self) -> MaybeErr {
|
|
fn no_undeliverable_msgs(&self) -> MaybeErr {
|
|
let mut err = MaybeErr::none();
|
|
let mut err = MaybeErr::none();
|
|
- for transition in self.protocol.transitions.iter() {
|
|
|
|
|
|
+ for transition in self.def().transitions.iter() {
|
|
let mut allowed_states: Option<HashSet<&Ident>> = None;
|
|
let mut allowed_states: Option<HashSet<&Ident>> = None;
|
|
for dest in transition.out_msgs.as_ref().iter() {
|
|
for dest in transition.out_msgs.as_ref().iter() {
|
|
if dest.msg.is_reply() {
|
|
if dest.msg.is_reply() {
|
|
@@ -162,15 +127,22 @@ impl<'a> ProtocolValidator<'a> {
|
|
.out_states
|
|
.out_states
|
|
.as_ref()
|
|
.as_ref()
|
|
.iter()
|
|
.iter()
|
|
- .map(|state| &state.state_trait)
|
|
|
|
- .chain(transition.in_state.owned_states.as_ref().iter())
|
|
|
|
|
|
+ .map(|state| state.state_trait.as_ref())
|
|
|
|
+ .chain(
|
|
|
|
+ transition
|
|
|
|
+ .in_state
|
|
|
|
+ .owned_states
|
|
|
|
+ .as_ref()
|
|
|
|
+ .iter()
|
|
|
|
+ .map(|ident| ident.as_ref()),
|
|
|
|
+ )
|
|
.collect()
|
|
.collect()
|
|
});
|
|
});
|
|
- if !allowed.contains(&dest_state.state_trait) {
|
|
|
|
|
|
+ if !allowed.contains(dest_state.state_trait.as_ref()) {
|
|
err = err.combine(
|
|
err = err.combine(
|
|
syn::Error::new(
|
|
syn::Error::new(
|
|
dest_state.state_trait.span(),
|
|
dest_state.state_trait.span(),
|
|
- Self::UNDELIVERABLE_ERR,
|
|
|
|
|
|
+ error::msgs::UNDELIVERABLE_ERR,
|
|
)
|
|
)
|
|
.into(),
|
|
.into(),
|
|
);
|
|
);
|
|
@@ -182,15 +154,10 @@ impl<'a> ProtocolValidator<'a> {
|
|
err
|
|
err
|
|
}
|
|
}
|
|
|
|
|
|
- const INVALID_REPLY_ERR: &str =
|
|
|
|
- "Replies can only be used in transitions which handle messages.";
|
|
|
|
- const MULTIPLE_REPLIES_ERR: &str =
|
|
|
|
- "Only a single reply can be sent in response to any message.";
|
|
|
|
-
|
|
|
|
/// Verifies that exactly one reply is sent in response to a previously sent message.
|
|
/// Verifies that exactly one reply is sent in response to a previously sent message.
|
|
fn replies_expected(&self) -> MaybeErr {
|
|
fn replies_expected(&self) -> MaybeErr {
|
|
let mut err = MaybeErr::none();
|
|
let mut err = MaybeErr::none();
|
|
- for transition in self.protocol.transitions.iter() {
|
|
|
|
|
|
+ for transition in self.def().transitions.iter() {
|
|
let replies: Vec<_> = transition
|
|
let replies: Vec<_> = transition
|
|
.out_msgs
|
|
.out_msgs
|
|
.as_ref()
|
|
.as_ref()
|
|
@@ -206,7 +173,10 @@ impl<'a> ProtocolValidator<'a> {
|
|
replies
|
|
replies
|
|
.iter()
|
|
.iter()
|
|
.map(|reply| {
|
|
.map(|reply| {
|
|
- syn::Error::new(reply.msg_type.span(), Self::MULTIPLE_REPLIES_ERR)
|
|
|
|
|
|
+ syn::Error::new(
|
|
|
|
+ reply.msg_type.span(),
|
|
|
|
+ error::msgs::MULTIPLE_REPLIES_ERR,
|
|
|
|
+ )
|
|
})
|
|
})
|
|
.collect(),
|
|
.collect(),
|
|
);
|
|
);
|
|
@@ -216,7 +186,7 @@ impl<'a> ProtocolValidator<'a> {
|
|
replies
|
|
replies
|
|
.iter()
|
|
.iter()
|
|
.map(|reply| {
|
|
.map(|reply| {
|
|
- syn::Error::new(reply.msg_type.span(), Self::INVALID_REPLY_ERR)
|
|
|
|
|
|
+ syn::Error::new(reply.msg_type.span(), error::msgs::INVALID_REPLY_ERR)
|
|
})
|
|
})
|
|
.collect(),
|
|
.collect(),
|
|
);
|
|
);
|
|
@@ -225,41 +195,30 @@ impl<'a> ProtocolValidator<'a> {
|
|
err
|
|
err
|
|
}
|
|
}
|
|
|
|
|
|
- const NO_MSG_SENT_OR_RECEIVED_ERR: &str = "A transition must send or receive a message.";
|
|
|
|
-
|
|
|
|
- /// Verifies that either a message is received, or sent by a transition. The rational behind
|
|
|
|
- /// 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.protocol
|
|
|
|
- .transitions
|
|
|
|
- .iter()
|
|
|
|
- .filter(|transition| {
|
|
|
|
- transition.in_msg().is_none() && transition.out_msgs.as_ref().is_empty()
|
|
|
|
- })
|
|
|
|
- .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
|
|
/// 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.
|
|
|
|
|
|
+ /// incoming message. Such actors are not allowed to receive any messages which are not replies.
|
|
fn clients_only_receive_replies(&self) -> MaybeErr {
|
|
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);
|
|
|
|
- }
|
|
|
|
|
|
+ self.actors()
|
|
|
|
+ .values()
|
|
|
|
+ .filter(|actor| actor.is_client())
|
|
|
|
+ .flat_map(|actor| {
|
|
|
|
+ actor
|
|
|
|
+ .states()
|
|
|
|
+ .values()
|
|
|
|
+ .flat_map(|state| state.methods().values())
|
|
|
|
+ })
|
|
|
|
+ .filter(|method| {
|
|
|
|
+ if let Some(msg) = method.def().in_msg() {
|
|
|
|
+ !msg.is_reply()
|
|
|
|
+ } else {
|
|
|
|
+ false
|
|
}
|
|
}
|
|
- false
|
|
|
|
})
|
|
})
|
|
.map(|transition| {
|
|
.map(|transition| {
|
|
- syn::Error::new(transition.span(), Self::CLIENT_RECEIVED_NON_REPLY_ERR)
|
|
|
|
|
|
+ syn::Error::new(
|
|
|
|
+ transition.span(),
|
|
|
|
+ error::msgs::CLIENT_RECEIVED_NON_REPLY_ERR,
|
|
|
|
+ )
|
|
})
|
|
})
|
|
.collect()
|
|
.collect()
|
|
}
|
|
}
|
|
@@ -268,64 +227,24 @@ impl<'a> ProtocolValidator<'a> {
|
|
#[cfg(test)]
|
|
#[cfg(test)]
|
|
mod tests {
|
|
mod tests {
|
|
use super::*;
|
|
use super::*;
|
|
- use crate::parsing::{ActorDef, Dest, NameDef, Transition};
|
|
|
|
-
|
|
|
|
- macro_rules! assert_ok {
|
|
|
|
- ($maybe_err:expr) => {
|
|
|
|
- let result: syn::Result<()> = $maybe_err.into();
|
|
|
|
- assert!(result.is_ok(), "{}", result.err().unwrap());
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- macro_rules! assert_err {
|
|
|
|
- ($maybe_err:expr, $expected_msg:expr) => {
|
|
|
|
- let result: syn::Result<()> = $maybe_err.into();
|
|
|
|
- assert!(result.is_err());
|
|
|
|
- assert_eq!($expected_msg, result.err().unwrap().to_string());
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Creates minimal [Protocol] value.
|
|
|
|
- fn min_protocol() -> Protocol {
|
|
|
|
- const STATE_NAME: &str = "Init";
|
|
|
|
- Protocol::new(
|
|
|
|
- NameDef::new("Test"),
|
|
|
|
- [
|
|
|
|
- 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", [])],
|
|
|
|
- [],
|
|
|
|
- ),
|
|
|
|
- ],
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
|
|
+ use crate::{
|
|
|
|
+ error::{assert_err, assert_ok},
|
|
|
|
+ parsing::{ActorDef, Dest, NameDef, Protocol, Transition},
|
|
|
|
+ };
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_ok() {
|
|
fn all_states_declared_and_used_ok() {
|
|
- let protocol = min_protocol();
|
|
|
|
- let result = ProtocolValidator::new(&protocol).all_states_declared_and_used();
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::minimal()).unwrap();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ let result = input.all_states_declared_and_used();
|
|
|
|
+
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_end_not_used_ok() {
|
|
fn all_states_declared_and_used_end_not_used_ok() {
|
|
const STATE_NAME: &str = "Init";
|
|
const STATE_NAME: &str = "Init";
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Test"),
|
|
NameDef::new("Test"),
|
|
[ActorDef::new("actor", [STATE_NAME])],
|
|
[ActorDef::new("actor", [STATE_NAME])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -334,17 +253,17 @@ mod tests {
|
|
[State::new(STATE_NAME, [])],
|
|
[State::new(STATE_NAME, [])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_undeclared_err() {
|
|
fn all_states_declared_and_used_undeclared_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeclared"),
|
|
NameDef::new("Undeclared"),
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -353,17 +272,17 @@ mod tests {
|
|
[State::new("Next", [])],
|
|
[State::new("Next", [])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNDECLARED_STATE_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_undeclared_out_state_owned_err() {
|
|
fn all_states_declared_and_used_undeclared_out_state_owned_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeclared"),
|
|
NameDef::new("Undeclared"),
|
|
[ActorDef::new("actor", ["Init", "Next"])],
|
|
[ActorDef::new("actor", ["Init", "Next"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -372,17 +291,17 @@ mod tests {
|
|
[State::new("Init", []), State::new("Next", ["Undeclared"])],
|
|
[State::new("Init", []), State::new("Next", ["Undeclared"])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNDECLARED_STATE_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_undeclared_in_state_owned_err() {
|
|
fn all_states_declared_and_used_undeclared_in_state_owned_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeclared"),
|
|
NameDef::new("Undeclared"),
|
|
[ActorDef::new("actor", ["Init", "Next"])],
|
|
[ActorDef::new("actor", ["Init", "Next"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -391,17 +310,17 @@ mod tests {
|
|
[State::new("Next", [])],
|
|
[State::new("Next", [])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNDECLARED_STATE_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNDECLARED_STATE_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn all_states_declared_and_used_unused_err() {
|
|
fn all_states_declared_and_used_unused_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Unused"),
|
|
NameDef::new("Unused"),
|
|
[ActorDef::new("actor", ["Init", "Extra"])],
|
|
[ActorDef::new("actor", ["Init", "Extra"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -410,25 +329,26 @@ mod tests {
|
|
[State::new("End", [])],
|
|
[State::new("End", [])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.all_states_declared_and_used();
|
|
let result = input.all_states_declared_and_used();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNUSED_STATE_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNUSED_STATE_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn receivers_and_senders_matched_ok() {
|
|
fn receivers_and_senders_matched_ok() {
|
|
- let protocol = min_protocol();
|
|
|
|
- let result = ProtocolValidator::new(&protocol).receivers_and_senders_matched();
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::minimal()).unwrap();
|
|
|
|
+
|
|
|
|
+ let result = input.receivers_and_senders_matched();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn receivers_and_senders_matched_unmatched_sender_err() {
|
|
fn receivers_and_senders_matched_unmatched_sender_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Unbalanced"),
|
|
NameDef::new("Unbalanced"),
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -440,17 +360,17 @@ mod tests {
|
|
Message::new("Msg", false, []),
|
|
Message::new("Msg", false, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.receivers_and_senders_matched();
|
|
let result = input.receivers_and_senders_matched();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNMATCHED_SENDER_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNMATCHED_SENDER_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn receivers_and_senders_matched_unmatched_receiver_err() {
|
|
fn receivers_and_senders_matched_unmatched_receiver_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Unbalanced"),
|
|
NameDef::new("Unbalanced"),
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[ActorDef::new("actor", ["Init"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -459,25 +379,26 @@ mod tests {
|
|
[State::new("Init", [])],
|
|
[State::new("Init", [])],
|
|
[],
|
|
[],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.receivers_and_senders_matched();
|
|
let result = input.receivers_and_senders_matched();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNMATCHED_RECEIVER_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNMATCHED_RECEIVER_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn no_undeliverable_msgs_ok() {
|
|
fn no_undeliverable_msgs_ok() {
|
|
- let protocol = min_protocol();
|
|
|
|
- let result = ProtocolValidator::new(&protocol).no_undeliverable_msgs();
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::minimal()).unwrap();
|
|
|
|
+
|
|
|
|
+ let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn no_undeliverable_msgs_reply_ok() {
|
|
fn no_undeliverable_msgs_reply_ok() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeliverable"),
|
|
NameDef::new("Undeliverable"),
|
|
[ActorDef::new("actor", ["Listening", "Client"])],
|
|
[ActorDef::new("actor", ["Listening", "Client"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -489,17 +410,17 @@ mod tests {
|
|
Message::new("Msg", true, []),
|
|
Message::new("Msg", true, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn no_undeliverable_msgs_service_ok() {
|
|
fn no_undeliverable_msgs_service_ok() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeliverable"),
|
|
NameDef::new("Undeliverable"),
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -511,17 +432,17 @@ mod tests {
|
|
Message::new("Msg", false, []),
|
|
Message::new("Msg", false, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn no_undeliverable_msgs_owned_ok() {
|
|
fn no_undeliverable_msgs_owned_ok() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeliverable"),
|
|
NameDef::new("Undeliverable"),
|
|
[ActorDef::new("actor", ["FileClient", "FileHandle"])],
|
|
[ActorDef::new("actor", ["FileClient", "FileHandle"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -533,17 +454,17 @@ mod tests {
|
|
Message::new("FileOp", false, []),
|
|
Message::new("FileOp", false, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn no_undeliverable_msgs_err() {
|
|
fn no_undeliverable_msgs_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("Undeliverable"),
|
|
NameDef::new("Undeliverable"),
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -555,17 +476,17 @@ mod tests {
|
|
Message::new("Msg", false, []),
|
|
Message::new("Msg", false, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.no_undeliverable_msgs();
|
|
let result = input.no_undeliverable_msgs();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::UNDELIVERABLE_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::UNDELIVERABLE_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn replies_expected_ok() {
|
|
fn replies_expected_ok() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("ValidReplies"),
|
|
NameDef::new("ValidReplies"),
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -577,17 +498,17 @@ mod tests {
|
|
Message::new("Msg", true, []),
|
|
Message::new("Msg", true, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.replies_expected();
|
|
let result = input.replies_expected();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn replies_expected_invalid_reply_err() {
|
|
fn replies_expected_invalid_reply_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("ValidReplies"),
|
|
NameDef::new("ValidReplies"),
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[ActorDef::new("actor", ["Client", "Server"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -599,17 +520,17 @@ mod tests {
|
|
Message::new("Msg", true, []),
|
|
Message::new("Msg", true, []),
|
|
)],
|
|
)],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.replies_expected();
|
|
let result = input.replies_expected();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::INVALID_REPLY_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::INVALID_REPLY_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn replies_expected_multiple_replies_err() {
|
|
fn replies_expected_multiple_replies_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("ValidReplies"),
|
|
NameDef::new("ValidReplies"),
|
|
[ActorDef::new("actor", ["Client", "OtherClient", "Server"])],
|
|
[ActorDef::new("actor", ["Client", "OtherClient", "Server"])],
|
|
[Transition::new(
|
|
[Transition::new(
|
|
@@ -627,77 +548,17 @@ mod tests {
|
|
),
|
|
),
|
|
],
|
|
],
|
|
)],
|
|
)],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.replies_expected();
|
|
let result = input.replies_expected();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::MULTIPLE_REPLIES_ERR);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- #[test]
|
|
|
|
- fn msg_sent_or_received_msg_received_ok() {
|
|
|
|
- let protocol = Protocol::new(
|
|
|
|
- NameDef::new("Test"),
|
|
|
|
- [ActorDef::new("actor", ["Init"])],
|
|
|
|
- [Transition::new(
|
|
|
|
- State::new("Init", []),
|
|
|
|
- Some(Message::new("Activate", false, [])),
|
|
|
|
- [State::new("End", [])],
|
|
|
|
- [],
|
|
|
|
- )],
|
|
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
-
|
|
|
|
- let result = input.msg_sent_or_received();
|
|
|
|
-
|
|
|
|
- assert_ok!(result);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- #[test]
|
|
|
|
- fn msg_sent_or_received_msg_sent_ok() {
|
|
|
|
- let protocol = Protocol::new(
|
|
|
|
- NameDef::new("Test"),
|
|
|
|
- [ActorDef::new("actor", ["First", "Second"])],
|
|
|
|
- [Transition::new(
|
|
|
|
- State::new("First", []),
|
|
|
|
- None,
|
|
|
|
- [State::new("First", [])],
|
|
|
|
- [Dest::new(
|
|
|
|
- DestinationState::Individual(State::new("Second", [])),
|
|
|
|
- Message::new("Msg", false, []),
|
|
|
|
- )],
|
|
|
|
- )],
|
|
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
-
|
|
|
|
- let result = input.msg_sent_or_received();
|
|
|
|
-
|
|
|
|
- assert_ok!(result);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- #[test]
|
|
|
|
- fn msg_sent_or_received_neither_err() {
|
|
|
|
- let protocol = Protocol::new(
|
|
|
|
- NameDef::new("Test"),
|
|
|
|
- [ActorDef::new("actor", ["First"])],
|
|
|
|
- [Transition::new(
|
|
|
|
- State::new("First", []),
|
|
|
|
- None,
|
|
|
|
- [State::new("First", [])],
|
|
|
|
- [],
|
|
|
|
- )],
|
|
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
-
|
|
|
|
- let result = input.msg_sent_or_received();
|
|
|
|
-
|
|
|
|
- assert_err!(result, ProtocolValidator::NO_MSG_SENT_OR_RECEIVED_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::MULTIPLE_REPLIES_ERR);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn clients_only_receive_replies_ok() {
|
|
fn clients_only_receive_replies_ok() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("ClientReplies"),
|
|
NameDef::new("ClientReplies"),
|
|
[
|
|
[
|
|
ActorDef::new("client", ["Client", "Waiting"]),
|
|
ActorDef::new("client", ["Client", "Waiting"]),
|
|
@@ -735,17 +596,17 @@ mod tests {
|
|
[],
|
|
[],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.clients_only_receive_replies();
|
|
let result = input.clients_only_receive_replies();
|
|
|
|
|
|
- assert_ok!(result);
|
|
|
|
|
|
+ assert_ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn clients_only_receive_replies_err() {
|
|
fn clients_only_receive_replies_err() {
|
|
- let protocol = Protocol::new(
|
|
|
|
|
|
+ let input = ProtocolModel::new(Protocol::new(
|
|
NameDef::new("ClientReplies"),
|
|
NameDef::new("ClientReplies"),
|
|
[
|
|
[
|
|
ActorDef::new("client", ["Client", "Waiting"]),
|
|
ActorDef::new("client", ["Client", "Waiting"]),
|
|
@@ -789,11 +650,11 @@ mod tests {
|
|
[],
|
|
[],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
- );
|
|
|
|
- let input = ProtocolValidator::new(&protocol);
|
|
|
|
|
|
+ ))
|
|
|
|
+ .unwrap();
|
|
|
|
|
|
let result = input.clients_only_receive_replies();
|
|
let result = input.clients_only_receive_replies();
|
|
|
|
|
|
- assert_err!(result, ProtocolValidator::CLIENT_RECEIVED_NON_REPLY_ERR);
|
|
|
|
|
|
+ assert_err(result, error::msgs::CLIENT_RECEIVED_NON_REPLY_ERR);
|
|
}
|
|
}
|
|
}
|
|
}
|