now only tests are missing
Some checks failed
Rust/sat-rs/pipeline/head There was a failure building this commit

This commit is contained in:
Robin Müller 2024-04-29 23:22:20 +02:00
parent b4fbdba8a0
commit 6b3fd931be
Signed by: muellerr
GPG Key ID: A649FB78196E3849
4 changed files with 238 additions and 104 deletions

View File

@ -2,7 +2,6 @@ use std::sync::mpsc::{self};
use crate::pus::create_verification_reporter;
use satrs::event_man::{EventMessageU32, EventRoutingError};
use satrs::params::WritableToBeBytes;
use satrs::pus::event::EventTmHookProvider;
use satrs::pus::verification::VerificationReporter;
use satrs::pus::EcssTmSender;
@ -42,6 +41,7 @@ pub struct PusEventHandler<TmSender: EcssTmSender> {
tm_sender: TmSender,
time_provider: CdsTime,
timestamp: [u8; 7],
small_data_buf: [u8; 64],
verif_handler: VerificationReporter,
}
@ -82,6 +82,7 @@ impl<TmSender: EcssTmSender> PusEventHandler<TmSender> {
pus_event_man_rx,
time_provider: CdsTime::new_with_u16_days(0, 0),
timestamp: [0; 7],
small_data_buf: [0; 64],
verif_handler,
tm_sender,
}
@ -132,19 +133,17 @@ impl<TmSender: EcssTmSender> PusEventHandler<TmSender> {
// Perform the generation of PUS event packets
match self.pus_event_man_rx.try_recv() {
Ok(event_msg) => {
update_time(&mut self.time_provider, &mut self.timestamp);
let param_vec = event_msg.params().map_or(Vec::new(), |param| {
param.to_vec().expect("failed to convert params to vec")
});
// We use the TM modification hook to set the sender APID for each event.
self.pus_event_tm_creator.reporter.tm_hook.next_apid =
UniqueApidTargetId::from(event_msg.sender_id()).apid;
update_time(&mut self.time_provider, &mut self.timestamp);
self.pus_event_tm_creator
.generate_pus_event_tm_generic(
.generate_pus_event_tm_generic_with_generic_params(
&self.tm_sender,
&self.timestamp,
event_msg.event(),
Some(&param_vec),
&mut self.small_data_buf,
event_msg.params(),
)
.expect("Sending TM as event failed");
}

View File

@ -1,12 +1,12 @@
use log::{error, warn};
use satrs::action::{ActionRequest, ActionRequestVariant};
use satrs::params::WritableToBeBytes;
use satrs::pool::SharedStaticMemoryPool;
use satrs::pus::action::{
ActionReplyPus, ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap,
};
use satrs::pus::verification::{
FailParams, FailParamsWithStep, TcStateAccepted, TcStateStarted, VerificationReporter,
handle_completion_failure_with_error_as_params, handle_step_failure_with_error_as_params,
FailParams, TcStateAccepted, TcStateStarted, VerificationReporter,
VerificationReportingProvider, VerificationToken,
};
use satrs::pus::{
@ -61,7 +61,7 @@ impl PusReplyHandler<ActivePusActionRequestStd, ActionReplyPus> for ActionReplyH
active_request: &ActivePusActionRequestStd,
tm_sender: &(impl EcssTmSender + ?Sized),
verification_handler: &impl VerificationReportingProvider,
time_stamp: &[u8],
timestamp: &[u8],
) -> Result<bool, Self::Error> {
let verif_token: VerificationToken<TcStateStarted> = active_request
.token()
@ -69,15 +69,21 @@ impl PusReplyHandler<ActivePusActionRequestStd, ActionReplyPus> for ActionReplyH
.expect("invalid token state");
let remove_entry = match &reply.message.variant {
ActionReplyVariant::CompletionFailed { error_code, params } => {
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(
let error_propagated = handle_completion_failure_with_error_as_params(
tm_sender,
verif_token,
FailParams::new(time_stamp, error_code, &self.fail_data_buf[..fail_data_len]),
verification_handler,
timestamp,
error_code,
&mut self.fail_data_buf,
params.as_ref(),
)?;
if !error_propagated {
log::warn!(
"error params for completion failure were not propated: {:?}",
params.as_ref()
);
}
true
}
ActionReplyVariant::StepFailed {
@ -85,31 +91,33 @@ impl PusReplyHandler<ActivePusActionRequestStd, ActionReplyPus> for ActionReplyH
step,
params,
} => {
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(
let error_propagated = handle_step_failure_with_error_as_params(
tm_sender,
verif_token,
FailParamsWithStep::new(
time_stamp,
&EcssEnumU16::new(*step),
error_code,
&self.fail_data_buf[..fail_data_len],
),
verification_handler,
timestamp,
&EcssEnumU16::new(*step),
error_code,
&mut self.fail_data_buf,
params.as_ref(),
)?;
if !error_propagated {
log::warn!(
"error params for completion failure were not propated: {:?}",
params.as_ref()
);
}
true
}
ActionReplyVariant::Completed => {
verification_handler.completion_success(tm_sender, verif_token, time_stamp)?;
verification_handler.completion_success(tm_sender, verif_token, timestamp)?;
true
}
ActionReplyVariant::StepSuccess { step } => {
verification_handler.step_success(
tm_sender,
&verif_token,
time_stamp,
timestamp,
EcssEnumU16::new(*step),
)?;
false

View File

@ -107,6 +107,7 @@ pub mod alloc_mod {
use crate::{
events::EventU16,
params::{Params, WritableToBeBytes},
pus::event::{DummyEventHook, EventTmHookProvider},
};
@ -147,6 +148,12 @@ pub mod alloc_mod {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct EventGenerationResult {
pub event_was_enabled: bool,
pub params_were_propagated: bool,
}
pub struct PusEventTmCreatorWithMap<
ReportingMap: PusEventReportingMapProvider<Event>,
Event: GenericEvent,
@ -212,6 +219,53 @@ pub mod alloc_mod {
.map_err(|e| e.into()),
}
}
pub fn generate_pus_event_tm_generic_with_generic_params(
&self,
sender: &(impl EcssTmSender + ?Sized),
time_stamp: &[u8],
event: Event,
small_data_buf: &mut [u8],
params: Option<&Params>,
) -> Result<EventGenerationResult, EventManError> {
let mut result = EventGenerationResult {
event_was_enabled: false,
params_were_propagated: true,
};
if params.is_none() {
result.event_was_enabled =
self.generate_pus_event_tm_generic(sender, time_stamp, event, None)?;
return Ok(result);
}
let params = params.unwrap();
result.event_was_enabled = match params {
Params::Heapless(heapless_param) => {
heapless_param
.write_to_be_bytes(&mut small_data_buf[..heapless_param.written_len()])
.map_err(EcssTmtcError::ByteConversion)?;
self.generate_pus_event_tm_generic(
sender,
time_stamp,
event,
Some(small_data_buf),
)?
}
Params::Vec(vec) => {
self.generate_pus_event_tm_generic(sender, time_stamp, event, Some(vec))?
}
Params::String(string) => self.generate_pus_event_tm_generic(
sender,
time_stamp,
event,
Some(string.as_bytes()),
)?,
_ => {
result.params_were_propagated = false;
self.generate_pus_event_tm_generic(sender, time_stamp, event, None)?
}
};
Ok(result)
}
}
impl<Event: GenericEvent + Copy + PartialEq + Eq + Hash, EventTmHook: EventTmHookProvider>
@ -336,4 +390,9 @@ mod tests {
assert!(event_sent);
event_rx.try_recv().expect("No info event received");
}
#[test]
fn test_event_with_generic_params() {
// TODO: Test this.
}
}

View File

@ -79,6 +79,7 @@
//! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs)
//! for the verification module contains examples how this module could be used in a more complex
//! context involving multiple threads
use crate::params::{Params, WritableToBeBytes};
use crate::pus::{source_buffer_large_enough, EcssTmSender, EcssTmtcError};
use core::fmt::{Debug, Display, Formatter};
use core::hash::{Hash, Hasher};
@ -1171,26 +1172,139 @@ pub mod alloc_mod {
}
}
/*
#[cfg(feature = "std")]
pub mod std_mod {
use std::sync::mpsc;
use crate::pool::StoreAddr;
use crate::pus::verification::VerificationReporterWithSender;
use super::alloc_mod::VerificationReporterWithSharedPoolSender;
pub type VerificationReporterWithSharedPoolMpscSender =
VerificationReporterWithSharedPoolSender<mpsc::Sender<StoreAddr>>;
pub type VerificationReporterWithSharedPoolMpscBoundedSender =
VerificationReporterWithSharedPoolSender<mpsc::SyncSender<StoreAddr>>;
pub type VerificationReporterWithVecMpscSender =
VerificationReporterWithSender<mpsc::Sender<alloc::vec::Vec<u8>>>;
pub type VerificationReporterWithVecMpscBoundedSender =
VerificationReporterWithSender<mpsc::SyncSender<alloc::vec::Vec<u8>>>;
/// This helper function simplifies generating completion failures where the error data has
/// the generic [Params] type.
///
/// A small data buffer needs to be supplied for the [Params::Heapless] type because all data
/// suplied as error data must be held in a slice. Passing a static buffer avoids dynamic memory
/// allocation for this case.
///
/// Please note that this specific function can not propagate the [Params::Store] variant.
/// This function also might not be able to propagate other error variants which are added in
/// the future. The returned boolean on success denotes whether the error parameters were
/// propagated properly.
pub fn handle_completion_failure_with_error_as_params<TcState: WasAtLeastAccepted + Copy>(
tm_sender: &(impl EcssTmSender + ?Sized),
verif_token: VerificationToken<TcState>,
verif_reporter: &impl VerificationReportingProvider,
timestamp: &[u8],
error_code: &impl EcssEnumeration,
small_data_buf: &mut [u8],
error_params: Option<&Params>,
) -> Result<bool, EcssTmtcError> {
let mut error_params_propagated = true;
if error_params.is_none() {
verif_reporter.completion_failure(
tm_sender,
verif_token,
FailParams::new(timestamp, error_code, &[]),
)?;
return Ok(true);
}
let error_params = error_params.unwrap();
match error_params {
Params::Heapless(heapless_param) => {
heapless_param
.write_to_be_bytes(&mut small_data_buf[..heapless_param.written_len()])?;
verif_reporter.completion_failure(
tm_sender,
verif_token,
FailParams::new(
timestamp,
error_code,
&small_data_buf[..heapless_param.written_len()],
),
)?;
}
Params::Vec(vec) => {
verif_reporter.completion_failure(
tm_sender,
verif_token,
FailParams::new(timestamp, error_code, vec),
)?;
}
Params::String(str) => {
verif_reporter.completion_failure(
tm_sender,
verif_token,
FailParams::new(timestamp, error_code, str.as_bytes()),
)?;
}
_ => {
verif_reporter.completion_failure(
tm_sender,
verif_token,
FailParams::new(timestamp, error_code, &[]),
)?;
error_params_propagated = false;
}
}
Ok(error_params_propagated)
}
/// This function is similar to [handle_completion_failure_with_error_as_params] but handles the
/// step failure case.
#[allow(clippy::too_many_arguments)]
pub fn handle_step_failure_with_error_as_params(
tm_sender: &(impl EcssTmSender + ?Sized),
verif_token: VerificationToken<TcStateStarted>,
verif_reporter: &impl VerificationReportingProvider,
timestamp: &[u8],
step: &impl EcssEnumeration,
error_code: &impl EcssEnumeration,
small_data_buf: &mut [u8],
error_params: Option<&Params>,
) -> Result<bool, EcssTmtcError> {
if error_params.is_none() {
verif_reporter.step_failure(
tm_sender,
verif_token,
FailParamsWithStep::new(timestamp, step, error_code, &[]),
)?;
return Ok(true);
}
let error_params = error_params.unwrap();
let mut error_params_propagated = true;
match error_params {
Params::Heapless(heapless_param) => {
heapless_param
.write_to_be_bytes(&mut small_data_buf[..heapless_param.written_len()])?;
verif_reporter.step_failure(
tm_sender,
verif_token,
FailParamsWithStep::new(
timestamp,
step,
error_code,
&small_data_buf[..heapless_param.written_len()],
),
)?;
}
Params::Vec(vec) => {
verif_reporter.step_failure(
tm_sender,
verif_token,
FailParamsWithStep::new(timestamp, step, error_code, vec),
)?;
}
Params::String(str) => {
verif_reporter.step_failure(
tm_sender,
verif_token,
FailParamsWithStep::new(timestamp, step, error_code, str.as_bytes()),
)?;
}
_ => {
verif_reporter.step_failure(
tm_sender,
verif_token,
FailParamsWithStep::new(timestamp, step, error_code, &[]),
)?;
error_params_propagated = false;
}
}
Ok(error_params_propagated)
}
*/
#[cfg(any(feature = "test_util", test))]
pub mod test_util {
@ -1566,62 +1680,6 @@ pub mod test_util {
.pop_front()
.expect("report queue is empty")
}
/*
pub fn verification_info(&self, req_id: &RequestId) -> Option<VerificationStatus> {
let verif_map = self.verification_map.lock().unwrap();
let value = verif_map.borrow().get(req_id).cloned();
value
}
pub fn check_started(&self, req_id: &RequestId) -> bool {
let verif_map = self.verification_map.lock().unwrap();
if let Some(entry) = verif_map.borrow().get(req_id) {
return entry.started.unwrap_or(false);
}
false
}
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_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");
}
*/
}
}
@ -2369,4 +2427,14 @@ pub mod tests {
.expect("Sending completion success failed");
testbench.completion_success_check(true);
}
#[test]
fn test_completion_failure_helper() {
// TODO: Add tests for this.
}
#[test]
fn test_step_failure_helper() {
// TODO: Add tests for this.
}
}