diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index dd7bf47..2723de7 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -22,6 +22,7 @@ derive-new = "0.5" [dependencies.satrs] # version = "0.2.0-rc.0" path = "../satrs" +features = ["test_util"] [dependencies.satrs-mib] # version = "0.1.1" diff --git a/satrs-example/src/acs/mgm.rs b/satrs-example/src/acs/mgm.rs index 3f45520..9926ba2 100644 --- a/satrs-example/src/acs/mgm.rs +++ b/satrs-example/src/acs/mgm.rs @@ -1,3 +1,5 @@ +// TODO: Remove this at a later stage. +#![allow(dead_code)] use std::sync::mpsc::{self}; use std::sync::{Arc, Mutex}; diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index 1175153..7b60f97 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -383,7 +383,7 @@ mod tests { > { pub fn new_for_action() -> Self { - env_logger::init(); + let _ = env_logger::builder().is_test(true).try_init(); let target_and_apid_id = TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID); let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel(); let (pus_action_tx, pus_action_rx) = mpsc::channel(); diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index 8ac82b1..d7f5082 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -367,6 +367,40 @@ impl< } #[cfg(test)] -pub mod tests { - // TODO: Add unittests for HK converter. +mod tests { + use satrs::{ + pus::{ + test_util::TEST_APID, + verification::{ + test_util::{SharedVerificationMap, TestVerificationReporter}, + VerificationReportingProvider, + }, + PusTcToRequestConverter, + }, + spacepackets::{ + ecss::{ + tc::{PusTcCreator, PusTcReader}, + WritablePusPacket, + }, + SpHeader, + }, + }; + + use super::ExampleHkRequestConverter; + + #[test] + fn test_hk_converter() { + let shared_verif_map = SharedVerificationMap::default(); + let mut test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone()); + let mut converter = ExampleHkRequestConverter::default(); + let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap(); + let ping = PusTcCreator::new_simple(&mut sp_header, 3, 25, Some(&[1, 2, 3, 4]), true); + let token = test_verif_reporter.add_tc(&ping); + let accepted_token = test_verif_reporter + .acceptance_success(token, &[]) + .expect("acceptance failed"); + let pus_tc_raw = ping.to_vec().unwrap(); + let pus_tc_reader = PusTcReader::new(&pus_tc_raw).expect("invalid pus tc"); + converter.convert(accepted_token, &pus_tc_reader.0, &[], &test_verif_reporter); + } } diff --git a/satrs/Cargo.toml b/satrs/Cargo.toml index 4f35c30..d233eb5 100644 --- a/satrs/Cargo.toml +++ b/satrs/Cargo.toml @@ -115,6 +115,7 @@ alloc = [ serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"] crossbeam = ["crossbeam-channel"] heapless = ["dep:heapless"] +test_util = [] doc-images = [] [package.metadata.docs.rs] diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 5ef5df1..abb24c7 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -5,7 +5,7 @@ use crate::{ ComponentId, }; -use super::{verification::VerificationToken, ActivePusRequestStd, ActiveRequestProvider}; +use super::{ActivePusRequestStd, ActiveRequestProvider}; use delegate::delegate; use satrs_shared::res_code::ResultU16; diff --git a/satrs/src/pus/event_srv.rs b/satrs/src/pus/event_srv.rs index bb66151..a808679 100644 --- a/satrs/src/pus/event_srv.rs +++ b/satrs/src/pus/event_srv.rs @@ -159,7 +159,7 @@ mod tests { 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, }; @@ -168,7 +168,7 @@ mod tests { events::EventU32, pus::{ event_man::EventRequestWithToken, - tests::{PusServiceHandlerWithSharedStoreCommon, PusTestHarness, TEST_APID}, + tests::PusServiceHandlerWithSharedStoreCommon, verification::{TcStateAccepted, VerificationToken}, EcssTcInSharedStoreConverter, PusPacketHandlerResult, PusPacketHandlingError, }, diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index f582ad1..ae9839a 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -40,7 +40,7 @@ pub use alloc_mod::*; #[cfg(feature = "std")] pub use std_mod::*; -use self::verification::{TcStateStarted, VerificationReportingProvider}; +use self::verification::VerificationReportingProvider; #[derive(Debug, PartialEq, Eq, Clone)] pub enum PusTmWrapper<'tm> { @@ -667,7 +667,7 @@ pub mod std_mod { #[cfg(feature = "crossbeam")] pub use cb_mod::*; - use super::verification::{TcStateStarted, TcStateToken, VerificationReportingProvider}; + use super::verification::{TcStateToken, VerificationReportingProvider}; use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory}; impl From> for EcssTmtcError { @@ -1429,6 +1429,33 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), E Ok(()) } +#[cfg(any(feature = "test_util", test))] +pub mod test_util { + use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader}; + + use super::{ + verification::{self, TcStateAccepted, VerificationToken}, + PusPacketHandlerResult, PusPacketHandlingError, + }; + + pub const TEST_APID: u16 = 0x101; + + pub trait PusTestHarness { + fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; + 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: verification::RequestId, + ); + } + + pub trait SimplePusPacketHandler { + fn handle_one_tc(&mut self) -> Result; + } +} + #[cfg(test)] pub mod tests { use core::cell::RefCell; @@ -1450,22 +1477,17 @@ pub mod tests { use crate::tmtc::tm_helper::SharedTmPool; use crate::ComponentId; + use super::test_util::TEST_APID; + use super::verification::std_mod::{ VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, }; - use super::verification::tests::{SharedVerificationMap, TestVerificationReporter}; + use super::verification::test_util::{SharedVerificationMap, TestVerificationReporter}; use super::verification::{ TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender, VerificationReportingProvider, VerificationToken, }; - use super::{ - EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, - GenericRoutingError, MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, - PusServiceHelper, TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc, - TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId, - }; - - pub const TEST_APID: u16 = 0x101; + use super::*; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct CommonTmInfo { @@ -1476,17 +1498,6 @@ pub mod tests { pub time_stamp: [u8; 7], } - pub trait PusTestHarness { - fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken; - 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); - } - - pub trait SimplePusPacketHandler { - fn handle_one_tc(&mut self) -> Result; - } - impl CommonTmInfo { pub fn new_from_tm(tm: &PusTmCreator) -> Self { let mut time_stamp = [0; 7]; diff --git a/satrs/src/pus/scheduler_srv.rs b/satrs/src/pus/scheduler_srv.rs index 0677573..ccb3412 100644 --- a/satrs/src/pus/scheduler_srv.rs +++ b/satrs/src/pus/scheduler_srv.rs @@ -225,11 +225,11 @@ pub type PusService11SchedHandlerStaticWithBoundedMpsc = PusServic #[cfg(test)] mod tests { use crate::pool::{StaticMemoryPool, StaticPoolConfig}; - use crate::pus::tests::TEST_APID; + use crate::pus::test_util::{PusTestHarness, TEST_APID}; use crate::pus::verification::VerificationReporterWithSharedPoolMpscBoundedSender; use crate::pus::{ scheduler::{self, PusSchedulerProvider, TcInfo}, - tests::{PusServiceHandlerWithSharedStoreCommon, PusTestHarness}, + tests::PusServiceHandlerWithSharedStoreCommon, verification::{RequestId, TcStateAccepted, VerificationToken}, EcssTcInSharedStoreConverter, }; diff --git a/satrs/src/pus/test.rs b/satrs/src/pus/test.rs index f85a566..3125b25 100644 --- a/satrs/src/pus/test.rs +++ b/satrs/src/pus/test.rs @@ -151,9 +151,9 @@ pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler< #[cfg(test)] mod tests { + use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID}; use crate::pus::tests::{ - PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon, PusTestHarness, - SimplePusPacketHandler, TEST_APID, + PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon, }; use crate::pus::verification::std_mod::{ VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender, diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index c1d4095..96f7b65 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -209,6 +209,7 @@ impl From> for VerificationOrSendErrorWithToken VerificationOrSendErrorWithToken(value.0, value.1) } } + /// Support token to allow type-state programming. This prevents calling the verification /// steps in an invalid order. #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -217,6 +218,28 @@ pub struct VerificationToken { req_id: RequestId, } +impl VerificationToken { + fn new(req_id: RequestId) -> VerificationToken { + VerificationToken { + state: PhantomData, + req_id, + } + } + + /// Create a verification token with a state. This can be useful for test purposes. + /// For general purposes, it is recommended to use the API exposed by verification handlers. + pub fn new_accepted_state(req_id: RequestId) -> VerificationToken { + VerificationToken { + state: PhantomData, + req_id, + } + } + + pub fn req_id(&self) -> RequestId { + self.req_id + } +} + pub trait WasAtLeastAccepted {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -290,19 +313,6 @@ impl From> for TcStateToken { } } -impl VerificationToken { - fn new(req_id: RequestId) -> VerificationToken { - VerificationToken { - state: PhantomData, - req_id, - } - } - - pub fn req_id(&self) -> RequestId { - self.req_id - } -} - /// Composite helper struct to pass failure parameters to the [VerificationReporter] pub struct FailParams<'stamp, 'fargs> { pub time_stamp: &'stamp [u8], @@ -1430,40 +1440,15 @@ pub mod std_mod { VerificationReporterWithVecSender>>; } -#[cfg(test)] -pub mod tests { - use crate::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig}; - use crate::pus::tests::CommonTmInfo; - use crate::pus::verification::{ - EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone, - VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, - VerificationToken, - }; - use crate::pus::{ - EcssChannel, PusTmWrapper, TmInSharedPoolSenderWithId, TmInSharedPoolSenderWithMpsc, - }; - use crate::tmtc::tm_helper::SharedTmPool; - use crate::ComponentId; - use alloc::format; - use alloc::sync::Arc; +#[cfg(any(feature = "test_util", test))] +pub mod test_util { + use core::cell::RefCell; + use std::sync::Mutex; + + use alloc::{sync::Arc, vec::Vec}; use hashbrown::HashMap; - use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; - use spacepackets::ecss::tm::PusTmReader; - use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, PusError, PusPacket}; - use spacepackets::util::UnsignedEnum; - use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader}; - use std::cell::RefCell; - use std::collections::VecDeque; - use std::sync::{mpsc, Mutex}; - use std::time::Duration; - use std::vec; - use std::vec::Vec; - use super::VerificationReportingProvider; - - fn is_send(_: &T) {} - #[allow(dead_code)] - fn is_sync(_: &T) {} + use super::*; #[derive(Clone)] pub struct VerificationStatus { @@ -1691,8 +1676,42 @@ pub mod tests { false } } +} + +#[cfg(test)] +pub mod tests { + use crate::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig}; + use crate::pus::test_util::TEST_APID; + use crate::pus::tests::CommonTmInfo; + use crate::pus::verification::{ + EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone, + VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, + VerificationToken, + }; + use crate::pus::{ + EcssChannel, PusTmWrapper, TmInSharedPoolSenderWithId, TmInSharedPoolSenderWithMpsc, + }; + use crate::tmtc::tm_helper::SharedTmPool; + use crate::ComponentId; + use alloc::format; + use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; + use spacepackets::ecss::tm::PusTmReader; + use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, PusError, PusPacket}; + use spacepackets::util::UnsignedEnum; + use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader}; + use std::cell::RefCell; + use std::collections::VecDeque; + use std::sync::mpsc; + use std::time::Duration; + use std::vec; + use std::vec::Vec; + + use super::VerificationReportingProvider; + + fn is_send(_: &T) {} + #[allow(dead_code)] + fn is_sync(_: &T) {} - const TEST_APID: u16 = 0x02; const EMPTY_STAMP: [u8; 7] = [0; 7]; #[derive(Debug, Eq, PartialEq, Clone)]