basic test framework done
This commit is contained in:
parent
cc1f3ed091
commit
74f65243e4
@ -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)]
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
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());
|
||||
event_sent = event_man
|
||||
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
|
||||
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");
|
||||
assert!(!event_sent);
|
||||
let res = event_rx.try_recv();
|
||||
assert!(res.is_err());
|
||||
assert!(matches!(res.unwrap_err(), TryRecvError::Empty));
|
||||
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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user