diff --git a/coverage.py b/coverage.py index b7efbe9..126a101 100755 --- a/coverage.py +++ b/coverage.py @@ -43,8 +43,8 @@ def main(): parser.add_argument( "-p", "--package", - choices=["satrs-core"], - default="satrs-core", + choices=["satrs"], + default="satrs", help="Choose project to generate coverage for", ) parser.add_argument( diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index 6338c23..653fe80 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -45,9 +45,10 @@ impl PusActionToRequestConverter for ExampleActionRequestConverter { FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA), ) .expect("Sending start failure failed"); - return Err(PusPacketHandlingError::NotEnoughAppData( - "Expected at least 4 bytes".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 8, + found: user_data.len(), + }); } let target_id = TargetAndApidId::from_pus_tc(tc).unwrap(); let action_id = u32::from_be_bytes(user_data[4..8].try_into().unwrap()); diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 1dd82c0..035bb86 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -50,9 +50,10 @@ impl PusHkToRequestConverter for ExampleHkRequestConverter { ), ) .expect("Sending start failure TM failed"); - return Err(PusPacketHandlingError::NotEnoughAppData( - "Expected at least 8 bytes of app data".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 4, + found: 0, + }); } if user_data.len() < 8 { let err = if user_data.len() < 4 { @@ -65,9 +66,10 @@ impl PusHkToRequestConverter for ExampleHkRequestConverter { verif_reporter .start_failure(token, FailParams::new(time_stamp, err, &user_data_len_raw)) .expect("Sending start failure TM failed"); - return Err(PusPacketHandlingError::NotEnoughAppData( - "Expected at least 8 bytes of app data".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 8, + found: 4, + }); } let subservice = tc.subservice(); let target_id = TargetAndApidId::from_pus_tc(tc).expect("invalid tc format"); @@ -109,9 +111,10 @@ impl PusHkToRequestConverter for ExampleHkRequestConverter { ), ) .expect("Sending start failure TM failed"); - return Err(PusPacketHandlingError::NotEnoughAppData( - "expected at least 8 bytes of app data".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 12, + found: user_data.len(), + }); } HkRequest::ModifyCollectionInterval( unique_id, diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index ffa5988..b903cb4 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -168,7 +168,7 @@ impl PusRoutingErrorHandler for GenericRoutingErrorHandler token: satrs::pus::verification::VerificationToken< satrs::pus::verification::TcStateAccepted, >, - tc: &PusTcReader, + _tc: &PusTcReader, error: Self::Error, time_stamp: &[u8], verif_reporter: &impl VerificationReportingProvider, @@ -195,17 +195,13 @@ impl PusRoutingErrorHandler for GenericRoutingErrorHandler ) .expect("Sending start failure failed"); } - GenericRoutingError::NotEnoughAppData => { - let app_data_len = tc.app_data().len() as u32; - let app_data_len_raw = app_data_len.to_be_bytes(); + GenericRoutingError::NotEnoughAppData { expected, found } => { + let mut context_info = (found as u32).to_be_bytes().to_vec(); + context_info.extend_from_slice(&(expected as u32).to_be_bytes()); verif_reporter .start_failure( token, - FailParams::new( - time_stamp, - &tmtc_err::NOT_ENOUGH_APP_DATA, - &app_data_len_raw, - ), + FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info), ) .expect("Sending start failure failed"); } diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 77c2050..6eb1302 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -89,9 +89,9 @@ pub mod std_mod { RoutingError = GenericRoutingError, > { service_helper: PusServiceHelper, - request_converter: RequestConverter, - request_router: RequestRouter, - routing_error_handler: RoutingErrorHandler, + pub request_converter: RequestConverter, + pub request_router: RequestRouter, + pub routing_error_handler: RoutingErrorHandler, } impl< @@ -100,7 +100,7 @@ pub mod std_mod { RequestConverter: PusActionToRequestConverter, RequestRouter: PusActionRequestRouter, RoutingErrorHandler: PusRoutingErrorHandler, - RoutingError, + RoutingError: Clone, > PusService8ActionHandler< TcInMemConverter, @@ -110,6 +110,8 @@ pub mod std_mod { RoutingErrorHandler, RoutingError, > + where + PusPacketHandlingError: From, { pub fn new( service_helper: PusServiceHelper, @@ -155,10 +157,11 @@ pub mod std_mod { target_id, ecss_tc_and_token.token, &tc, - e, + e.clone(), &time_stamp, &self.service_helper.common.verification_handler, ); + return Err(e.into()); } Ok(PusPacketHandlerResult::RequestHandled) } @@ -176,7 +179,7 @@ mod tests { ecss::{ tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}, tm::PusTmReader, - PusPacket, + PusPacket, WritablePusPacket, }, CcsdsPacket, SequenceFlags, SpHeader, }; @@ -197,7 +200,7 @@ mod tests { #[derive(Default)] pub struct TestRouter { pub routing_requests: RefCell>, - pub routing_error: RefCell>, + pub injected_routing_failure: RefCell>, } impl PusActionRequestRouter for TestRouter { @@ -212,11 +215,25 @@ mod tests { self.routing_requests .borrow_mut() .push_back((target_id, hk_request)); + if self.injected_routing_failure.borrow().is_some() { + return Err(self.injected_routing_failure.borrow_mut().take().unwrap()); + } Ok(()) } } - impl PusRoutingErrorHandler for TestRouter { + impl TestRouter { + pub fn inject_routing_error(&mut self, error: GenericRoutingError) { + *self.injected_routing_failure.borrow_mut() = Some(error); + } + } + + #[derive(Default)] + struct TestRoutingErrorHandler { + pub routing_errors: RefCell>, + } + + impl PusRoutingErrorHandler for TestRoutingErrorHandler { type Error = GenericRoutingError; fn handle_error( @@ -228,7 +245,7 @@ mod tests { _time_stamp: &[u8], _verif_reporter: &impl VerificationReportingProvider, ) { - self.routing_error + self.routing_errors .borrow_mut() .push_back((target_id, error)); } @@ -263,9 +280,10 @@ mod tests { ), ) .expect("start success failure"); - return Err(PusPacketHandlingError::NotEnoughAppData( - "user data too short".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 4, + found: tc.user_data().len(), + }); } if tc.subservice() == 1 { verif_reporter @@ -292,7 +310,7 @@ mod tests { TestVerificationReporter, TestConverter, TestRouter, - TestRouter, + TestRoutingErrorHandler, >, } @@ -306,7 +324,7 @@ mod tests { srv_handler, TestConverter::default(), TestRouter::default(), - TestRouter::default(), + TestRoutingErrorHandler::default(), ), } } @@ -342,9 +360,116 @@ mod tests { let action_id: u32 = 1; let action_id_raw = action_id.to_be_bytes(); let tc = PusTcCreator::new(&mut sp_header, sec_header, action_id_raw.as_ref(), true); - let token = action_handler.send_tc(&tc); - let request_id = token.req_id(); + action_handler.send_tc(&tc); let result = action_handler.handle_one_tc(); assert!(result.is_ok()); + assert_eq!( + action_handler + .handler + .request_converter + .conversion_request + .len(), + 1 + ); + assert_eq!( + action_handler.handler.request_converter.conversion_request[0], + tc.to_vec().unwrap() + ); + assert_eq!( + action_handler + .handler + .request_router + .routing_requests + .borrow() + .len(), + 1 + ); + let (target_id, action_req) = action_handler + .handler + .request_router + .routing_requests + .borrow_mut() + .pop_front() + .unwrap(); + assert_eq!(target_id, TEST_APID.into()); + if let ActionRequest::UnsignedIdAndVecData { action_id, data } = action_req { + assert_eq!(action_id, 1); + assert_eq!(data, &[]); + } + } + + #[test] + fn test_routing_error() { + let mut action_handler = Pus8HandlerWithVecTester::new(); + let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap(); + let sec_header = PusTcSecondaryHeader::new_simple(8, 1); + let action_id: u32 = 1; + let action_id_raw = action_id.to_be_bytes(); + let tc = PusTcCreator::new(&mut sp_header, sec_header, action_id_raw.as_ref(), true); + let error = GenericRoutingError::UnknownTargetId(25); + action_handler + .handler + .request_router + .inject_routing_error(error); + action_handler.send_tc(&tc); + let result = action_handler.handle_one_tc(); + assert!(result.is_err()); + let check_error = |routing_error: GenericRoutingError| { + if let GenericRoutingError::UnknownTargetId(id) = routing_error { + assert_eq!(id, 25); + } else { + panic!("unexpected error type"); + } + }; + if let PusPacketHandlingError::RequestRoutingError(routing_error) = result.unwrap_err() { + check_error(routing_error); + } else { + panic!("unexpected error type"); + } + + assert_eq!( + action_handler + .handler + .request_converter + .conversion_request + .len(), + 1 + ); + assert_eq!( + action_handler.handler.request_converter.conversion_request[0], + tc.to_vec().unwrap() + ); + + let (target_id, action_req) = action_handler + .handler + .request_router + .routing_requests + .borrow_mut() + .pop_front() + .unwrap(); + assert_eq!(target_id, TEST_APID.into()); + if let ActionRequest::UnsignedIdAndVecData { action_id, data } = action_req { + assert_eq!(action_id, 1); + assert_eq!(data, &[]); + } + + assert_eq!( + action_handler + .handler + .routing_error_handler + .routing_errors + .borrow() + .len(), + 1 + ); + let (target_id, found_error) = action_handler + .handler + .routing_error_handler + .routing_errors + .borrow_mut() + .pop_front() + .unwrap(); + assert_eq!(target_id, TEST_APID.into()); + check_error(found_error); } } diff --git a/satrs/src/pus/event_srv.rs b/satrs/src/pus/event_srv.rs index 0987e6b..b55a5c9 100644 --- a/satrs/src/pus/event_srv.rs +++ b/satrs/src/pus/event_srv.rs @@ -52,9 +52,10 @@ impl< } let handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| { if tc.user_data().len() < 4 { - return Err(PusPacketHandlingError::NotEnoughAppData( - "at least 4 bytes event ID expected".into(), - )); + return Err(PusPacketHandlingError::NotEnoughAppData { + expected: 4, + found: tc.user_data().len(), + }); } let user_data = tc.user_data(); let event_u32 = EventU32::from(u32::from_be_bytes(user_data[0..4].try_into().unwrap())); @@ -281,8 +282,9 @@ mod tests { 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"); + if let PusPacketHandlingError::NotEnoughAppData { expected, found } = result { + assert_eq!(expected, 4); + assert_eq!(found, 3); } else { panic!("unexpected result type {result:?}") } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index b6ea08f..4afe0e3 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -638,8 +638,8 @@ pub mod std_mod { #[derive(Debug, Clone, Error)] pub enum GenericRoutingError { - #[error("Not enough application data, expected at least 4 bytes for target ID")] - NotEnoughAppData, + #[error("not enough application data, expected at least {expected}, found {found}")] + NotEnoughAppData { expected: usize, found: usize }, #[error("Unknown target ID {0}")] UnknownTargetId(TargetId), #[error("Sending action request failed: {0}")] @@ -654,8 +654,8 @@ pub mod std_mod { WrongService(u8), #[error("invalid subservice {0}")] InvalidSubservice(u8), - #[error("not enough application data available: {0}")] - NotEnoughAppData(String), + #[error("not enough application data, expected at least {expected}, found {found}")] + NotEnoughAppData { expected: usize, found: usize }, #[error("PUS packet too large, does not fit in buffer: {0}")] PusPacketTooLarge(usize), #[error("invalid application data")] @@ -1110,7 +1110,7 @@ pub mod tests { current_tm: Option>, tc_sender: mpsc::Sender, tm_receiver: mpsc::Receiver>, - verification_handler: VerificationReporter, + pub verification_handler: VerificationReporter, } impl PusServiceHandlerWithVecCommon {