prepared some infrastructure for tests
This commit is contained in:
parent
0f639900e2
commit
4f9cf38d34
@ -912,9 +912,29 @@ pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), E
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator};
|
||||
use std::sync::{mpsc, RwLock};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec;
|
||||
use spacepackets::ecss::tc::PusTcCreator;
|
||||
use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator, PusTmReader};
|
||||
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
||||
use spacepackets::CcsdsPacket;
|
||||
|
||||
use crate::pool::{LocalPool, PoolCfg, SharedPool, StoreAddr};
|
||||
use crate::pus::verification::RequestId;
|
||||
use crate::tmtc::tm_helper::SharedTmStore;
|
||||
|
||||
use super::verification::{
|
||||
TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken,
|
||||
};
|
||||
use super::{
|
||||
EcssTcAndToken, EcssTcInStoreConverter, MpscTcReceiver, MpscTmInStoreSender,
|
||||
PusServiceHandler,
|
||||
};
|
||||
|
||||
pub(crate) const TEST_APID: u16 = 0x101;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub(crate) struct CommonTmInfo {
|
||||
pub subservice: u8,
|
||||
@ -929,7 +949,7 @@ pub(crate) mod tests {
|
||||
let mut time_stamp = [0; 7];
|
||||
time_stamp.clone_from_slice(&tm.timestamp()[0..7]);
|
||||
Self {
|
||||
subservice: tm.subservice(),
|
||||
subservice: PusPacket::subservice(tm),
|
||||
apid: tm.apid(),
|
||||
msg_counter: tm.msg_counter(),
|
||||
dest_id: tm.dest_id(),
|
||||
@ -937,4 +957,99 @@ pub(crate) mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PusServiceHandlerWithStoreCommon {
|
||||
pus_buf: [u8; 2048],
|
||||
tm_buf: [u8; 2048],
|
||||
tc_pool: SharedPool,
|
||||
tm_pool: SharedTmStore,
|
||||
tc_sender: mpsc::Sender<EcssTcAndToken>,
|
||||
tm_receiver: mpsc::Receiver<StoreAddr>,
|
||||
verification_handler: VerificationReporterWithSender,
|
||||
}
|
||||
|
||||
impl PusServiceHandlerWithStoreCommon {
|
||||
pub fn new() -> (Self, PusServiceHandler<EcssTcInStoreConverter>) {
|
||||
let pool_cfg = PoolCfg::new(vec![(16, 16), (8, 32), (4, 64)]);
|
||||
let tc_pool = LocalPool::new(pool_cfg.clone());
|
||||
let tm_pool = LocalPool::new(pool_cfg);
|
||||
let shared_tc_pool = SharedPool::new(RwLock::new(Box::new(tc_pool)));
|
||||
let shared_tm_pool = SharedTmStore::new(Box::new(tm_pool));
|
||||
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
||||
let (tm_tx, tm_rx) = mpsc::channel();
|
||||
|
||||
let verif_sender =
|
||||
MpscTmInStoreSender::new(0, "verif_sender", shared_tm_pool.clone(), tm_tx.clone());
|
||||
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
||||
let verification_handler =
|
||||
VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender));
|
||||
let test_srv_tm_sender =
|
||||
MpscTmInStoreSender::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx);
|
||||
let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx);
|
||||
let in_store_converter = EcssTcInStoreConverter::new(shared_tc_pool.clone(), 2048);
|
||||
(
|
||||
PusServiceHandlerWithStoreCommon {
|
||||
pus_buf: [0; 2048],
|
||||
tm_buf: [0; 2048],
|
||||
tc_pool: shared_tc_pool,
|
||||
tm_pool: shared_tm_pool,
|
||||
tc_sender: test_srv_tc_tx,
|
||||
tm_receiver: tm_rx,
|
||||
verification_handler: verification_handler.clone(),
|
||||
},
|
||||
PusServiceHandler::new(
|
||||
Box::new(test_srv_tc_receiver),
|
||||
Box::new(test_srv_tm_sender),
|
||||
TEST_APID,
|
||||
verification_handler,
|
||||
in_store_converter,
|
||||
),
|
||||
)
|
||||
}
|
||||
pub(crate) fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||
let token = self.verification_handler.add_tc(tc);
|
||||
let token = self
|
||||
.verification_handler
|
||||
.acceptance_success(token, Some(&[0; 7]))
|
||||
.unwrap();
|
||||
let tc_size = tc.write_to_bytes(&mut self.pus_buf).unwrap();
|
||||
let mut tc_pool = self.tc_pool.write().unwrap();
|
||||
let addr = tc_pool.add(&self.pus_buf[..tc_size]).unwrap();
|
||||
drop(tc_pool);
|
||||
// Send accepted TC to test service handler.
|
||||
self.tc_sender
|
||||
.send(EcssTcAndToken::new(addr, token))
|
||||
.expect("sending tc failed");
|
||||
token
|
||||
}
|
||||
|
||||
pub(crate) fn read_next_tm(&mut self) -> PusTmReader<'_> {
|
||||
let next_msg = self.tm_receiver.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
let tm_addr = next_msg.unwrap();
|
||||
let tm_pool = self.tm_pool.pool.read().unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
self.tm_buf[0..tm_raw.len()].copy_from_slice(tm_raw);
|
||||
PusTmReader::new(&self.tm_buf, 7).unwrap().0
|
||||
}
|
||||
|
||||
pub(crate) fn check_next_verification_tm<STATE>(
|
||||
&self,
|
||||
subservice: u8,
|
||||
token: VerificationToken<STATE>,
|
||||
) {
|
||||
let next_msg = self.tm_receiver.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
let tm_addr = next_msg.unwrap();
|
||||
let tm_pool = self.tm_pool.pool.read().unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
let tm = PusTmReader::new(tm_raw, 7).unwrap().0;
|
||||
assert_eq!(PusPacket::service(&tm), 1);
|
||||
assert_eq!(PusPacket::subservice(&tm), subservice);
|
||||
assert_eq!(tm.apid(), TEST_APID);
|
||||
let req_id =
|
||||
RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");
|
||||
assert_eq!(req_id, token.req_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub use alloc_mod::*;
|
||||
|
||||
/// This is the request ID as specified in ECSS-E-ST-70-41C 5.4.11.2 of the standard.
|
||||
///
|
||||
/// This version of the request ID is used to identify scheduled commands and also contains
|
||||
/// This version of the request ID is used to identify scheduled commands and also contains
|
||||
/// the source ID found in the secondary header of PUS telecommands.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
@ -35,6 +35,12 @@ impl<TcInMemConverter: EcssTcInMemConverter> PusService17TestHandler<TcInMemConv
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_service_handler(service_handler: PusServiceHandler<TcInMemConverter>) -> Self {
|
||||
Self {
|
||||
psb: service_handler,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||
let possible_packet = self.psb.retrieve_and_accept_next_packet()?;
|
||||
if possible_packet.is_none() {
|
||||
@ -107,25 +113,24 @@ impl<TcInMemConverter: EcssTcInMemConverter> PusService17TestHandler<TcInMemConv
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::pool::{LocalPool, PoolCfg, SharedPool};
|
||||
use crate::pus::test::PusService17TestHandler;
|
||||
use crate::pus::tests::{PusServiceHandlerWithStoreCommon, TEST_APID};
|
||||
use crate::pus::verification::{
|
||||
RequestId, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken,
|
||||
RequestId, TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender,
|
||||
VerificationToken,
|
||||
};
|
||||
use crate::pus::{
|
||||
EcssTcAndToken, EcssTcInStoreConverter, EcssTcInVecConverter, MpscTcReceiver,
|
||||
MpscTmAsVecSender, MpscTmInStoreSender, TcInMemory,
|
||||
MpscTmAsVecSender, TcInMemory,
|
||||
};
|
||||
use crate::tmtc::tm_helper::SharedTmStore;
|
||||
use delegate::delegate;
|
||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
|
||||
use spacepackets::ecss::tm::PusTmReader;
|
||||
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
||||
use spacepackets::{CcsdsPacket, SequenceFlags, SpHeader};
|
||||
use std::boxed::Box;
|
||||
use std::sync::{mpsc, RwLock};
|
||||
use std::vec;
|
||||
use std::sync::mpsc;
|
||||
|
||||
const TEST_APID: u16 = 0x101;
|
||||
use super::PusService17TestHandler;
|
||||
|
||||
fn verify_verification_tm<STATE>(
|
||||
subservice: u8,
|
||||
@ -139,84 +144,61 @@ mod tests {
|
||||
assert_eq!(req_id, token.req_id());
|
||||
}
|
||||
|
||||
struct Pus17HandlerWithStoreTester {
|
||||
common: PusServiceHandlerWithStoreCommon,
|
||||
handler: PusService17TestHandler<EcssTcInStoreConverter>,
|
||||
}
|
||||
|
||||
impl Pus17HandlerWithStoreTester {
|
||||
pub fn new() -> Self {
|
||||
let (common, srv_handler) = PusServiceHandlerWithStoreCommon::new();
|
||||
let pus_17_handler = PusService17TestHandler::new_from_service_handler(srv_handler);
|
||||
Self {
|
||||
common,
|
||||
handler: pus_17_handler,
|
||||
}
|
||||
}
|
||||
|
||||
delegate! {
|
||||
to self.common {
|
||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||
fn check_next_verification_tm<STATE>(
|
||||
&self,
|
||||
subservice: u8,
|
||||
token: VerificationToken<STATE>,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_ping_processing_using_store() {
|
||||
let mut pus_buf: [u8; 64] = [0; 64];
|
||||
let pool_cfg = PoolCfg::new(vec![(16, 16), (8, 32), (4, 64)]);
|
||||
let tc_pool = LocalPool::new(pool_cfg.clone());
|
||||
let tm_pool = LocalPool::new(pool_cfg);
|
||||
let tc_pool_shared = SharedPool::new(RwLock::new(Box::new(tc_pool)));
|
||||
let shared_tm_store = SharedTmStore::new(Box::new(tm_pool));
|
||||
let tm_pool_shared = shared_tm_store.clone_backing_pool();
|
||||
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
||||
let (tm_tx, tm_rx) = mpsc::channel();
|
||||
let verif_sender =
|
||||
MpscTmInStoreSender::new(0, "verif_sender", shared_tm_store.clone(), tm_tx.clone());
|
||||
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
||||
let mut verification_handler =
|
||||
VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender));
|
||||
let test_srv_tm_sender = MpscTmInStoreSender::new(0, "TEST_SENDER", shared_tm_store, tm_tx);
|
||||
let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx);
|
||||
let in_store_converter = EcssTcInStoreConverter::new(tc_pool_shared.clone(), 2048);
|
||||
let mut pus_17_handler = PusService17TestHandler::new(
|
||||
Box::new(test_srv_tc_receiver),
|
||||
Box::new(test_srv_tm_sender),
|
||||
TEST_APID,
|
||||
verification_handler.clone(),
|
||||
in_store_converter,
|
||||
);
|
||||
let mut tester = Pus17HandlerWithStoreTester::new();
|
||||
// Create a ping TC, verify acceptance.
|
||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||
let token = verification_handler.add_tc(&ping_tc);
|
||||
let token = verification_handler
|
||||
.acceptance_success(token, None)
|
||||
.unwrap();
|
||||
let tc_size = ping_tc.write_to_bytes(&mut pus_buf).unwrap();
|
||||
let mut tc_pool = tc_pool_shared.write().unwrap();
|
||||
let addr = tc_pool.add(&pus_buf[..tc_size]).unwrap();
|
||||
drop(tc_pool);
|
||||
// Send accepted TC to test service handler.
|
||||
test_srv_tc_tx
|
||||
.send(EcssTcAndToken::new(addr, token))
|
||||
.unwrap();
|
||||
let result = pus_17_handler.handle_one_tc();
|
||||
let token = tester.send_tc(&ping_tc);
|
||||
let result = tester.handler.handle_one_tc();
|
||||
assert!(result.is_ok());
|
||||
// We should see 4 replies in the TM queue now: Acceptance TM, Start TM, ping reply and
|
||||
// Completion TM
|
||||
let mut next_msg = tm_rx.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
let mut tm_addr = next_msg.unwrap();
|
||||
let tm_pool = tm_pool_shared.read().unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
verify_verification_tm(1, &PusTmReader::new(tm_raw, 0).unwrap().0, token);
|
||||
|
||||
// Acceptance TM
|
||||
next_msg = tm_rx.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
tm_addr = next_msg.unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
// Is generated with CDS short timestamp.
|
||||
verify_verification_tm(3, &PusTmReader::new(tm_raw, 7).unwrap().0, token);
|
||||
tester.check_next_verification_tm(1, token);
|
||||
|
||||
// Start TM
|
||||
tester.check_next_verification_tm(3, token);
|
||||
|
||||
// Ping reply
|
||||
next_msg = tm_rx.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
tm_addr = next_msg.unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
// Is generated with CDS short timestamp.
|
||||
let (tm, _) = PusTmReader::new(tm_raw, 7).unwrap();
|
||||
let tm = tester.read_next_tm();
|
||||
assert_eq!(tm.service(), 17);
|
||||
assert_eq!(tm.subservice(), 2);
|
||||
assert!(tm.user_data().is_empty());
|
||||
|
||||
// TM completion
|
||||
next_msg = tm_rx.try_recv();
|
||||
assert!(next_msg.is_ok());
|
||||
tm_addr = next_msg.unwrap();
|
||||
let tm_raw = tm_pool.read(&tm_addr).unwrap();
|
||||
verify_verification_tm(7, &PusTmReader::new(tm_raw, 7).unwrap().0, token);
|
||||
tester.check_next_verification_tm(7, token);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -16,7 +16,7 @@ pub mod std_mod {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SharedTmStore {
|
||||
pool: SharedPool,
|
||||
pub pool: SharedPool,
|
||||
}
|
||||
|
||||
impl SharedTmStore {
|
||||
|
Loading…
Reference in New Issue
Block a user