continue unittests
All checks were successful
Rust/sat-rs/pipeline/pr-main This commit looks good

This commit is contained in:
Robin Müller 2024-03-28 09:53:11 +01:00
parent 3aba762faa
commit 3642a88ea8
Signed by: muellerr
GPG Key ID: A649FB78196E3849
6 changed files with 131 additions and 16 deletions

View File

@ -21,6 +21,8 @@ use satrs_example::config::{ComponentIdList, PUS_APID};
use crate::update_time;
/// The PUS event handler subscribes for all events and converts them into ECSS PUS 5 event
/// packets. It also handles the verification completion of PUS event service requests.
pub struct PusEventHandler<VerificationReporter: VerificationReportingProvider> {
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
pus_event_dispatcher: DefaultPusEventU32Dispatcher<()>,
@ -30,8 +32,6 @@ pub struct PusEventHandler<VerificationReporter: VerificationReportingProvider>
timestamp: [u8; 7],
verif_handler: VerificationReporter,
}
/*
*/
impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<VerificationReporter> {
pub fn new(
@ -115,6 +115,8 @@ impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<Verifi
}
}
/// This is a thin wrapper around the event manager which also caches the sender component
/// used to send events to the event manager.
pub struct EventManagerWrapper {
event_manager: EventManagerWithBoundedMpsc,
event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
@ -132,6 +134,7 @@ impl EventManagerWrapper {
}
}
// Returns a cached event sender to send events to the event manager for routing.
pub fn clone_event_sender(&self) -> mpsc::Sender<(EventU32, Option<Params>)> {
self.event_sender.clone()
}

View File

