Skip to content

Commit

Permalink
first unittest for source handler
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Aug 19, 2024
1 parent d3aa56a commit ed4b3ee
Show file tree
Hide file tree
Showing 3 changed files with 381 additions and 177 deletions.
154 changes: 16 additions & 138 deletions satrs/src/cfdp/dest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ impl<
fn notice_of_suspension(&mut self) {
// TODO: Implement suspension handling.
}

fn abandon_transaction(&mut self) {
self.reset();
}
Expand Down Expand Up @@ -815,6 +816,10 @@ impl<
Ok(1)
}

pub fn local_cfg(&self) -> &LocalEntityConfig<UserFaultHook> {
&self.local_cfg
}

fn tstate(&self) -> &TransferState<CheckTimerProvider> {
&self.tparams.tstate
}
Expand All @@ -831,7 +836,7 @@ mod tests {
#[allow(unused_imports)]
use std::println;

use alloc::{collections::VecDeque, string::String, sync::Arc, vec::Vec};
use alloc::{sync::Arc, vec::Vec};
use rand::Rng;
use spacepackets::{
cfdp::{
Expand All @@ -844,148 +849,18 @@ mod tests {

use crate::cfdp::{
filestore::NativeFilestore,
tests::{basic_remote_cfg_table, SentPdu, TestCfdpSender, TestFaultHandler},
user::OwnedMetadataRecvdParams,
tests::{
basic_remote_cfg_table, SentPdu, TestCfdpSender, TestCfdpUser, TestFaultHandler,
LOCAL_ID,
},
CheckTimerProviderCreator, CountdownProvider, FaultHandler, IndicationConfig,
StdRemoteEntityConfigProvider, CRC_32,
};

use super::*;

const LOCAL_ID: UnsignedByteFieldU16 = UnsignedByteFieldU16::new(1);
const REMOTE_ID: UnsignedByteFieldU16 = UnsignedByteFieldU16::new(2);

pub struct FileSegmentRecvdParamsNoSegMetadata {
pub id: TransactionId,
pub offset: u64,
pub length: usize,
}

#[derive(Default)]
struct TestCfdpUser {
next_expected_seq_num: u64,
expected_full_src_name: String,
expected_full_dest_name: String,
expected_file_size: u64,
transaction_indication_call_count: u32,
eof_recvd_call_count: u32,
finished_indic_queue: VecDeque<TransactionFinishedParams>,
metadata_recv_queue: VecDeque<OwnedMetadataRecvdParams>,
file_seg_recvd_queue: VecDeque<FileSegmentRecvdParamsNoSegMetadata>,
}

impl TestCfdpUser {
fn new(
next_expected_seq_num: u64,
expected_full_src_name: String,
expected_full_dest_name: String,
expected_file_size: u64,
) -> Self {
Self {
next_expected_seq_num,
expected_full_src_name,
expected_full_dest_name,
expected_file_size,
transaction_indication_call_count: 0,
eof_recvd_call_count: 0,
finished_indic_queue: VecDeque::new(),
metadata_recv_queue: VecDeque::new(),
file_seg_recvd_queue: VecDeque::new(),
}
}

fn generic_id_check(&self, id: &crate::cfdp::TransactionId) {
assert_eq!(id.source_id, LOCAL_ID.into());
assert_eq!(id.seq_num().value(), self.next_expected_seq_num);
}
}

impl CfdpUser for TestCfdpUser {
fn transaction_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
self.transaction_indication_call_count += 1;
}

fn eof_sent_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
}

fn transaction_finished_indication(
&mut self,
finished_params: &crate::cfdp::user::TransactionFinishedParams,
) {
self.generic_id_check(&finished_params.id);
self.finished_indic_queue.push_back(*finished_params);
}

fn metadata_recvd_indication(
&mut self,
md_recvd_params: &crate::cfdp::user::MetadataReceivedParams,
) {
self.generic_id_check(&md_recvd_params.id);
assert_eq!(
String::from(md_recvd_params.src_file_name),
self.expected_full_src_name
);
assert_eq!(
String::from(md_recvd_params.dest_file_name),
self.expected_full_dest_name
);
assert_eq!(md_recvd_params.msgs_to_user.len(), 0);
assert_eq!(md_recvd_params.source_id, LOCAL_ID.into());
assert_eq!(md_recvd_params.file_size, self.expected_file_size);
self.metadata_recv_queue.push_back(md_recvd_params.into());
}

fn file_segment_recvd_indication(
&mut self,
segment_recvd_params: &crate::cfdp::user::FileSegmentRecvdParams,
) {
self.generic_id_check(&segment_recvd_params.id);
self.file_seg_recvd_queue
.push_back(FileSegmentRecvdParamsNoSegMetadata {
id: segment_recvd_params.id,
offset: segment_recvd_params.offset,
length: segment_recvd_params.length,
})
}

fn report_indication(&mut self, _id: &crate::cfdp::TransactionId) {}

fn suspended_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
) {
panic!("unexpected suspended indication");
}

fn resumed_indication(&mut self, _id: &crate::cfdp::TransactionId, _progresss: u64) {}

fn fault_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
_progress: u64,
) {
panic!("unexpected fault indication");
}

fn abandoned_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
_progress: u64,
) {
panic!("unexpected abandoned indication");
}

