This commit is contained in:
parent
3aba762faa
commit
3642a88ea8
@ -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()
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user