@ -69,7 +69,10 @@ impl PusReplyHandler<ActivePusActionRequestStd, ActionReplyPusWithActionId> for
.expect("invalid token state");
let remove_entry = match &reply.message.variant {
ActionReplyPus::CompletionFailed { error_code, params } => {
let fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
let mut fail_data_len = 0;
if let Some(params) = params {
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
}
verification_handler
.completion_failure(
verif_token,
@ -87,7 +90,10 @@ impl PusReplyHandler<ActivePusActionRequestStd, ActionReplyPusWithActionId> for
step,
params,
} => {
let fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
let mut fail_data_len = 0;
if let Some(params) = params {
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
}
verification_handler
.step_failure(
verif_token,
@ -353,6 +359,7 @@ impl<
mod tests {
use satrs::{
pus::verification::VerificationReporterCfg,
res_code::ResultU16,
spacepackets::{
ecss::{
tc::{PusTcCreator, PusTcSecondaryHeader},
@ -632,21 +639,81 @@ mod tests {
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
assert!(result.is_ok());
assert!(result.unwrap());
testbench
.verif_reporter
.assert_full_completion_success(&req_id, None);
}
#[test]
fn reply_handling_completion_failure() {
// TODO: Implement
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
let action_id = 5_u32;
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
let active_action_req =
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
let error_code = ResultU16::new(2, 3);
let reply = ActionReplyPusWithActionId::new(
action_id,
ActionReplyPus::CompletionFailed {
error_code,
params: None,
},
);
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
assert!(result.is_ok());
assert!(result.unwrap());
testbench
.verif_reporter
.assert_completion_failure(&req_id, None, error_code.raw() as u64);
}
#[test]
fn reply_handling_step_success() {
// TODO: Implement
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
let action_id = 5_u32;
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
let active_action_req =
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
let reply =
ActionReplyPusWithActionId::new(action_id, ActionReplyPus::StepSuccess { step: 1 });
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
assert!(result.is_ok());
// Entry should not be removed, completion not done yet.
assert!(!result.unwrap());
let verif_info = testbench.verif_reporter.verification_info(&req_id);
assert!(verif_info.is_some());
let verif_info = verif_info.unwrap();
assert!(verif_info.step_status.unwrap());
assert_eq!(verif_info.step, 1);
}
#[test]
fn reply_handling_step_failure() {
// TODO: Implement
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
let action_id = 5_u32;
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
let active_action_req =
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
let error_code = ResultU16::new(2, 3);
let reply = ActionReplyPusWithActionId::new(
action_id,
ActionReplyPus::StepFailed {
error_code,
step: 1,
params: None,
},
);
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
assert!(result.is_ok());
assert!(result.unwrap());
let verif_info = testbench.verif_reporter.verification_info(&req_id);
assert!(verif_info.is_some());
let verif_info = verif_info.unwrap();
assert!(!verif_info.step_status.unwrap());
assert_eq!(verif_info.step, 1);
}
#[test]

View File

@ -538,7 +538,10 @@ mod tests {
let result = reply_testbench.handle_reply(&reply, &active_req, &[]);
assert!(result.is_ok());
assert!(result.unwrap());
reply_testbench.verif_reporter.check_completed(&req_id);
assert!(reply_testbench
.verif_reporter
.completion_status(&req_id)
.unwrap());
}
// TODO: Add more tests for reply handler: Request timeout and unrequested reply.

View File

@ -234,14 +234,15 @@ mod tests {
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
let mode_and_submode = ModeAndSubmode::new(2, 1);
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
mode_and_submode.write_to_be_bytes(&mut app_data[4..]).unwrap();
mode_and_submode
.write_to_be_bytes(&mut app_data[4..])
.unwrap();
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
let token = testbench.add_tc(&tc);
let (_active_req, req) = testbench
.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID)
.expect("conversion has failed");
assert_eq!(req, ModeRequest::SetMode(mode_and_submode));
}
#[test]
@ -263,7 +264,8 @@ mod tests {
fn mode_converter_announce_mode_recursively() {
let mut testbench = PusConverterTestbench::new(ModeRequestConverter::default());
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
let sec_header =
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
let mut app_data: [u8; 4] = [0; 4];
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);

View File

@ -32,12 +32,12 @@ pub enum ActionReplyPus {
},
CompletionFailed {
error_code: ResultU16,
params: Params,
params: Option<Params>,
},
StepFailed {
error_code: ResultU16,
step: u16,
params: Params,
params: Option<Params>,
},
}

View File

@ -1709,12 +1709,52 @@ pub mod test_util {
false
}
pub fn check_completed(&self, req_id: &RequestId) -> bool {
fn generic_completion_checks(
entry: &VerificationStatus,
step: Option<u16>,
completion_success: bool,
) {
assert!(entry.accepted.unwrap());
assert!(entry.started.unwrap());
if let Some(step) = step {
assert!(entry.step_status.unwrap());
assert_eq!(entry.step, step);
} else {
assert!(entry.step_status.is_none());
}
assert_eq!(entry.completed.unwrap(), completion_success);
}
pub fn assert_full_completion_success(&self, req_id: &RequestId, step: Option<u16>) {
let verif_map = self.verification_map.lock().unwrap();
if let Some(entry) = verif_map.borrow().get(req_id) {
return entry.completed.unwrap_or(false);
Self::generic_completion_checks(entry, step, true);
return;
}
false
panic!("request not in verification map");
}
pub fn assert_completion_failure(
&self,
req_id: &RequestId,
step: Option<u16>,
error_code: u64,
) {
let verif_map = self.verification_map.lock().unwrap();
if let Some(entry) = verif_map.borrow().get(req_id) {
Self::generic_completion_checks(entry, step, false);
assert_eq!(entry.fail_enum.unwrap(), error_code);
return;
}
panic!("request not in verification map");
}
pub fn completion_status(&self, req_id: &RequestId) -> Option<bool> {
let verif_map = self.verification_map.lock().unwrap();
if let Some(entry) = verif_map.borrow().get(req_id) {
return entry.completed;
}
panic!("request not in verification map");
}
}
}