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

This commit is contained in:
Robin Müller 2024-02-19 18:24:20 +01:00
parent 7f53a88068
commit c691e29070
Signed by: muellerr
GPG Key ID: A649FB78196E3849
3 changed files with 299 additions and 108 deletions

View File

@ -170,11 +170,8 @@ pub mod std_mod {
#[cfg(test)]
mod tests {
use core::cell::RefCell;
use delegate::delegate;
use alloc::{collections::VecDeque, vec::Vec};
use satrs_shared::res_code::ResultU16;
use spacepackets::{
ecss::{
tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader},
@ -186,24 +183,18 @@ mod tests {
use crate::pus::{
tests::{
PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler, TEST_APID,
PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler, TestConverter,
TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID,
},
verification::{
tests::TestVerificationReporter, FailParams, RequestId, VerificationReportingProvider,
},
EcssTcInVecConverter, GenericRoutingError, PusPacketHandlerResult, PusPacketHandlingError,
PusRoutingErrorHandler,
};
use super::*;
#[derive(Default)]
pub struct TestRouter {
pub routing_requests: RefCell<VecDeque<(TargetId, ActionRequest)>>,
pub injected_routing_failure: RefCell<Option<GenericRoutingError>>,
}
impl PusActionRequestRouter for TestRouter {
impl PusActionRequestRouter for TestRouter<ActionRequest> {
type Error = GenericRoutingError;
fn route(
@ -222,43 +213,7 @@ mod tests {
}
}
impl TestRouter {
pub fn inject_routing_error(&mut self, error: GenericRoutingError) {
*self.injected_routing_failure.borrow_mut() = Some(error);
}
}
#[derive(Default)]
struct TestRoutingErrorHandler {
pub routing_errors: RefCell<VecDeque<(TargetId, GenericRoutingError)>>,
}
impl PusRoutingErrorHandler for TestRoutingErrorHandler {
type Error = GenericRoutingError;
fn handle_error(
&self,
target_id: TargetId,
_token: VerificationToken<TcStateAccepted>,
_tc: &PusTcReader,
error: Self::Error,
_time_stamp: &[u8],
_verif_reporter: &impl VerificationReportingProvider,
) {
self.routing_errors
.borrow_mut()
.push_back((target_id, error));
}
}
#[derive(Default)]
pub struct TestConverter {
pub conversion_request: VecDeque<Vec<u8>>,
}
const APP_DATA_TOO_SHORT: ResultU16 = ResultU16::new(1, 1);
impl PusActionToRequestConverter for TestConverter {
impl PusActionToRequestConverter for TestConverter<8> {
type Error = PusPacketHandlingError;
fn convert(
&mut self,
@ -268,6 +223,7 @@ mod tests {
verif_reporter: &impl VerificationReportingProvider,
) -> Result<(TargetId, ActionRequest), Self::Error> {
self.conversion_request.push_back(tc.raw_data().to_vec());
self.check_service(tc)?;
let target_id = tc.apid();
if tc.user_data().len() < 4 {
verif_reporter
@ -308,8 +264,8 @@ mod tests {
handler: PusService8ActionHandler<
EcssTcInVecConverter,
TestVerificationReporter,
TestConverter,
TestRouter,
TestConverter<8>,
TestRouter<ActionRequest>,
TestRoutingErrorHandler,
>,
}
@ -328,6 +284,17 @@ mod tests {
),
}
}
delegate! {
to self.handler.request_converter {
pub fn check_next_conversion(&mut self, tc: &PusTcCreator);
}
}
delegate! {
to self.handler.request_router {
pub fn retrieve_next_request(&mut self) -> (TargetId, ActionRequest);
}
}
}
impl PusTestHarness for Pus8HandlerWithVecTester {
@ -363,34 +330,8 @@ mod tests {
action_handler.send_tc(&tc);
let result = action_handler.handle_one_tc();
assert!(result.is_ok());
assert_eq!(
action_handler
.handler
.request_converter
.conversion_request
.len(),
1
);
assert_eq!(
action_handler.handler.request_converter.conversion_request[0],
tc.to_vec().unwrap()
);
assert_eq!(
action_handler
.handler
.request_router
.routing_requests
.borrow()
.len(),
1
);
let (target_id, action_req) = action_handler
.handler
.request_router
.routing_requests
.borrow_mut()
.pop_front()
.unwrap();
action_handler.check_next_conversion(&tc);
let (target_id, action_req) = action_handler.retrieve_next_request();
assert_eq!(target_id, TEST_APID.into());
if let ActionRequest::UnsignedIdAndVecData { action_id, data } = action_req {
assert_eq!(action_id, 1);
@ -427,26 +368,8 @@ mod tests {
panic!("unexpected error type");
}
assert_eq!(
action_handler
.handler
.request_converter
.conversion_request
.len(),
1
);
assert_eq!(
action_handler.handler.request_converter.conversion_request[0],
tc.to_vec().unwrap()
);
let (target_id, action_req) = action_handler
.handler
.request_router
.routing_requests
.borrow_mut()
.pop_front()
.unwrap();
action_handler.check_next_conversion(&tc);
let (target_id, action_req) = action_handler.retrieve_next_request();
assert_eq!(target_id, TEST_APID.into());
if let ActionRequest::UnsignedIdAndVecData { action_id, data } = action_req {
assert_eq!(action_id, 1);

View File

@ -93,9 +93,9 @@ pub mod std_mod {
RoutingError = GenericRoutingError,
> {
service_helper: PusServiceHelper<TcInMemConverter, VerificationReporter>,
request_converter: RequestConverter,
request_router: RequestRouter,
routing_error_handler: RoutingErrorHandler,
pub request_converter: RequestConverter,
pub request_router: RequestRouter,
pub routing_error_handler: RoutingErrorHandler,
}
impl<
@ -167,3 +167,185 @@ pub mod std_mod {
}
}
}
#[cfg(test)]
mod tests {
use delegate::delegate;
use spacepackets::ecss::hk::Subservice;
use spacepackets::{
ecss::{
tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader},
tm::PusTmReader,
PusPacket,
},
CcsdsPacket, SequenceFlags, SpHeader,
};
use crate::{
hk::HkRequest,
pus::{
tests::{
PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler,
TestConverter, TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID,
},
verification::{
tests::TestVerificationReporter, FailParams, RequestId, TcStateAccepted,
VerificationReportingProvider, VerificationToken,
},
EcssTcInVecConverter, GenericRoutingError, PusPacketHandlerResult,
PusPacketHandlingError,
},
TargetId,
};
use super::{PusHkRequestRouter, PusHkToRequestConverter, PusService3HkHandler};
impl PusHkRequestRouter for TestRouter<HkRequest> {
type Error = GenericRoutingError;
fn route(
&self,
target_id: TargetId,
hk_request: HkRequest,
_token: VerificationToken<TcStateAccepted>,
) -> Result<(), Self::Error> {
self.routing_requests
.borrow_mut()
.push_back((target_id, hk_request));
if self.injected_routing_failure.borrow().is_some() {
return Err(self.injected_routing_failure.borrow_mut().take().unwrap());
}
Ok(())
}
}
impl PusHkToRequestConverter for TestConverter<3> {
type Error = PusPacketHandlingError;
fn convert(
&mut self,
token: VerificationToken<TcStateAccepted>,
tc: &PusTcReader,
time_stamp: &[u8],
verif_reporter: &impl VerificationReportingProvider,
) -> Result<(TargetId, HkRequest), Self::Error> {
self.conversion_request.push_back(tc.raw_data().to_vec());
self.check_service(tc)?;
let target_id = tc.apid();
if tc.user_data().len() < 4 {
verif_reporter
.start_failure(
token,
FailParams::new(
time_stamp,
&APP_DATA_TOO_SHORT,
(tc.user_data().len() as u32).to_be_bytes().as_ref(),
),
)
.expect("start success failure");
return Err(PusPacketHandlingError::NotEnoughAppData {
expected: 4,
found: tc.user_data().len(),
});
}
if tc.subservice() == Subservice::TcGenerateOneShotHk as u8 {
verif_reporter
.start_success(token, time_stamp)
.expect("start success failure");
return Ok((
target_id.into(),
HkRequest::OneShot(u32::from_be_bytes(
tc.user_data()[0..4].try_into().unwrap(),
)),
));
}
Err(PusPacketHandlingError::InvalidAppData(
"unexpected app data".into(),
))
}
}
struct Pus3HandlerWithVecTester {
common: PusServiceHandlerWithVecCommon<TestVerificationReporter>,
handler: PusService3HkHandler<
EcssTcInVecConverter,
TestVerificationReporter,
TestConverter<3>,
TestRouter<HkRequest>,
TestRoutingErrorHandler,
>,
}
impl Pus3HandlerWithVecTester {
pub fn new() -> Self {
let (common, srv_handler) =
PusServiceHandlerWithVecCommon::new_with_test_verif_sender();
Self {
common,
handler: PusService3HkHandler::new(
srv_handler,
TestConverter::default(),
TestRouter::default(),
TestRoutingErrorHandler::default(),
),
}
}
delegate! {
to self.handler.request_converter {
pub fn check_next_conversion(&mut self, tc: &PusTcCreator);
}
}
delegate! {
to self.handler.request_router {
pub fn retrieve_next_request(&mut self) -> (TargetId, HkRequest);
}
}
}
impl PusTestHarness for Pus3HandlerWithVecTester {
delegate! {
to self.common {
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
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,
);
}
}
}
impl SimplePusPacketHandler for Pus3HandlerWithVecTester {
delegate! {
to self.handler {
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError>;
}
}
}
#[test]
fn basic_test() {
let mut hk_handler = Pus3HandlerWithVecTester::new();
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
let sec_header = PusTcSecondaryHeader::new_simple(3, Subservice::TcGenerateOneShotHk as u8);
let unique_id: u32 = 1;
let unique_id_raw = unique_id.to_be_bytes();
let tc = PusTcCreator::new(&mut sp_header, sec_header, unique_id_raw.as_ref(), true);
hk_handler.send_tc(&tc);
let result = hk_handler.handle_one_tc();
assert!(result.is_ok());
hk_handler.check_next_conversion(&tc);
let (target_id, hk_request) = hk_handler.retrieve_next_request();
assert_eq!(target_id, TEST_APID.into());
if let HkRequest::OneShot(id) = hk_request {
assert_eq!(id, unique_id);
} else {
panic!("unexpected request");
}
}
#[test]
fn test_routing_error() {}
}

View File

@ -931,12 +931,15 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), E
#[cfg(test)]
pub mod tests {
use core::cell::RefCell;
use std::sync::mpsc::TryRecvError;
use std::sync::{mpsc, RwLock};
use alloc::boxed::Box;
use alloc::vec;
use spacepackets::ecss::tc::PusTcCreator;
use alloc::collections::VecDeque;
use alloc::vec::Vec;
use satrs_shared::res_code::ResultU16;
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader};
use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator, PusTmReader};
use spacepackets::ecss::{PusPacket, WritablePusPacket};
use spacepackets::CcsdsPacket;
@ -946,6 +949,7 @@ pub mod tests {
};
use crate::pus::verification::RequestId;
use crate::tmtc::tm_helper::SharedTmPool;
use crate::TargetId;
use super::verification::tests::{SharedVerificationMap, TestVerificationReporter};
use super::verification::{
@ -953,9 +957,9 @@ pub mod tests {
VerificationReportingProvider, VerificationToken,
};
use super::{
EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, MpscTcReceiver,
MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult,
PusPacketHandlingError, PusServiceHelper, TcInMemory,
EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericRoutingError,
MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult,
PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, TcInMemory,
};
pub const TEST_APID: u16 = 0x101;
@ -1014,7 +1018,7 @@ pub mod tests {
Self,
PusServiceHelper<EcssTcInSharedStoreConverter, VerificationReporterWithSender>,
) {
let pool_cfg = StaticPoolConfig::new(vec![(16, 16), (8, 32), (4, 64)], false);
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
let tm_pool = StaticMemoryPool::new(pool_cfg);
let shared_tc_pool = SharedStaticMemoryPool::new(RwLock::new(tc_pool));
@ -1227,4 +1231,86 @@ pub mod tests {
assert_eq!(req_id, expected_request_id);
}
}
pub const APP_DATA_TOO_SHORT: ResultU16 = ResultU16::new(1, 1);
#[derive(Default)]
pub struct TestConverter<const SERVICE: u8> {
pub conversion_request: VecDeque<Vec<u8>>,
}
impl<const SERVICE: u8> TestConverter<SERVICE> {
pub fn check_service(&self, tc: &PusTcReader) -> Result<(), PusPacketHandlingError> {
if tc.service() != SERVICE {
return Err(PusPacketHandlingError::WrongService(tc.service()));
}
Ok(())
}
pub fn is_empty(&self) {
self.conversion_request.is_empty();
}
pub fn check_next_conversion(&mut self, tc: &PusTcCreator) {
assert!(!self.conversion_request.is_empty());
assert_eq!(
self.conversion_request.pop_front().unwrap(),
tc.to_vec().unwrap()
);
}
}
#[derive(Default)]
pub struct TestRoutingErrorHandler {
pub routing_errors: RefCell<VecDeque<(TargetId, GenericRoutingError)>>,
}
impl PusRoutingErrorHandler for TestRoutingErrorHandler {
type Error = GenericRoutingError;
fn handle_error(
&self,
target_id: TargetId,
_token: VerificationToken<TcStateAccepted>,
_tc: &PusTcReader,
error: Self::Error,
_time_stamp: &[u8],
_verif_reporter: &impl VerificationReportingProvider,
) {
self.routing_errors
.borrow_mut()
.push_back((target_id, error));
}
}
pub struct TestRouter<REQUEST> {
pub routing_requests: RefCell<VecDeque<(TargetId, REQUEST)>>,
pub injected_routing_failure: RefCell<Option<GenericRoutingError>>,
}
impl<REQUEST> Default for TestRouter<REQUEST> {
fn default() -> Self {
Self {
routing_requests: Default::default(),
injected_routing_failure: Default::default(),
}
}
}
impl<REQUEST> TestRouter<REQUEST> {
pub fn inject_routing_error(&mut self, error: GenericRoutingError) {
*self.injected_routing_failure.borrow_mut() = Some(error);
}
pub fn is_empty(&self) -> bool {
self.routing_requests.borrow().is_empty()
}
pub fn retrieve_next_request(&mut self) -> (TargetId, REQUEST) {
if self.routing_requests.borrow().is_empty() {
panic!("no routing request available");
}
self.routing_requests.borrow_mut().pop_front().unwrap()
}
}
}