#![cfg_attr(not(test), allow(dead_code, unused_imports, unused_macros))]
use mocks::{ExpectedSend, test_stack};
use crate::{
Address, DEFAULT_TTL, FrameKind, Header, NetStackSendError,
interface_manager::InterfaceSendError,
};
pub mod mocks {
use std::collections::VecDeque;
use mutex::raw_impls::cs::CriticalSectionRawMutex;
use crate::{
Header, HeaderSeq, ProtocolError,
interface_manager::{InterfaceSendError, InterfaceState, Profile, SetStateError},
net_stack::ArcNetStack,
};
pub type TestNetStack = ArcNetStack<CriticalSectionRawMutex, MockProfile>;
pub fn test_stack() -> TestNetStack {
ArcNetStack::new_with_profile(MockProfile::default())
}
pub struct ExpectedSend {
pub hdr: Header,
pub data: Vec<u8>,
pub retval: Result<(), InterfaceSendError>,
}
pub struct ExpectedSendErr {
pub hdr: Header,
pub err: ProtocolError,
pub retval: Result<(), InterfaceSendError>,
}
pub struct ExpectedSendRaw {
pub hdr: HeaderSeq,
pub body: Vec<u8>,
pub retval: Result<(), InterfaceSendError>,
}
#[derive(Default)]
pub struct MockProfile {
pub expected_sends: VecDeque<ExpectedSend>,
pub expected_send_errs: VecDeque<ExpectedSendErr>,
pub expected_send_raws: VecDeque<ExpectedSendRaw>,
}
impl MockProfile {
pub fn add_exp_send(&mut self, exp: ExpectedSend) {
self.expected_sends.push_back(exp);
}
pub fn add_exp_send_err(&mut self, exp: ExpectedSendErr) {
self.expected_send_errs.push_back(exp);
}
pub fn add_exp_send_raw(&mut self, exp: ExpectedSendRaw) {
self.expected_send_raws.push_back(exp);
}
pub fn assert_all_empty(&self) {
assert!(self.expected_sends.is_empty());
assert!(self.expected_send_errs.is_empty());
assert!(self.expected_send_raws.is_empty());
}
}
impl Profile for MockProfile {
type InterfaceIdent = u64;
fn send<T: serde::Serialize>(
&mut self,
hdr: &Header,
data: &T,
) -> Result<(), InterfaceSendError> {
let data = postcard::to_stdvec(data).expect("Serializing send failed");
log::trace!("{}: Sending data:{:02X?}", hdr, data);
let now = self.expected_sends.pop_front().expect("Unexpected send");
assert_eq!(&now.hdr, hdr, "Send header mismatch");
assert_eq!(&now.data, &data, "Send data mismatch");
now.retval
}
fn send_err(
&mut self,
_hdr: &Header,
_err: ProtocolError,
_source: Option<Self::InterfaceIdent>,
) -> Result<(), InterfaceSendError> {
todo!()
}
fn send_raw(
&mut self,
_hdr: &HeaderSeq,
_data: &[u8],
_source: Self::InterfaceIdent,
) -> Result<(), InterfaceSendError> {
todo!()
}
fn interface_state(&mut self, _ident: Self::InterfaceIdent) -> Option<InterfaceState> {
todo!()
}
fn set_interface_state(
&mut self,
_ident: Self::InterfaceIdent,
_state: InterfaceState,
) -> Result<(), SetStateError> {
todo!()
}
}
}
macro_rules! send_testa {
( | Case | Header | Val | ProfileReturns | StackReturns |
| $(-)+ | $(-)+ | $(-)+ | $(-)+ | $(-)+ |
$(| $case:ident | $hdr:ident | $val:literal | $pret:ident | $sret:ident |)+
) => {
$(
#[test]
fn $case() {
let stack = test_stack();
stack.manage_profile(|p| {
p.add_exp_send(ExpectedSend {
hdr: $hdr(),
data: postcard::to_stdvec(&$val).unwrap(),
retval: $pret(),
});
});
let actval = stack.send_ty(&$hdr(), &$val);
assert_eq!(actval, $sret());
stack.manage_profile(|p| {
p.assert_all_empty();
});
}
)+
};
}
fn unicast_specific_port() -> Header {
Header {
src: Address::unknown(),
dst: Address {
network_id: 10,
node_id: 10,
port_id: 10,
},
any_all: None,
seq_no: None,
kind: FrameKind::RESERVED,
ttl: DEFAULT_TTL,
}
}
fn ok<E>() -> Result<(), E> {
Ok(())
}
fn interface_err(err: InterfaceSendError) -> Result<(), InterfaceSendError> {
Err(err)
}
fn stack_interface_err(err: InterfaceSendError) -> Result<(), NetStackSendError> {
Err(NetStackSendError::InterfaceSend(err))
}
fn stack_err(err: NetStackSendError) -> Result<(), NetStackSendError> {
Err(err)
}
fn inoroute() -> Result<(), InterfaceSendError> {
interface_err(InterfaceSendError::NoRouteToDest)
}
fn sinoroute() -> Result<(), NetStackSendError> {
stack_interface_err(InterfaceSendError::NoRouteToDest)
}
fn ifull() -> Result<(), InterfaceSendError> {
interface_err(InterfaceSendError::InterfaceFull)
}
fn sifull() -> Result<(), NetStackSendError> {
stack_interface_err(InterfaceSendError::InterfaceFull)
}
fn ilocal() -> Result<(), InterfaceSendError> {
interface_err(InterfaceSendError::DestinationLocal)
}
fn snoroute() -> Result<(), NetStackSendError> {
stack_err(NetStackSendError::NoRoute)
}
send_testa! {
| Case | Header | Val | ProfileReturns | StackReturns |
| ---- | ------ | --- | -------------- | ------------ |
| no_sockets_interface_takes | unicast_specific_port | 1234u64 | ok | ok |
| no_sockets_no_iroute | unicast_specific_port | 1234u64 | inoroute | sinoroute |
| no_sockets_interface_full | unicast_specific_port | 1234u64 | ifull | sifull |
| no_sockets_interface_local | unicast_specific_port | 1234u64 | ilocal | snoroute |
}