diff --git a/satrs-example/src/events.rs b/satrs-example/src/events.rs index cb0caf8..8f4bd08 100644 --- a/satrs-example/src/events.rs +++ b/satrs-example/src/events.rs @@ -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 { tm_sender: TmSender, time_provider: CdsTime, timestamp: [u8; 7], + small_data_buf: [u8; 64], verif_handler: VerificationReporter, } @@ -82,6 +82,7 @@ impl PusEventHandler { 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,21 +133,26 @@ impl PusEventHandler { // 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; - self.pus_event_tm_creator - .generate_pus_event_tm_generic( + update_time(&mut self.time_provider, &mut self.timestamp); + let generation_result = self + .pus_event_tm_creator + .generate_pus_event_tm_generic_with_generic_params( &self.tm_sender, &self.timestamp, event_msg.event(), - Some(¶m_vec), + &mut self.small_data_buf, + event_msg.params(), ) .expect("Sending TM as event failed"); + if !generation_result.params_were_propagated { + log::warn!( + "Event TM parameters were not propagated: {:?}", + event_msg.params() + ); + } } Err(e) => match e { mpsc::TryRecvError::Empty => break, diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index dcdb345..7f4e76f 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -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_generic_params, handle_step_failure_with_generic_params, + FailParamHelper, FailParams, TcStateAccepted, TcStateStarted, VerificationReporter, VerificationReportingProvider, VerificationToken, }; use satrs::pus::{ @@ -61,7 +61,7 @@ impl PusReplyHandler for ActionReplyH active_request: &ActivePusActionRequestStd, tm_sender: &(impl EcssTmSender + ?Sized), verification_handler: &impl VerificationReportingProvider, - time_stamp: &[u8], + timestamp: &[u8], ) -> Result { let verif_token: VerificationToken = active_request .token() @@ -69,15 +69,23 @@ impl PusReplyHandler 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_generic_params( tm_sender, verif_token, - FailParams::new(time_stamp, error_code, &self.fail_data_buf[..fail_data_len]), + verification_handler, + FailParamHelper { + error_code, + params: params.as_ref(), + timestamp, + small_data_buf: &mut self.fail_data_buf, + }, )?; + if !error_propagated { + log::warn!( + "error params for completion failure were not propated: {:?}", + params.as_ref() + ); + } true } ActionReplyVariant::StepFailed { @@ -85,31 +93,35 @@ impl PusReplyHandler 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_generic_params( tm_sender, verif_token, - FailParamsWithStep::new( - time_stamp, - &EcssEnumU16::new(*step), + verification_handler, + FailParamHelper { error_code, - &self.fail_data_buf[..fail_data_len], - ), + params: params.as_ref(), + timestamp, + small_data_buf: &mut self.fail_data_buf, + }, + &EcssEnumU16::new(*step), )?; + 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 diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs index 6e5ec37..75b5be3 100644 --- a/satrs-example/src/pus/mod.rs +++ b/satrs-example/src/pus/mod.rs @@ -439,20 +439,17 @@ where return Ok(()); } let active_request = active_req_opt.unwrap(); - let request_finished = self - .reply_handler - .handle_reply( - reply, - active_request, - &self.service_helper.common.tm_sender, - &self.service_helper.common.verif_reporter, - time_stamp, - ) - .unwrap_or(false); - if request_finished { + let result = self.reply_handler.handle_reply( + reply, + active_request, + &self.service_helper.common.tm_sender, + &self.service_helper.common.verif_reporter, + time_stamp, + ); + if result.is_err() || (result.is_ok() && *result.as_ref().unwrap()) { self.active_request_map.remove(reply.request_id()); } - Ok(()) + result.map(|_| ()) } pub fn check_for_request_timeouts(&mut self) { diff --git a/satrs/Cargo.toml b/satrs/Cargo.toml index 94f8e79..92b753d 100644 --- a/satrs/Cargo.toml +++ b/satrs/Cargo.toml @@ -15,6 +15,7 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup [dependencies] delegate = ">0.7, <=0.10" paste = "1" +derive-new = "0.6" smallvec = "1" crc = "3" diff --git a/satrs/src/params.rs b/satrs/src/params.rs index da770eb..63135c5 100644 --- a/satrs/src/params.rs +++ b/satrs/src/params.rs @@ -643,52 +643,18 @@ impl From<&str> for Params { } } -/// Please note while [WritableToBeBytes] is implemented for [Params], the default implementation -/// will not be able to process the [Params::Store] parameter variant. -impl WritableToBeBytes for Params { +impl WritableToBeBytes for ParamsHeapless { fn written_len(&self) -> usize { match self { - Params::Heapless(p) => match p { - ParamsHeapless::Raw(raw) => raw.written_len(), - ParamsHeapless::EcssEnum(enumeration) => enumeration.written_len(), - }, - Params::Store(_) => 0, - #[cfg(feature = "alloc")] - Params::Vec(vec) => vec.len(), - #[cfg(feature = "alloc")] - Params::String(string) => string.len(), + ParamsHeapless::Raw(raw) => raw.written_len(), + ParamsHeapless::EcssEnum(ecss_enum) => ecss_enum.written_len(), } } fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { match self { - Params::Heapless(p) => match p { - ParamsHeapless::Raw(raw) => raw.write_to_be_bytes(buf), - ParamsHeapless::EcssEnum(enumeration) => enumeration.write_to_be_bytes(buf), - }, - Params::Store(_) => Ok(0), - #[cfg(feature = "alloc")] - Params::Vec(vec) => { - if buf.len() < vec.len() { - return Err(ByteConversionError::ToSliceTooSmall { - found: buf.len(), - expected: vec.len(), - }); - } - buf[0..vec.len()].copy_from_slice(vec); - Ok(vec.len()) - } - #[cfg(feature = "alloc")] - Params::String(string) => { - if buf.len() < string.len() { - return Err(ByteConversionError::ToSliceTooSmall { - found: buf.len(), - expected: string.len(), - }); - } - buf[0..string.len()].copy_from_slice(string.as_bytes()); - Ok(string.len()) - } + ParamsHeapless::Raw(raw) => raw.write_to_be_bytes(buf), + ParamsHeapless::EcssEnum(ecss_enum) => ecss_enum.write_to_be_bytes(buf), } } } @@ -837,10 +803,9 @@ mod tests { #[test] fn test_params_written_len_raw() { let param_raw = ParamsRaw::from((500_u32, 1000_u32)); - let param: Params = Params::Heapless(param_raw.into()); - assert_eq!(param.written_len(), 8); + assert_eq!(param_raw.written_len(), 8); let mut buf: [u8; 8] = [0; 8]; - param + param_raw .write_to_be_bytes(&mut buf) .expect("writing to buffer failed"); assert_eq!(u32::from_be_bytes(buf[0..4].try_into().unwrap()), 500); @@ -848,21 +813,28 @@ mod tests { } #[test] - fn test_params_written_string() { - let string = "Test String".to_string(); - let param = Params::String(string.clone()); - assert_eq!(param.written_len(), string.len()); - let vec = param.to_vec().unwrap(); - let string_conv_back = String::from_utf8(vec).expect("conversion to string failed"); - assert_eq!(string_conv_back, string); + fn test_heapless_param_writable_trait_raw() { + let param_heapless = ParamsHeapless::Raw(ParamsRaw::from((500_u32, 1000_u32))); + assert_eq!(param_heapless.written_len(), 8); + let mut buf: [u8; 8] = [0; 8]; + let size = param_heapless + .write_to_be_bytes(&mut buf) + .expect("writing failed"); + assert_eq!(size, 8); + assert_eq!(u32::from_be_bytes(buf[0..4].try_into().unwrap()), 500); + assert_eq!(u32::from_be_bytes(buf[4..8].try_into().unwrap()), 1000); } #[test] - fn test_params_written_vec() { - let vec: Vec = alloc::vec![1, 2, 3, 4, 5]; - let param = Params::Vec(vec.clone()); - assert_eq!(param.written_len(), vec.len()); - assert_eq!(param.to_vec().expect("writing vec params failed"), vec); + fn test_heapless_param_writable_trait_ecss_enum() { + let param_heapless = ParamsHeapless::EcssEnum(ParamsEcssEnum::U16(5.into())); + assert_eq!(param_heapless.written_len(), 2); + let mut buf: [u8; 2] = [0; 2]; + let size = param_heapless + .write_to_be_bytes(&mut buf) + .expect("writing failed"); + assert_eq!(size, 2); + assert_eq!(u16::from_be_bytes(buf[0..2].try_into().unwrap()), 5); } #[test] diff --git a/satrs/src/pus/event.rs b/satrs/src/pus/event.rs index 578167f..a6301e2 100644 --- a/satrs/src/pus/event.rs +++ b/satrs/src/pus/event.rs @@ -407,7 +407,7 @@ mod tests { severity_to_subservice(severity) as u8 ); assert_eq!(tm_info.common.dest_id, 0); - assert_eq!(tm_info.common.time_stamp, time_stamp_empty); + assert_eq!(tm_info.common.timestamp, time_stamp_empty); assert_eq!(tm_info.common.msg_counter, 0); assert_eq!(tm_info.common.apid, EXAMPLE_APID); assert_eq!(tm_info.event, event); diff --git a/satrs/src/pus/event_man.rs b/satrs/src/pus/event_man.rs index c8aec2d..ed8238c 100644 --- a/satrs/src/pus/event_man.rs +++ b/satrs/src/pus/event_man.rs @@ -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: 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 { + 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 @@ -261,6 +315,12 @@ pub mod alloc_mod { } #[cfg(test)] mod tests { + use alloc::string::{String, ToString}; + use alloc::vec; + use spacepackets::ecss::event::Subservice; + use spacepackets::ecss::tm::PusTmReader; + use spacepackets::ecss::PusPacket; + use super::*; use crate::request::UniqueApidTargetId; use crate::{events::SeverityInfo, tmtc::PacketAsVec}; @@ -336,4 +396,70 @@ mod tests { assert!(event_sent); event_rx.try_recv().expect("No info event received"); } + + #[test] + fn test_event_with_generic_string_param() { + let event_man = create_basic_man_1(); + let mut small_data_buf = [0; 128]; + let param_data = "hello world"; + let (event_tx, event_rx) = mpsc::channel::(); + let res = event_man.generate_pus_event_tm_generic_with_generic_params( + &event_tx, + &EMPTY_STAMP, + INFO_EVENT.into(), + &mut small_data_buf, + Some(¶m_data.to_string().into()), + ); + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(res.event_was_enabled); + assert!(res.params_were_propagated); + let event_tm = event_rx.try_recv().expect("no event received"); + let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed"); + assert_eq!(tm.service(), 5); + assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8); + assert_eq!(tm.user_data().len(), 4 + param_data.len()); + let u32_event = u32::from_be_bytes(tm.user_data()[0..4].try_into().unwrap()); + assert_eq!(u32_event, INFO_EVENT.raw()); + let string_data = String::from_utf8_lossy(&tm.user_data()[4..]); + assert_eq!(string_data, param_data); + } + + #[test] + fn test_event_with_generic_vec_param() { + let event_man = create_basic_man_1(); + let mut small_data_buf = [0; 128]; + let param_data = vec![1, 2, 3, 4]; + let (event_tx, event_rx) = mpsc::channel::(); + let res = event_man.generate_pus_event_tm_generic_with_generic_params( + &event_tx, + &EMPTY_STAMP, + INFO_EVENT.into(), + &mut small_data_buf, + Some(¶m_data.clone().into()), + ); + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(res.event_was_enabled); + assert!(res.params_were_propagated); + let event_tm = event_rx.try_recv().expect("no event received"); + let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed"); + assert_eq!(tm.service(), 5); + assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8); + assert_eq!(tm.user_data().len(), 4 + param_data.len()); + let u32_event = u32::from_be_bytes(tm.user_data()[0..4].try_into().unwrap()); + assert_eq!(u32_event, INFO_EVENT.raw()); + let vec_data = tm.user_data()[4..].to_vec(); + assert_eq!(vec_data, param_data); + } + + #[test] + fn test_event_with_generic_store_param_not_propagated() { + // TODO: Test this. + } + + #[test] + fn test_event_with_generic_heapless_param() { + // TODO: Test this. + } } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 78caa4d..4a76757 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -1284,36 +1284,46 @@ pub mod tests { pub seq_count: u16, pub msg_counter: u16, pub dest_id: u16, - pub time_stamp: [u8; 7], + pub timestamp: Vec, } impl CommonTmInfo { - pub fn new_zero_seq_count( + pub fn new( subservice: u8, apid: u16, + seq_count: u16, + msg_counter: u16, dest_id: u16, - time_stamp: [u8; 7], + timestamp: &[u8], ) -> Self { Self { subservice, apid, - seq_count: 0, - msg_counter: 0, + seq_count, + msg_counter, dest_id, - time_stamp, + timestamp: timestamp.to_vec(), } } + pub fn new_zero_seq_count( + subservice: u8, + apid: u16, + dest_id: u16, + timestamp: &[u8], + ) -> Self { + Self::new(subservice, apid, 0, 0, dest_id, timestamp) + } pub fn new_from_tm(tm: &PusTmCreator) -> Self { - let mut time_stamp = [0; 7]; - time_stamp.clone_from_slice(&tm.timestamp()[0..7]); + let mut timestamp = [0; 7]; + timestamp.clone_from_slice(&tm.timestamp()[0..7]); Self { subservice: PusPacket::subservice(tm), apid: tm.apid(), seq_count: tm.seq_count(), msg_counter: tm.msg_counter(), dest_id: tm.dest_id(), - time_stamp, + timestamp: timestamp.to_vec(), } } } diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index 2f81e41..81358a4 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -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}; @@ -353,7 +354,7 @@ pub struct FailParams<'stamp, 'fargs> { impl<'stamp, 'fargs> FailParams<'stamp, 'fargs> { pub fn new( time_stamp: &'stamp [u8], - failure_code: &'fargs impl EcssEnumeration, + failure_code: &'fargs dyn EcssEnumeration, failure_data: &'fargs [u8], ) -> Self { Self { @@ -381,7 +382,7 @@ impl<'stamp, 'fargs> FailParamsWithStep<'stamp, 'fargs> { pub fn new( time_stamp: &'stamp [u8], step: &'fargs impl EcssEnumeration, - failure_code: &'fargs impl EcssEnumeration, + failure_code: &'fargs dyn EcssEnumeration, failure_data: &'fargs [u8], ) -> Self { Self { @@ -1171,26 +1172,143 @@ 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>; - pub type VerificationReporterWithSharedPoolMpscBoundedSender = - VerificationReporterWithSharedPoolSender>; - pub type VerificationReporterWithVecMpscSender = - VerificationReporterWithSender>>; - pub type VerificationReporterWithVecMpscBoundedSender = - VerificationReporterWithSender>>; +pub struct FailParamHelper<'stamp, 'fargs, 'buf, 'params> { + pub timestamp: &'stamp [u8], + pub error_code: &'fargs dyn EcssEnumeration, + pub small_data_buf: &'buf mut [u8], + pub params: Option<&'params Params>, +} + +/// 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_generic_params( + tm_sender: &(impl EcssTmSender + ?Sized), + verif_token: VerificationToken, + verif_reporter: &impl VerificationReportingProvider, + helper: FailParamHelper, +) -> Result { + let mut error_params_propagated = true; + if helper.params.is_none() { + verif_reporter.completion_failure( + tm_sender, + verif_token, + FailParams::new(helper.timestamp, helper.error_code, &[]), + )?; + return Ok(true); + } + let error_params = helper.params.unwrap(); + match error_params { + Params::Heapless(heapless_param) => { + heapless_param + .write_to_be_bytes(&mut helper.small_data_buf[..heapless_param.written_len()])?; + verif_reporter.completion_failure( + tm_sender, + verif_token, + FailParams::new( + helper.timestamp, + helper.error_code, + &helper.small_data_buf[..heapless_param.written_len()], + ), + )?; + } + #[cfg(feature = "alloc")] + Params::Vec(vec) => { + verif_reporter.completion_failure( + tm_sender, + verif_token, + FailParams::new(helper.timestamp, helper.error_code, vec), + )?; + } + #[cfg(feature = "alloc")] + Params::String(str) => { + verif_reporter.completion_failure( + tm_sender, + verif_token, + FailParams::new(helper.timestamp, helper.error_code, str.as_bytes()), + )?; + } + _ => { + verif_reporter.completion_failure( + tm_sender, + verif_token, + FailParams::new(helper.timestamp, helper.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. +pub fn handle_step_failure_with_generic_params( + tm_sender: &(impl EcssTmSender + ?Sized), + verif_token: VerificationToken, + verif_reporter: &impl VerificationReportingProvider, + helper: FailParamHelper, + step: &impl EcssEnumeration, +) -> Result { + if helper.params.is_none() { + verif_reporter.step_failure( + tm_sender, + verif_token, + FailParamsWithStep::new(helper.timestamp, step, helper.error_code, &[]), + )?; + return Ok(true); + } + let error_params = helper.params.unwrap(); + let mut error_params_propagated = true; + match error_params { + Params::Heapless(heapless_param) => { + heapless_param + .write_to_be_bytes(&mut helper.small_data_buf[..heapless_param.written_len()])?; + verif_reporter.step_failure( + tm_sender, + verif_token, + FailParamsWithStep::new( + helper.timestamp, + step, + helper.error_code, + &helper.small_data_buf[..heapless_param.written_len()], + ), + )?; + } + #[cfg(feature = "alloc")] + Params::Vec(vec) => { + verif_reporter.step_failure( + tm_sender, + verif_token, + FailParamsWithStep::new(helper.timestamp, step, helper.error_code, vec), + )?; + } + #[cfg(feature = "alloc")] + Params::String(str) => { + verif_reporter.step_failure( + tm_sender, + verif_token, + FailParamsWithStep::new(helper.timestamp, step, helper.error_code, str.as_bytes()), + )?; + } + _ => { + verif_reporter.step_failure( + tm_sender, + verif_token, + FailParamsWithStep::new(helper.timestamp, step, helper.error_code, &[]), + )?; + error_params_propagated = false; + } + } + Ok(error_params_propagated) } - */ #[cfg(any(feature = "test_util", test))] pub mod test_util { @@ -1566,73 +1684,19 @@ pub mod test_util { .pop_front() .expect("report queue is empty") } - /* - pub fn verification_info(&self, req_id: &RequestId) -> Option { - 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, - 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, - 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 { - 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"); - } - */ } } #[cfg(test)] pub mod tests { + use crate::params::Params; use crate::pool::{SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig}; use crate::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0}; use crate::pus::tests::CommonTmInfo; use crate::pus::verification::{ - EcssTmSender, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone, - VerificationReporter, VerificationReporterCfg, VerificationToken, + handle_step_failure_with_generic_params, EcssTmSender, EcssTmtcError, FailParams, + FailParamsWithStep, RequestId, TcStateNone, VerificationReporter, VerificationReporterCfg, + VerificationToken, }; use crate::pus::{ChannelWithId, PusTmVariant}; use crate::request::MessageMetadata; @@ -1640,6 +1704,7 @@ pub mod tests { use crate::tmtc::{PacketSenderWithSharedPool, SharedPacketPool}; use crate::ComponentId; use alloc::format; + use alloc::string::ToString; use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; use spacepackets::ecss::{ EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration, PusError, PusPacket, @@ -1654,8 +1719,9 @@ pub mod tests { use std::vec::Vec; use super::{ - DummyVerificationHook, SeqCountProviderSimple, TcStateAccepted, TcStateStarted, - VerificationHookProvider, VerificationReportingProvider, WasAtLeastAccepted, + handle_completion_failure_with_generic_params, DummyVerificationHook, FailParamHelper, + SeqCountProviderSimple, TcStateAccepted, TcStateStarted, VerificationHookProvider, + VerificationReportingProvider, WasAtLeastAccepted, }; fn is_send(_: &T) {} @@ -1663,6 +1729,7 @@ pub mod tests { fn is_sync(_: &T) {} const EMPTY_STAMP: [u8; 7] = [0; 7]; + const DUMMY_STAMP: &[u8] = &[0, 1, 0, 1, 0, 1, 0]; #[derive(Debug, Eq, PartialEq, Clone)] struct TmInfo { @@ -1740,8 +1807,8 @@ pub mod tests { tc: Vec, } - fn base_reporter(id: ComponentId) -> VerificationReporter { - let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); + fn base_reporter(id: ComponentId, max_fail_data_len: usize) -> VerificationReporter { + let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, max_fail_data_len).unwrap(); VerificationReporter::new(id, &cfg) } @@ -1844,66 +1911,57 @@ pub mod tests { .completion_failure(&self.sender, token, params) } - fn completion_success_check(&mut self, incrementing_couters: bool) { - assert_eq!(self.sender.service_queue.borrow().len(), 3); - let mut current_seq_count = 0; + fn check_acceptance_success(&self, timestamp: &[u8; 7]) { let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - seq_count: current_seq_count, - msg_counter: current_seq_count, - dest_id: self.reporter.dest_id(), - time_stamp: EMPTY_STAMP, - }, + common: CommonTmInfo::new(1, TEST_APID, 0, 0, self.reporter.dest_id(), timestamp), additional_data: None, }; - let mut info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + let mut service_queue = self.sender.service_queue.borrow_mut(); + assert!(service_queue.len() >= 1); + let info = service_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); + } - if incrementing_couters { - current_seq_count += 1; - } - + fn check_start_success(&mut self, seq_count: u16, msg_counter: u16, timestamp: &[u8]) { + let mut srv_queue = self.sender.service_queue.borrow_mut(); let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo { - subservice: 3, - apid: TEST_APID, - msg_counter: current_seq_count, - seq_count: current_seq_count, - dest_id: self.reporter.dest_id(), - time_stamp: [0, 1, 0, 1, 0, 1, 0], - }, + common: CommonTmInfo::new( + 3, + TEST_APID, + seq_count, + msg_counter, + self.reporter.dest_id(), + timestamp, + ), additional_data: None, }; - info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + let info = srv_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); + } - if incrementing_couters { - current_seq_count += 1; - } + fn check_completion_success(&mut self, seq_count: u16, msg_counter: u16) { let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo { - subservice: 7, - apid: TEST_APID, - msg_counter: current_seq_count, - seq_count: current_seq_count, - dest_id: self.reporter.dest_id(), - time_stamp: EMPTY_STAMP, - }, + common: CommonTmInfo::new( + 7, + TEST_APID, + seq_count, + msg_counter, + self.reporter.dest_id(), + &EMPTY_STAMP, + ), additional_data: None, }; - info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); + let info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); assert_eq!(info, cmp_info); } } impl VerificationReporterTestbench { - fn new(id: ComponentId, tc: PusTcCreator) -> Self { - let reporter = base_reporter(id); + fn new(id: ComponentId, tc: PusTcCreator, max_fail_data_len: usize) -> Self { + let reporter = base_reporter(id, max_fail_data_len); Self { id, sender: TestSender::default(), @@ -1913,36 +1971,10 @@ pub mod tests { } } - fn acceptance_check(&self, time_stamp: &[u8; 7]) { + fn check_acceptance_failure(&mut self, timestamp: &[u8; 7]) { let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo { - subservice: 1, - apid: TEST_APID, - seq_count: 0, - msg_counter: 0, - dest_id: self.reporter.dest_id(), - time_stamp: *time_stamp, - }, - additional_data: None, - }; - let mut service_queue = self.sender.service_queue.borrow_mut(); - assert_eq!(service_queue.len(), 1); - let info = service_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - } - - fn acceptance_fail_check(&mut self, stamp_buf: [u8; 7]) { - let cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo { - subservice: 2, - seq_count: 0, - apid: TEST_APID, - msg_counter: 0, - dest_id: self.reporter.dest_id(), - time_stamp: stamp_buf, - }, + common: CommonTmInfo::new(2, TEST_APID, 0, 0, self.reporter.dest_id(), timestamp), additional_data: Some([0, 2].to_vec()), }; let service_queue = self.sender.service_queue.get_mut(); @@ -1951,12 +1983,12 @@ pub mod tests { assert_eq!(info, cmp_info); } - fn start_fail_check(&mut self, fail_data_raw: [u8; 4]) { + fn check_start_failure(&mut self, fail_data_raw: [u8; 4]) { let mut srv_queue = self.sender.service_queue.borrow_mut(); assert_eq!(srv_queue.len(), 2); let mut cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(1, TEST_APID, 0, EMPTY_STAMP), + common: CommonTmInfo::new_zero_seq_count(1, TEST_APID, 0, &EMPTY_STAMP), additional_data: None, }; let mut info = srv_queue.pop_front().unwrap(); @@ -1964,148 +1996,67 @@ pub mod tests { cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(4, TEST_APID, 0, EMPTY_STAMP), + common: CommonTmInfo::new_zero_seq_count(4, TEST_APID, 0, &EMPTY_STAMP), additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()), }; info = srv_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); } - fn step_success_check(&mut self, time_stamp: &[u8; 7]) { - let mut cmp_info = TmInfo { + fn check_step_success(&mut self, step: u8, timestamp: &[u8; 7]) { + let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(1, TEST_APID, 0, *time_stamp), - additional_data: None, + common: CommonTmInfo::new_zero_seq_count(5, TEST_APID, 0, timestamp), + additional_data: Some([step].to_vec()), }; let mut srv_queue = self.sender.service_queue.borrow_mut(); - let mut info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(3, TEST_APID, 0, *time_stamp), - additional_data: None, - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(5, TEST_APID, 0, *time_stamp), - additional_data: Some([0].to_vec()), - }; - info = srv_queue.pop_front().unwrap(); - assert_eq!(info, cmp_info); - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count(5, TEST_APID, 0, *time_stamp), - additional_data: Some([1].to_vec()), - }; - info = srv_queue.pop_front().unwrap(); + let info = srv_queue.pop_front().unwrap(); assert_eq!(info, cmp_info); } - fn check_step_failure(&mut self, fail_data_raw: [u8; 4]) { - assert_eq!(self.sender.service_queue.borrow().len(), 4); - let mut cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count( - 1, - TEST_APID, - self.reporter.dest_id(), - EMPTY_STAMP, - ), - additional_data: None, - }; - let mut info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count( - 3, - TEST_APID, - self.reporter.dest_id(), - [0, 1, 0, 1, 0, 1, 0], - ), - additional_data: None, - }; - info = self.sender.service_queue.borrow_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count( - 5, - TEST_APID, - self.reporter.dest_id(), - EMPTY_STAMP, - ), - additional_data: Some([0].to_vec()), - }; - info = self.sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { + fn check_step_failure( + &mut self, + step: &impl EcssEnumeration, + error_code: &impl EcssEnumeration, + fail_data: &[u8], + ) { + let mut additional_data = Vec::new(); + additional_data.extend(step.to_vec()); + additional_data.extend(error_code.to_vec()); + additional_data.extend(fail_data); + let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), common: CommonTmInfo::new_zero_seq_count( 6, TEST_APID, self.reporter.dest_id(), - EMPTY_STAMP, - ), - additional_data: Some( - [ - [1].as_slice(), - &[0, 0, 0x10, 0x20], - fail_data_raw.as_slice(), - ] - .concat() - .to_vec(), + &EMPTY_STAMP, ), + additional_data: Some(additional_data), }; - info = self.sender.service_queue.get_mut().pop_front().unwrap(); + let info = self.sender.service_queue.get_mut().pop_front().unwrap(); assert_eq!(info, cmp_info); } - fn completion_fail_check(&mut self) { - assert_eq!(self.sender.service_queue.borrow().len(), 3); - - let mut cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count( - 1, - TEST_APID, - self.reporter.dest_id(), - EMPTY_STAMP, - ), - additional_data: None, - }; - let mut info = self.sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { - requestor: MessageMetadata::new(self.request_id.into(), self.id), - common: CommonTmInfo::new_zero_seq_count( - 3, - TEST_APID, - self.reporter.dest_id(), - [0, 1, 0, 1, 0, 1, 0], - ), - additional_data: None, - }; - info = self.sender.service_queue.get_mut().pop_front().unwrap(); - assert_eq!(info, cmp_info); - - cmp_info = TmInfo { + fn check_completion_failure( + &mut self, + error_code: &impl EcssEnumeration, + fail_data: &[u8], + ) { + let mut additional_data = Vec::new(); + additional_data.extend(error_code.to_vec()); + additional_data.extend(fail_data); + let cmp_info = TmInfo { requestor: MessageMetadata::new(self.request_id.into(), self.id), common: CommonTmInfo::new_zero_seq_count( 8, TEST_APID, self.reporter.dest_id(), - EMPTY_STAMP, + &EMPTY_STAMP, ), - additional_data: Some([0, 0, 0x10, 0x20].to_vec()), + additional_data: Some(additional_data), }; - info = self.sender.service_queue.get_mut().pop_front().unwrap(); + let info = self.sender.service_queue.get_mut().pop_front().unwrap(); assert_eq!(info, cmp_info); } } @@ -2128,7 +2079,7 @@ pub mod tests { #[test] fn test_state() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); assert_eq!(testbench.reporter.apid(), TEST_APID); testbench.reporter.set_apid(TEST_APID + 1); assert_eq!(testbench.reporter.apid(), TEST_APID + 1); @@ -2136,43 +2087,43 @@ pub mod tests { #[test] fn test_basic_acceptance_success() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let token = testbench.init(); testbench .acceptance_success(token, &EMPTY_STAMP) .expect("sending acceptance success failed"); - testbench.acceptance_check(&EMPTY_STAMP); + testbench.check_acceptance_success(&EMPTY_STAMP); } #[test] fn test_basic_acceptance_failure() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let init_token = testbench.init(); - let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; + let timestamp = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); - let fail_params = FailParams::new_no_fail_data(stamp_buf.as_slice(), &fail_code); + let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code); testbench .acceptance_failure(init_token, fail_params) .expect("sending acceptance failure failed"); - testbench.acceptance_fail_check(stamp_buf); + testbench.check_acceptance_failure(×tamp); } #[test] fn test_basic_acceptance_failure_with_helper() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let init_token = testbench.init(); - let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; + let timestamp = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); - let fail_params = FailParams::new_no_fail_data(stamp_buf.as_slice(), &fail_code); + let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code); testbench .acceptance_failure(init_token, fail_params) .expect("sending acceptance failure failed"); - testbench.acceptance_fail_check(stamp_buf); + testbench.check_acceptance_failure(×tamp); } #[test] fn test_acceptance_fail_data_too_large() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8); let init_token = testbench.init(); let stamp_buf = [1, 2, 3, 4, 5, 6, 7]; let fail_code = EcssEnumU16::new(2); @@ -2204,7 +2155,7 @@ pub mod tests { #[test] fn test_basic_acceptance_failure_with_fail_data() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let fail_code = EcssEnumU8::new(10); let fail_data = EcssEnumU32::new(12); let mut fail_data_raw = [0; 4]; @@ -2216,7 +2167,7 @@ pub mod tests { .expect("sending acceptance failure failed"); let cmp_info = TmInfo { requestor: MessageMetadata::new(testbench.request_id.into(), testbench.id), - common: CommonTmInfo::new_zero_seq_count(2, TEST_APID, 0, EMPTY_STAMP), + common: CommonTmInfo::new_zero_seq_count(2, TEST_APID, 0, &EMPTY_STAMP), additional_data: Some([10, 0, 0, 0, 12].to_vec()), }; let mut service_queue = testbench.sender.service_queue.borrow_mut(); @@ -2227,7 +2178,7 @@ pub mod tests { #[test] fn test_start_failure() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let init_token = testbench.init(); let fail_code = EcssEnumU8::new(22); let fail_data: i32 = -12; @@ -2241,12 +2192,12 @@ pub mod tests { testbench .start_failure(accepted_token, fail_params) .expect("Start failure failure"); - testbench.start_fail_check(fail_data_raw); + testbench.check_start_failure(fail_data_raw); } #[test] fn test_start_failure_with_helper() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let token = testbench.init(); let fail_code = EcssEnumU8::new(22); let fail_data: i32 = -12; @@ -2260,12 +2211,12 @@ pub mod tests { testbench .start_failure(accepted_token, fail_params) .expect("start failure failed"); - testbench.start_fail_check(fail_data_raw); + testbench.check_start_failure(fail_data_raw); } #[test] fn test_steps_success() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let token = testbench.init(); let accepted_token = testbench .acceptance_success(token, &EMPTY_STAMP) @@ -2280,12 +2231,15 @@ pub mod tests { .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(1)) .expect("step 1 failed"); assert_eq!(testbench.sender.service_queue.borrow().len(), 4); - testbench.step_success_check(&EMPTY_STAMP); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(0, 0, &EMPTY_STAMP); + testbench.check_step_success(0, &EMPTY_STAMP); + testbench.check_step_success(1, &EMPTY_STAMP); } #[test] fn test_step_failure() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let token = testbench.init(); let fail_code = EcssEnumU32::new(0x1020); let fail_data: f32 = -22.3232; @@ -2303,7 +2257,7 @@ pub mod tests { .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); let started_token = testbench - .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) + .start_success(accepted_token, DUMMY_STAMP) .expect("Sending start success failed"); testbench .step_success(&started_token, &EMPTY_STAMP, EcssEnumU8::new(0)) @@ -2311,12 +2265,15 @@ pub mod tests { testbench .step_failure(started_token, fail_params) .expect("Step failure failed"); - testbench.check_step_failure(fail_data_raw); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(0, 0, DUMMY_STAMP); + testbench.check_step_success(0, &EMPTY_STAMP); + testbench.check_step_failure(&fail_step, &fail_code, &fail_data_raw); } #[test] fn test_completion_failure() { - let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping()); + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let token = testbench.init(); let fail_code = EcssEnumU32::new(0x1020); let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code); @@ -2325,29 +2282,34 @@ pub mod tests { .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); let started_token = testbench - .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) + .start_success(accepted_token, DUMMY_STAMP) .expect("Sending start success failed"); testbench .completion_failure(started_token, fail_params) .expect("Completion failure"); - testbench.completion_fail_check(); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(0, 0, DUMMY_STAMP); + + testbench.check_completion_failure(&fail_code, &[]); } #[test] fn test_complete_success_sequence() { let mut testbench = - VerificationReporterTestbench::new(TEST_COMPONENT_ID_0.id(), create_generic_ping()); + VerificationReporterTestbench::new(TEST_COMPONENT_ID_0.id(), create_generic_ping(), 16); let token = testbench.init(); let accepted_token = testbench .acceptance_success(token, &EMPTY_STAMP) .expect("Sending acceptance success failed"); let started_token = testbench - .start_success(accepted_token, &[0, 1, 0, 1, 0, 1, 0]) + .start_success(accepted_token, DUMMY_STAMP) .expect("Sending start success failed"); testbench .completion_success(started_token, &EMPTY_STAMP) .expect("Sending completion success failed"); - testbench.completion_success_check(false); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(0, 0, DUMMY_STAMP); + testbench.check_completion_success(0, 0); } #[test] @@ -2367,6 +2329,83 @@ pub mod tests { testbench .completion_success(started_token, &EMPTY_STAMP) .expect("Sending completion success failed"); - testbench.completion_success_check(true); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(1, 1, DUMMY_STAMP); + testbench.check_completion_success(2, 2); + } + + #[test] + fn test_completion_failure_helper_string_param() { + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32); + let token = testbench.init(); + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) + .expect("Sending acceptance success failed"); + let mut small_data_buf: [u8; 16] = [0; 16]; + let fail_code = EcssEnumU8::new(1); + let fail_data = "error 404 oh no".to_string(); + let fail_params = Params::String(fail_data.clone()); + let result = handle_completion_failure_with_generic_params( + &testbench.sender, + accepted_token, + &testbench.reporter, + FailParamHelper { + timestamp: &EMPTY_STAMP, + error_code: &fail_code, + small_data_buf: &mut small_data_buf, + params: Some(&fail_params), + }, + ); + assert!(result.unwrap()); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_completion_failure(&fail_code, fail_data.as_bytes()); + } + + #[test] + fn test_step_failure_helper_string_param() { + let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32); + let token = testbench.init(); + let accepted_token = testbench + .acceptance_success(token, &EMPTY_STAMP) + .expect("Sending acceptance success failed"); + let started_token = testbench + .start_success(accepted_token, &EMPTY_STAMP) + .expect("Sending start success failed"); + let mut small_data_buf: [u8; 16] = [0; 16]; + let step = EcssEnumU8::new(2); + let fail_code = EcssEnumU8::new(1); + let fail_data = "AAAAAAAAAAAHHHHHH".to_string(); + let fail_params = Params::String(fail_data.clone()); + let result = handle_step_failure_with_generic_params( + &testbench.sender, + started_token, + &testbench.reporter, + FailParamHelper { + timestamp: &EMPTY_STAMP, + error_code: &fail_code, + small_data_buf: &mut small_data_buf, + params: Some(&fail_params), + }, + &step, + ); + assert!(result.unwrap()); + testbench.check_acceptance_success(&EMPTY_STAMP); + testbench.check_start_success(0, 0, &EMPTY_STAMP); + testbench.check_step_failure(&step, &fail_code, fail_data.as_bytes()); + } + + #[test] + fn test_completion_failure_helper_vec_param() { + // TODO: Test this. + } + + #[test] + fn test_completion_failure_helper_raw_param() { + // TODO: Test this. + } + + #[test] + fn test_completion_failure_helper_store_param_ignored() { + // TODO: Test this. } }