fn eof_recvd_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
self.eof_recvd_call_count += 1;
}
}

#[derive(Debug)]
struct TestCheckTimer {
counter: Cell<u32>,
Expand Down Expand Up @@ -1066,7 +941,7 @@ mod tests {
let test_sender = TestCfdpSender::default();
let dest_handler =
default_dest_handler(fault_handler, test_sender, check_timer_expired.clone());
let (src_path, dest_path) = init_full_filenames();
let (src_path, dest_path) = init_full_filepaths_textfile();
assert!(!Path::exists(&dest_path));
let handler = Self {
check_timer_expired,
Expand Down Expand Up @@ -1205,7 +1080,7 @@ mod tests {
}
}

fn init_full_filenames() -> (PathBuf, PathBuf) {
fn init_full_filepaths_textfile() -> (PathBuf, PathBuf) {
(
tempfile::TempPath::from_path("/tmp/test.txt").to_path_buf(),
tempfile::NamedTempFile::new()
Expand All @@ -1230,7 +1105,7 @@ mod tests {
2048,
test_packet_sender,
NativeFilestore::default(),
basic_remote_cfg_table(),
basic_remote_cfg_table(LOCAL_ID, true),
TestCheckTimerCreator::new(check_timer_expired),
)
}
Expand Down Expand Up @@ -1297,6 +1172,9 @@ mod tests {
.user_hook
.borrow()
.all_queues_empty());
assert!(dest_handler.pdu_sender.queue_empty());
assert_eq!(dest_handler.state(), State::Idle);
assert_eq!(dest_handler.step(), TransactionStep::Idle);
}

#[test]
Expand Down
147 changes: 142 additions & 5 deletions satrs/src/cfdp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ impl<'raw> PacketInfo<'raw> {
pub(crate) mod tests {
use core::cell::RefCell;

use alloc::{collections::VecDeque, vec::Vec};
use alloc::{collections::VecDeque, string::String, vec::Vec};
use spacepackets::{
cfdp::{
lv::Lv,
Expand All @@ -679,16 +679,150 @@ pub(crate) mod tests {
},
ChecksumType, ConditionCode, PduType, TransmissionMode,
},
util::UnsignedByteFieldU16,
util::{UnsignedByteField, UnsignedByteFieldU16, UnsignedEnum},
};

use crate::cfdp::PacketTarget;

use super::{
user::{CfdpUser, OwnedMetadataRecvdParams, TransactionFinishedParams},
PacketInfo, PduSendProvider, RemoteEntityConfig, RemoteEntityConfigProvider,
StdRemoteEntityConfigProvider, TransactionId, UserFaultHookProvider,
};

pub const LOCAL_ID: UnsignedByteFieldU16 = UnsignedByteFieldU16::new(1);

pub struct FileSegmentRecvdParamsNoSegMetadata {
pub id: TransactionId,
pub offset: u64,
pub length: usize,
}

#[derive(Default)]
pub struct TestCfdpUser {
pub next_expected_seq_num: u64,
pub expected_full_src_name: String,
pub expected_full_dest_name: String,
pub expected_file_size: u64,
pub transaction_indication_call_count: u32,
pub eof_recvd_call_count: u32,
pub finished_indic_queue: VecDeque<TransactionFinishedParams>,
pub metadata_recv_queue: VecDeque<OwnedMetadataRecvdParams>,
pub file_seg_recvd_queue: VecDeque<FileSegmentRecvdParamsNoSegMetadata>,
}

impl TestCfdpUser {
pub fn new(
next_expected_seq_num: u64,
expected_full_src_name: String,
expected_full_dest_name: String,
expected_file_size: u64,
) -> Self {
Self {
next_expected_seq_num,
expected_full_src_name,
expected_full_dest_name,
expected_file_size,
transaction_indication_call_count: 0,
eof_recvd_call_count: 0,
finished_indic_queue: VecDeque::new(),
metadata_recv_queue: VecDeque::new(),
file_seg_recvd_queue: VecDeque::new(),
}
}

pub fn generic_id_check(&self, id: &crate::cfdp::TransactionId) {
assert_eq!(id.source_id, LOCAL_ID.into());
assert_eq!(id.seq_num().value(), self.next_expected_seq_num);
}
}

impl CfdpUser for TestCfdpUser {
fn transaction_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
self.transaction_indication_call_count += 1;
}

fn eof_sent_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
}

fn transaction_finished_indication(
&mut self,
finished_params: &crate::cfdp::user::TransactionFinishedParams,
) {
self.generic_id_check(&finished_params.id);
self.finished_indic_queue.push_back(*finished_params);
}

fn metadata_recvd_indication(
&mut self,
md_recvd_params: &crate::cfdp::user::MetadataReceivedParams,
) {
self.generic_id_check(&md_recvd_params.id);
assert_eq!(
String::from(md_recvd_params.src_file_name),
self.expected_full_src_name
);
assert_eq!(
String::from(md_recvd_params.dest_file_name),
self.expected_full_dest_name
);
assert_eq!(md_recvd_params.msgs_to_user.len(), 0);
assert_eq!(md_recvd_params.source_id, LOCAL_ID.into());
assert_eq!(md_recvd_params.file_size, self.expected_file_size);
self.metadata_recv_queue.push_back(md_recvd_params.into());
}

fn file_segment_recvd_indication(
&mut self,
segment_recvd_params: &crate::cfdp::user::FileSegmentRecvdParams,
) {
self.generic_id_check(&segment_recvd_params.id);
self.file_seg_recvd_queue
.push_back(FileSegmentRecvdParamsNoSegMetadata {
id: segment_recvd_params.id,
offset: segment_recvd_params.offset,
length: segment_recvd_params.length,
})
}

fn report_indication(&mut self, _id: &crate::cfdp::TransactionId) {}

fn suspended_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
) {
panic!("unexpected suspended indication");
}

fn resumed_indication(&mut self, _id: &crate::cfdp::TransactionId, _progresss: u64) {}

fn fault_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
_progress: u64,
) {
panic!("unexpected fault indication");
}

fn abandoned_indication(
&mut self,
_id: &crate::cfdp::TransactionId,
_condition_code: ConditionCode,
_progress: u64,
) {
panic!("unexpected abandoned indication");
}

fn eof_recvd_indication(&mut self, id: &crate::cfdp::TransactionId) {
self.generic_id_check(id);
self.eof_recvd_call_count += 1;
}
}

#[derive(Default)]
pub(crate) struct TestFaultHandler {
pub notice_of_suspension_queue: VecDeque<(TransactionId, ConditionCode, u64)>,
Expand Down Expand Up @@ -791,14 +925,17 @@ pub(crate) mod tests {
}
}

pub fn basic_remote_cfg_table() -> StdRemoteEntityConfigProvider {
pub fn basic_remote_cfg_table(
dest_id: impl Into<UnsignedByteField>,
crc_on_transmission_by_default: bool,
) -> StdRemoteEntityConfigProvider {
let mut table = StdRemoteEntityConfigProvider::default();
let remote_entity_cfg = RemoteEntityConfig::new_with_default_values(
UnsignedByteFieldU16::new(1).into(),
dest_id.into(),
1024,
1024,
true,
true,
crc_on_transmission_by_default,
TransmissionMode::Unacknowledged,
ChecksumType::Crc32,
);
Expand Down
Loading

0 comments on commit ed4b3ee

Please sign in to comment.