Major refactoring and update of PUS module
This commit is contained in:
.gitignoreREADME.mdcoverage.py
misc
satrs-example
satrs-mib
satrs-shared
satrs
CHANGELOG.mdCargo.tomlrelease-checklist.md
src
action.rs
cfdp
encoding
event_man.rsevents.rshal
hk.rslib.rsmode.rsmode_tree.rsobjects.rsparams.rspool.rspus
action.rsevent.rsevent_man.rsevent_srv.rshk.rsmod.rsmode.rsscheduler.rsscheduler_srv.rstest.rsverification.rs
queue.rsrequest.rsseq_count.rstime.rstmtc
tests
@ -2,17 +2,18 @@ use crate::events::EventU32;
|
||||
use crate::pus::event_man::{EventRequest, EventRequestWithToken};
|
||||
use crate::pus::verification::TcStateToken;
|
||||
use crate::pus::{PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError};
|
||||
use crate::queue::GenericSendError;
|
||||
use spacepackets::ecss::event::Subservice;
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use super::verification::VerificationReportingProvider;
|
||||
use super::{
|
||||
get_current_cds_short_timestamp, EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore,
|
||||
PusServiceHelper,
|
||||
EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericConversionError,
|
||||
GenericRoutingError, PusServiceHelper,
|
||||
};
|
||||
|
||||
pub struct PusService5EventHandler<
|
||||
pub struct PusEventServiceHandler<
|
||||
TcReceiver: EcssTcReceiverCore,
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
@ -28,7 +29,7 @@ impl<
|
||||
TmSender: EcssTmSenderCore,
|
||||
TcInMemConverter: EcssTcInMemConverter,
|
||||
VerificationReporter: VerificationReportingProvider,
|
||||
> PusService5EventHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||
{
|
||||
pub fn new(
|
||||
service_helper: PusServiceHelper<
|
||||
@ -45,16 +46,19 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
pub fn poll_and_handle_next_tc(
|
||||
&mut self,
|
||||
time_stamp: &[u8],
|
||||
) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
let possible_packet = self.service_helper.retrieve_and_accept_next_packet()?;
|
||||
if possible_packet.is_none() {
|
||||
return Ok(PusPacketHandlerResult::Empty);
|
||||
}
|
||||
let ecss_tc_and_token = possible_packet.unwrap();
|
||||
let tc = self
|
||||
.service_helper
|
||||
.tc_in_mem_converter
|
||||
.convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?;
|
||||
self.service_helper
|
||||
.tc_in_mem_converter_mut()
|
||||
.cache(&ecss_tc_and_token.tc_in_memory)?;
|
||||
let tc = self.service_helper.tc_in_mem_converter().convert()?;
|
||||
let subservice = tc.subservice();
|
||||
let srv = Subservice::try_from(subservice);
|
||||
if srv.is_err() {
|
||||
@ -63,63 +67,73 @@ impl<
|
||||
ecss_tc_and_token.token,
|
||||
));
|
||||
}
|
||||
let handle_enable_disable_request = |enable: bool, stamp: [u8; 7]| {
|
||||
if tc.user_data().len() < 4 {
|
||||
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()));
|
||||
let start_token = self
|
||||
.service_helper
|
||||
.common
|
||||
.verification_handler
|
||||
.start_success(ecss_tc_and_token.token, &stamp)
|
||||
.map_err(|_| PartialPusHandlingError::Verification);
|
||||
let partial_error = start_token.clone().err();
|
||||
let mut token: TcStateToken = ecss_tc_and_token.token.into();
|
||||
if let Ok(start_token) = start_token {
|
||||
token = start_token.into();
|
||||
}
|
||||
let event_req_with_token = if enable {
|
||||
EventRequestWithToken {
|
||||
request: EventRequest::Enable(event_u32),
|
||||
token,
|
||||
let handle_enable_disable_request =
|
||||
|enable: bool| -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
if tc.user_data().len() < 4 {
|
||||
return Err(GenericConversionError::NotEnoughAppData {
|
||||
expected: 4,
|
||||
found: tc.user_data().len(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
} else {
|
||||
EventRequestWithToken {
|
||||
request: EventRequest::Disable(event_u32),
|
||||
token,
|
||||
let user_data = tc.user_data();
|
||||
let event_u32 =
|
||||
EventU32::from(u32::from_be_bytes(user_data[0..4].try_into().unwrap()));
|
||||
let start_token = self
|
||||
.service_helper
|
||||
.common
|
||||
.verif_reporter
|
||||
.start_success(
|
||||
&self.service_helper.common.tm_sender,
|
||||
ecss_tc_and_token.token,
|
||||
time_stamp,
|
||||
)
|
||||
.map_err(|_| PartialPusHandlingError::Verification);
|
||||
let partial_error = start_token.clone().err();
|
||||
let mut token: TcStateToken = ecss_tc_and_token.token.into();
|
||||
if let Ok(start_token) = start_token {
|
||||
token = start_token.into();
|
||||
}
|
||||
let event_req_with_token = if enable {
|
||||
EventRequestWithToken {
|
||||
request: EventRequest::Enable(event_u32),
|
||||
token,
|
||||
}
|
||||
} else {
|
||||
EventRequestWithToken {
|
||||
request: EventRequest::Disable(event_u32),
|
||||
token,
|
||||
}
|
||||
};
|
||||
self.event_request_tx
|
||||
.send(event_req_with_token)
|
||||
.map_err(|_| {
|
||||
PusPacketHandlingError::RequestRouting(GenericRoutingError::Send(
|
||||
GenericSendError::RxDisconnected,
|
||||
))
|
||||
})?;
|
||||
if let Some(partial_error) = partial_error {
|
||||
return Ok(PusPacketHandlerResult::RequestHandledPartialSuccess(
|
||||
partial_error,
|
||||
));
|
||||
}
|
||||
Ok(PusPacketHandlerResult::RequestHandled)
|
||||
};
|
||||
self.event_request_tx
|
||||
.send(event_req_with_token)
|
||||
.map_err(|_| {
|
||||
PusPacketHandlingError::Other("Forwarding event request failed".into())
|
||||
})?;
|
||||
if let Some(partial_error) = partial_error {
|
||||
return Ok(PusPacketHandlerResult::RequestHandledPartialSuccess(
|
||||
partial_error,
|
||||
));
|
||||
}
|
||||
Ok(PusPacketHandlerResult::RequestHandled)
|
||||
};
|
||||
let mut partial_error = None;
|
||||
let time_stamp = get_current_cds_short_timestamp(&mut partial_error);
|
||||
|
||||
match srv.unwrap() {
|
||||
Subservice::TmInfoReport
|
||||
| Subservice::TmLowSeverityReport
|
||||
| Subservice::TmMediumSeverityReport
|
||||
| Subservice::TmHighSeverityReport => {
|
||||
return Err(PusPacketHandlingError::InvalidSubservice(tc.subservice()))
|
||||
return Err(PusPacketHandlingError::RequestConversion(
|
||||
GenericConversionError::WrongService(tc.subservice()),
|
||||
))
|
||||
}
|
||||
Subservice::TcEnableEventGeneration => {
|
||||
handle_enable_disable_request(true, time_stamp)?;
|
||||
handle_enable_disable_request(true)?;
|
||||
}
|
||||
Subservice::TcDisableEventGeneration => {
|
||||
handle_enable_disable_request(false, time_stamp)?;
|
||||
handle_enable_disable_request(false)?;
|
||||
}
|
||||
Subservice::TcReportDisabledList | Subservice::TmDisabledEventsReport => {
|
||||
return Ok(PusPacketHandlerResult::SubserviceNotImplemented(
|
||||
@ -137,60 +151,70 @@ impl<
|
||||
mod tests {
|
||||
use delegate::delegate;
|
||||
use spacepackets::ecss::event::Subservice;
|
||||
use spacepackets::time::{cds, TimeWriter};
|
||||
use spacepackets::util::UnsignedEnum;
|
||||
use spacepackets::{
|
||||
ecss::{
|
||||
tc::{PusTcCreator, PusTcSecondaryHeader},
|
||||
tm::PusTmReader,
|
||||
},
|
||||
SequenceFlags, SpHeader,
|
||||
SpHeader,
|
||||
};
|
||||
use std::sync::mpsc::{self, Sender};
|
||||
|
||||
use crate::pus::event_man::EventRequest;
|
||||
use crate::pus::tests::SimplePusPacketHandler;
|
||||
use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
|
||||
use crate::pus::verification::{
|
||||
RequestId, VerificationReporterWithSharedPoolMpscBoundedSender,
|
||||
RequestId, VerificationReporter, VerificationReportingProvider,
|
||||
};
|
||||
use crate::pus::{MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc};
|
||||
use crate::pus::{GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSenderBounded};
|
||||
use crate::{
|
||||
events::EventU32,
|
||||
pus::{
|
||||
event_man::EventRequestWithToken,
|
||||
tests::{PusServiceHandlerWithSharedStoreCommon, PusTestHarness, TEST_APID},
|
||||
tests::PusServiceHandlerWithSharedStoreCommon,
|
||||
verification::{TcStateAccepted, VerificationToken},
|
||||
EcssTcInSharedStoreConverter, PusPacketHandlerResult, PusPacketHandlingError,
|
||||
},
|
||||
};
|
||||
|
||||
use super::PusService5EventHandler;
|
||||
use super::PusEventServiceHandler;
|
||||
|
||||
const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25);
|
||||
|
||||
struct Pus5HandlerWithStoreTester {
|
||||
common: PusServiceHandlerWithSharedStoreCommon,
|
||||
handler: PusService5EventHandler<
|
||||
handler: PusEventServiceHandler<
|
||||
MpscTcReceiver,
|
||||
TmInSharedPoolSenderWithBoundedMpsc,
|
||||
MpscTmInSharedPoolSenderBounded,
|
||||
EcssTcInSharedStoreConverter,
|
||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
||||
VerificationReporter,
|
||||
>,
|
||||
}
|
||||
|
||||
impl Pus5HandlerWithStoreTester {
|
||||
pub fn new(event_request_tx: Sender<EventRequestWithToken>) -> Self {
|
||||
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
|
||||
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0);
|
||||
Self {
|
||||
common,
|
||||
handler: PusService5EventHandler::new(srv_handler, event_request_tx),
|
||||
handler: PusEventServiceHandler::new(srv_handler, event_request_tx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PusTestHarness for Pus5HandlerWithStoreTester {
|
||||
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||
self.handler
|
||||
.service_helper
|
||||
.verif_reporter()
|
||||
.acceptance_success(self.handler.service_helper.tm_sender(), init_token, &[0; 7])
|
||||
.expect("acceptance success failure")
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
||||
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_no_tm_available(&self) -> bool;
|
||||
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
||||
@ -200,10 +224,9 @@ mod tests {
|
||||
}
|
||||
|
||||
impl SimplePusPacketHandler for Pus5HandlerWithStoreTester {
|
||||
delegate! {
|
||||
to self.handler {
|
||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError>;
|
||||
}
|
||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||
self.handler.poll_and_handle_next_tc(&time_stamp)
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,15 +236,16 @@ mod tests {
|
||||
expected_event_req: EventRequest,
|
||||
event_req_receiver: mpsc::Receiver<EventRequestWithToken>,
|
||||
) {
|
||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||
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();
|
||||
let ping_tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
|
||||
let token = test_harness.init_verification(&ping_tc);
|
||||
test_harness.send_tc(&token, &ping_tc);
|
||||
let request_id = token.request_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);
|
||||
@ -274,10 +298,11 @@ mod tests {
|
||||
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 sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||
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 ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
|
||||
let token = test_harness.init_verification(&ping_tc);
|
||||
test_harness.send_tc(&token, &ping_tc);
|
||||
let result = test_harness.handle_one_tc();
|
||||
assert!(result.is_ok());
|
||||
let result = result.unwrap();
|
||||
@ -292,15 +317,19 @@ mod tests {
|
||||
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 sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
|
||||
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 ping_tc = PusTcCreator::new(sp_header, sec_header, &[0, 1, 2], true);
|
||||
let token = test_harness.init_verification(&ping_tc);
|
||||
test_harness.send_tc(&token, &ping_tc);
|
||||
let result = test_harness.handle_one_tc();
|
||||
assert!(result.is_err());
|
||||
let result = result.unwrap_err();
|
||||
if let PusPacketHandlingError::NotEnoughAppData { expected, found } = result {
|
||||
if let PusPacketHandlingError::RequestConversion(
|
||||
GenericConversionError::NotEnoughAppData { expected, found },
|
||||
) = result
|
||||
{
|
||||
assert_eq!(expected, 4);
|
||||
assert_eq!(found, 3);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user