basic test framework done

This commit is contained in:
Robin Müller 2022-11-01 19:24:09 +01:00
parent cc1f3ed091
commit 74f65243e4
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
3 changed files with 150 additions and 50 deletions

View File

@ -35,7 +35,7 @@ use alloc::vec::Vec;
use hashbrown::HashMap;
#[cfg(feature = "std")]
pub use stdmod::MpscEventReceiver;
pub use stdmod::*;
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
enum ListenerType {
@ -96,6 +96,14 @@ pub struct EventManager<SendProviderError, Event: GenericEvent = EventU32, AuxDa
event_receiver: Box<dyn EventReceiver<Event, AuxDataProvider>>,
}
/// Safety: It is safe to implement [Send] because all fields in the [EventManager] are [Send]
/// as well
#[cfg(feature = "std")]
unsafe impl<E, Event: GenericEvent + Send, AuxDataProvider: Send> Send
for EventManager<E, Event, AuxDataProvider>
{
}
pub enum HandlerResult<Provider: GenericEvent, AuxDataProvider> {
Empty,
Handled(u32, Provider, Option<AuxDataProvider>),
@ -128,8 +136,11 @@ impl<E, Event: GenericEvent + Copy> EventManager<E, Event> {
///
/// For example, this can be useful for a handler component which sends every event as
/// a telemetry packet.
pub fn subscribe_all(&mut self, dest: impl SendEventProvider<Event, Error = E> + 'static) {
self.update_listeners(ListenerType::All, dest);
pub fn subscribe_all(
&mut self,
send_provider: impl SendEventProvider<Event, Error = E> + 'static,
) {
self.update_listeners(ListenerType::All, send_provider);
}
/// Helper function which removes single subscriptions for which a group subscription already
@ -226,23 +237,24 @@ impl<E, Event: GenericEvent + Copy, AuxDataProvider: Clone>
#[cfg(feature = "std")]
pub mod stdmod {
use super::*;
use crate::event_man::{EventReceiver, EventWithAuxData};
use crate::events::{EventU16, EventU32, GenericEvent};
use crate::util::Params;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::{Receiver, SendError, Sender};
pub struct MpscEventReceiver<Event: GenericEvent = EventU32> {
pub struct MpscEventReceiver<Event: GenericEvent + Send = EventU32> {
mpsc_receiver: Receiver<(Event, Option<Params>)>,
}
impl<Event: GenericEvent> MpscEventReceiver<Event> {
impl<Event: GenericEvent + Send> MpscEventReceiver<Event> {
pub fn new(receiver: Receiver<(Event, Option<Params>)>) -> Self {
Self {
mpsc_receiver: receiver,
}
}
}
impl<Event: GenericEvent> EventReceiver<Event> for MpscEventReceiver<Event> {
impl<Event: GenericEvent + Send> EventReceiver<Event> for MpscEventReceiver<Event> {
fn receive(&mut self) -> Option<EventWithAuxData<Event>> {
if let Ok(event_and_data) = self.mpsc_receiver.try_recv() {
return Some(event_and_data);
@ -253,6 +265,35 @@ pub mod stdmod {
pub type MpscEventU32Receiver = MpscEventReceiver<EventU32>;
pub type MpscEventU16Receiver = MpscEventReceiver<EventU16>;
#[derive(Clone)]
pub struct MpscEventSendProvider<Event: GenericEvent + Send> {
id: u32,
sender: Sender<(Event, Option<Params>)>,
}
/// Safety: Send is safe to implement because both the ID and the MPSC sender are Send
//unsafe impl<Event: GenericEvent> Send for MpscEventSendProvider<Event> {}
impl<Event: GenericEvent + Send> MpscEventSendProvider<Event> {
pub fn new(id: u32, sender: Sender<(Event, Option<Params>)>) -> Self {
Self { id, sender }
}
}
impl<Event: GenericEvent + Send> SendEventProvider<Event> for MpscEventSendProvider<Event> {
type Error = SendError<(Event, Option<Params>)>;
fn id(&self) -> u32 {
self.id
}
fn send(&mut self, event: Event, aux_data: Option<Params>) -> Result<(), Self::Error> {
self.sender.send((event, aux_data))
}
}
pub type MpscEventU32SendProvider = MpscEventSendProvider<EventU32>;
pub type MpscEventU16SendProvider = MpscEventSendProvider<EventU16>;
}
#[cfg(test)]

View File

@ -38,6 +38,9 @@ pub struct DefaultPusMgmtBackendProvider<Event: GenericEvent = EventU32> {
disabled: HashSet<Event>,
}
/// Safety: All contained field are [Send] as well
unsafe impl<Event: GenericEvent + Send> Send for DefaultPusMgmtBackendProvider<Event> {}
impl<Event: GenericEvent> Default for DefaultPusMgmtBackendProvider<Event> {
fn default() -> Self {
Self {
@ -73,13 +76,19 @@ pub mod heapless_mod {
// TODO: After a new version of heapless is released which uses hash32 version 0.3, try using
// regular Event type again.
#[derive(Default)]
pub struct HeaplessPusMgmtBckendProvider<const N: usize, Provider: GenericEvent> {
pub struct HeaplessPusMgmtBackendProvider<const N: usize, Provider: GenericEvent> {
disabled: heapless::FnvIndexSet<LargestEventRaw, N>,
phantom: PhantomData<Provider>,
}
/// Safety: All contained field are [Send] as well
unsafe impl<const N: usize, Event: GenericEvent + Send> Send
for HeaplessPusMgmtBackendProvider<N, Event>
{
}
impl<const N: usize, Provider: GenericEvent> PusEventMgmtBackendProvider<Provider>
for HeaplessPusMgmtBckendProvider<N, Provider>
for HeaplessPusMgmtBackendProvider<N, Provider>
{
type Error = ();
@ -116,6 +125,9 @@ pub struct PusEventTmManager<BackendError, Provider: GenericEvent> {
backend: Box<dyn PusEventMgmtBackendProvider<Provider, Error = BackendError>>,
}
/// Safety: All contained fields are send as well.
unsafe impl<E: Send, Event: GenericEvent + Send> Send for PusEventTmManager<E, Event> {}
impl<BackendError, Provider: GenericEvent> PusEventTmManager<BackendError, Provider> {
pub fn new(
reporter: EventReporter,
@ -136,7 +148,6 @@ impl<BackendError, Event: GenericEvent> PusEventTmManager<BackendError, Event> {
pub fn generate_pus_event_tm_generic<E>(
&mut self,
severity: Severity,
sender: &mut (impl EcssTmSender<Error = E> + ?Sized),
time_stamp: &[u8],
event: Event,
@ -145,10 +156,7 @@ impl<BackendError, Event: GenericEvent> PusEventTmManager<BackendError, Event> {
if !self.backend.event_enabled(&event) {
return Ok(false);
}
if event.severity() != severity {
return Err(EventManError::SeverityMissmatch(severity, event.severity()));
}
match severity {
match event.severity() {
Severity::INFO => self
.reporter
.event_info(sender, time_stamp, event, aux_data)
@ -195,13 +203,7 @@ impl<BackendError> PusEventTmManager<BackendError, EventU32> {
event: EventU32TypedSev<Severity>,
aux_data: Option<&[u8]>,
) -> Result<bool, EventManError<E>> {
self.generate_pus_event_tm_generic(
Severity::SEVERITY,
sender,
time_stamp,
event.into(),
aux_data,
)
self.generate_pus_event_tm_generic(sender, time_stamp, event.into(), aux_data)
}
}
@ -261,13 +263,7 @@ mod tests {
assert!(res.is_ok());
assert!(res.unwrap());
let mut event_sent = event_man
.generate_pus_event_tm_generic(
Severity::LOW,
&mut sender,
&EMPTY_STAMP,
LOW_SEV_EVENT,
None,
)
.generate_pus_event_tm_generic(&mut sender, &EMPTY_STAMP, LOW_SEV_EVENT, None)
.expect("Sending low severity event failed");
assert!(!event_sent);
let res = event_rx.try_recv();

View File

@ -1,8 +1,11 @@
use fsrc_core::event_man::{EventManager, MpscEventReceiver, MpscEventU32SendProvider};
use fsrc_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
use fsrc_core::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventTmManager};
use fsrc_core::pus::{EcssTmError, EcssTmSender};
use fsrc_core::util::Params;
use spacepackets::tm::PusTm;
use std::sync::mpsc::{channel, SendError, TryRecvError};
use std::thread;
const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
@ -24,27 +27,87 @@ impl EcssTmSender for EventTmSender {
}
#[test]
fn test_basic() {
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
let backend = DefaultPusMgmtBackendProvider::<EventU32>::default();
let mut event_man = PusEventTmManager::new(reporter, Box::new(backend));
let (event_tx, event_rx) = channel();
let mut sender = EventTmSender { sender: event_tx };
let mut event_sent = event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
fn test_threaded_usage() {
let (event_sender, event_man_receiver) = channel();
let event_receiver = MpscEventReceiver::new(event_man_receiver);
let mut event_man = EventManager::new(Box::new(event_receiver));
assert!(event_sent);
// Will not check packet here, correctness of packet was tested somewhere else
event_rx.recv().expect("Receiving event TM failed");
let res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT);
assert!(res.is_ok());
assert!(res.unwrap());
event_sent = event_man
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
.expect("Sending info event failed");
assert!(!event_sent);
let res = event_rx.try_recv();
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), TryRecvError::Empty));
let (pus_event_man_tx, pus_event_man_rx) = channel();
let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx);
event_man.subscribe_all(pus_event_man_send_provider);
let (event_tx, event_rx) = channel();
let reporter = EventReporter::new(0x02, 128).expect("Creating event reporter failed");
let backend = DefaultPusMgmtBackendProvider::<EventU32>::default();
let mut pus_event_man = PusEventTmManager::new(reporter, Box::new(backend));
// PUS + Generic event manager thread
let jh0 = thread::spawn(move || {
let mut sender = EventTmSender { sender: event_tx };
loop {
let res = event_man.try_event_handling();
assert!(res.is_ok());
match pus_event_man_rx.try_recv() {
Ok((event, aux_data)) => {
// TODO: Convert auxiliary data into raw byte format
if let Some(aux_data) = aux_data {
match aux_data {
Params::Heapless(_) => {}
Params::Vec(_) => {}
Params::String(_) => {}
}
}
let res = pus_event_man.generate_pus_event_tm_generic(
&mut sender,
&EMPTY_STAMP,
event,
None,
);
assert!(res.is_ok());
assert!(res.unwrap());
break;
}
Err(e) => {
if let TryRecvError::Disconnected = e {
panic!("Event receiver disconnected!")
}
}
}
}
});
// Event sender and TM checker thread
let jh1 = thread::spawn(move || {
event_sender
.send((INFO_EVENT.into(), None))
.expect("Sending info event failed");
loop {
match event_rx.try_recv() {
// Event TM received successfully
Ok(_) => break,
Err(e) => {
if let TryRecvError::Disconnected = e {
panic!("Event sender disconnected!")
}
}
}
}
event_sender
.send((
LOW_SEV_EVENT.into(),
Some(Params::Heapless((2_u32, 3_u32).into())),
))
.expect("Sending low severity event failed");
loop {
match event_rx.try_recv() {
// Event TM received successfully
Ok(_) => break,
Err(e) => {
if let TryRecvError::Disconnected = e {
panic!("Event sender disconnected!")
}
}
}
}
});
jh0.join().expect("Joining manager thread failed");
jh1.join().expect("Joining creator thread failed");
}