diff --git a/satrs-core/src/pus/event_man.rs b/satrs-core/src/pus/event_man.rs index 132e24c..d51135a 100644 --- a/satrs-core/src/pus/event_man.rs +++ b/satrs-core/src/pus/event_man.rs @@ -82,7 +82,7 @@ pub mod heapless_mod { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub enum EventRequest { Enable(Event), Disable(Event), diff --git a/satrs-core/src/pus/event_srv.rs b/satrs-core/src/pus/event_srv.rs index 8c3704e..86f6b80 100644 --- a/satrs-core/src/pus/event_srv.rs +++ b/satrs-core/src/pus/event_srv.rs @@ -45,7 +45,7 @@ impl PusService5EventHandler PusService5EventHandler, @@ -148,11 +163,8 @@ mod tests { to self.common { fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; fn read_next_tm(&mut self) -> PusTmReader<'_>; - fn check_next_verification_tm( - &self, - subservice: u8, - token: VerificationToken, - ); + fn check_no_tm_available(&self) -> bool; + fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId); } to self.handler { @@ -160,4 +172,104 @@ mod tests { } } } + + fn event_test( + test_harness: &mut impl PusTestHarness, + subservice: Subservice, + expected_event_req: EventRequest, + event_req_receiver: mpsc::Receiver, + ) { + let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); + let sec_header = PusTcSecondaryHeader::new_simple(5, subservice as u8); + let mut app_data = [0; 4]; + TEST_EVENT_0 + .write_to_be_bytes(&mut app_data) + .expect("writing test event failed"); + let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true); + let token = test_harness.send_tc(&ping_tc); + let request_id = token.req_id(); + test_harness.handle_one_tc().unwrap(); + test_harness.check_next_verification_tm(1, request_id); + test_harness.check_next_verification_tm(3, request_id); + // Completion TM is not generated for us. + assert!(test_harness.check_no_tm_available()); + let event_request = event_req_receiver + .try_recv() + .expect("no event request received"); + assert_eq!(expected_event_req, event_request.request); + } + + #[test] + fn test_enabling_event_reporting() { + let (event_request_tx, event_request_rx) = mpsc::channel(); + let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx); + event_test( + &mut test_harness, + Subservice::TcEnableEventGeneration, + EventRequest::Enable(TEST_EVENT_0), + event_request_rx, + ); + } + + #[test] + fn test_disabling_event_reporting() { + let (event_request_tx, event_request_rx) = mpsc::channel(); + let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx); + event_test( + &mut test_harness, + Subservice::TcDisableEventGeneration, + EventRequest::Disable(TEST_EVENT_0), + event_request_rx, + ); + } + + #[test] + fn test_empty_tc_queue() { + let (event_request_tx, _) = mpsc::channel(); + let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx); + let result = test_harness.handle_one_tc(); + assert!(result.is_ok()); + let result = result.unwrap(); + if let PusPacketHandlerResult::Empty = result { + } else { + panic!("unexpected result type {result:?}") + } + } + + #[test] + fn test_sending_custom_subservice() { + let (event_request_tx, _) = mpsc::channel(); + let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx); + let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); + let sec_header = PusTcSecondaryHeader::new_simple(5, 200); + let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); + test_harness.send_tc(&ping_tc); + let result = test_harness.handle_one_tc(); + assert!(result.is_ok()); + let result = result.unwrap(); + if let PusPacketHandlerResult::CustomSubservice(subservice, _) = result { + assert_eq!(subservice, 200); + } else { + panic!("unexpected result type {result:?}") + } + } + + #[test] + fn test_sending_invalid_app_data() { + let (event_request_tx, _) = mpsc::channel(); + let mut test_harness = Pus5HandlerWithStoreTester::new(event_request_tx); + let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); + let sec_header = + PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8); + let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &[0, 1, 2], true); + test_harness.send_tc(&ping_tc); + let result = test_harness.handle_one_tc(); + assert!(result.is_err()); + let result = result.unwrap_err(); + if let PusPacketHandlingError::NotEnoughAppData(string) = result { + assert_eq!(string, "at least 4 bytes event ID expected"); + } else { + panic!("unexpected result type {result:?}") + } + } } diff --git a/satrs-core/src/pus/mod.rs b/satrs-core/src/pus/mod.rs index b2a4ae3..d833891 100644 --- a/satrs-core/src/pus/mod.rs +++ b/satrs-core/src/pus/mod.rs @@ -914,6 +914,7 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), E #[cfg(test)] pub mod tests { + use std::sync::mpsc::TryRecvError; use std::sync::{mpsc, RwLock}; use alloc::boxed::Box; @@ -950,12 +951,8 @@ pub mod tests { pub trait PusTestHarness { fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; fn read_next_tm(&mut self) -> PusTmReader<'_>; - fn check_next_verification_tm( - &self, - subservice: u8, - token: VerificationToken, - ); - + fn check_no_tm_available(&self) -> bool; + fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId); fn handle_one_tc(&mut self) -> Result; } @@ -1053,11 +1050,15 @@ pub mod tests { PusTmReader::new(&self.tm_buf, 7).unwrap().0 } - pub fn check_next_verification_tm( - &self, - subservice: u8, - token: VerificationToken, - ) { + pub fn check_no_tm_available(&self) -> bool { + let next_msg = self.tm_receiver.try_recv(); + if let TryRecvError::Empty = next_msg.unwrap_err() { + return true; + } + false + } + + pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); let tm_addr = next_msg.unwrap(); @@ -1069,7 +1070,7 @@ pub mod tests { assert_eq!(tm.apid(), TEST_APID); let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed"); - assert_eq!(req_id, token.req_id()); + assert_eq!(req_id, expected_request_id); } } @@ -1134,11 +1135,15 @@ pub mod tests { .0 } - pub fn check_next_verification_tm( - &self, - subservice: u8, - token: VerificationToken, - ) { + pub fn check_no_tm_available(&self) -> bool { + let next_msg = self.tm_receiver.try_recv(); + if let TryRecvError::Empty = next_msg.unwrap_err() { + return true; + } + false + } + + pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); let next_msg = next_msg.unwrap(); @@ -1148,7 +1153,7 @@ pub mod tests { assert_eq!(tm.apid(), TEST_APID); let req_id = RequestId::from_bytes(tm.user_data()).expect("generating request ID failed"); - assert_eq!(req_id, token.req_id()); + assert_eq!(req_id, expected_request_id); } } } diff --git a/satrs-core/src/pus/test.rs b/satrs-core/src/pus/test.rs index 797c07b..cb38051 100644 --- a/satrs-core/src/pus/test.rs +++ b/satrs-core/src/pus/test.rs @@ -15,9 +15,7 @@ pub struct PusService17TestHandler { impl PusService17TestHandler { pub fn new(service_helper: PusServiceHelper) -> Self { - Self { - service_helper, - } + Self { service_helper } } pub fn handle_one_tc(&mut self) -> Result { @@ -50,7 +48,8 @@ impl PusService17TestHandler VerificationToken; fn read_next_tm(&mut self) -> PusTmReader<'_>; - fn check_next_verification_tm( + fn check_no_tm_available(&self) -> bool; + fn check_next_verification_tm( &self, subservice: u8, - token: VerificationToken, + expected_request_id: RequestId ); } @@ -163,10 +164,11 @@ mod tests { to self.common { fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; fn read_next_tm(&mut self) -> PusTmReader<'_>; - fn check_next_verification_tm( + fn check_no_tm_available(&self) -> bool; + fn check_next_verification_tm( &self, subservice: u8, - token: VerificationToken, + expected_request_id: RequestId, ); } @@ -182,16 +184,17 @@ mod tests { let sec_header = PusTcSecondaryHeader::new_simple(17, 1); let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true); let token = test_harness.send_tc(&ping_tc); + let request_id = token.req_id(); let result = test_harness.handle_one_tc(); assert!(result.is_ok()); // We should see 4 replies in the TM queue now: Acceptance TM, Start TM, ping reply and // Completion TM // Acceptance TM - test_harness.check_next_verification_tm(1, token); + test_harness.check_next_verification_tm(1, request_id); // Start TM - test_harness.check_next_verification_tm(3, token); + test_harness.check_next_verification_tm(3, request_id); // Ping reply let tm = test_harness.read_next_tm(); @@ -200,7 +203,31 @@ mod tests { assert!(tm.user_data().is_empty()); // TM completion - test_harness.check_next_verification_tm(7, token); + test_harness.check_next_verification_tm(7, request_id); + } + + #[test] + fn test_basic_ping_processing_using_store() { + let mut test_harness = Pus17HandlerWithStoreTester::new(); + ping_test(&mut test_harness); + } + + #[test] + fn test_basic_ping_processing_using_vec() { + let mut test_harness = Pus17HandlerWithVecTester::new(); + ping_test(&mut test_harness); + } + + #[test] + fn test_empty_tc_queue() { + let mut test_harness = Pus17HandlerWithStoreTester::new(); + let result = test_harness.handle_one_tc(); + assert!(result.is_ok()); + let result = result.unwrap(); + if let PusPacketHandlerResult::Empty = result { + } else { + panic!("unexpected result type {result:?}") + } } #[test] @@ -236,28 +263,4 @@ mod tests { panic!("unexpected result type {result:?}") } } - - #[test] - fn test_basic_ping_processing_using_store() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); - ping_test(&mut test_harness); - } - - #[test] - fn test_basic_ping_processing_using_vec() { - let mut test_harness = Pus17HandlerWithVecTester::new(); - ping_test(&mut test_harness); - } - - #[test] - fn test_empty_tc_queue() { - let mut test_harness = Pus17HandlerWithStoreTester::new(); - let result = test_harness.handle_one_tc(); - assert!(result.is_ok()); - let result = result.unwrap(); - if let PusPacketHandlerResult::Empty = result { - } else { - panic!("unexpected result type {result:?}") - } - } } diff --git a/satrs-example/src/pus/test.rs b/satrs-example/src/pus/test.rs index dc2fbe0..a8d9a44 100644 --- a/satrs-example/src/pus/test.rs +++ b/satrs-example/src/pus/test.rs @@ -38,9 +38,13 @@ impl Service17CustomWrapper { warn!("PUS17: Subservice {subservice} not implemented") } PusPacketHandlerResult::CustomSubservice(subservice, token) => { - let (tc, _) = - PusTcReader::new(self.pus17_handler.service_helper.tc_in_mem_converter.tc_slice_raw()) - .unwrap(); + let (tc, _) = PusTcReader::new( + self.pus17_handler + .service_helper + .tc_in_mem_converter + .tc_slice_raw(), + ) + .unwrap(); let time_stamper = TimeProvider::from_now_with_u16_days().unwrap(); let mut stamp_buf: [u8; 7] = [0; 7]; time_stamper.write_to_bytes(&mut stamp_buf).unwrap();