add more tests

This commit is contained in:
Robin Müller 2025-01-21 13:18:14 +01:00
parent 821854baa0
commit 918ff101a8

View File

@ -299,6 +299,7 @@ impl SubsystemCommandingHelper {
#[derive(Default, Debug)]
pub struct ModeRequestHandlerMock {
pub id: ComponentId,
get_mode_calls: RefCell<usize>,
start_transition_calls: VecDeque<(MessageMetadata, ModeAndSubmode)>,
announce_mode_calls: RefCell<VecDeque<AnnounceModeInfo>>,
@ -307,6 +308,15 @@ pub struct ModeRequestHandlerMock {
send_mode_reply_calls: RefCell<VecDeque<(MessageMetadata, ModeReply)>>,
}
impl ModeRequestHandlerMock {
pub fn new(id: ComponentId) -> Self {
Self {
id,
..Default::default()
}
}
}
impl ModeRequestHandlerMock {
pub fn clear(&mut self) {
self.get_mode_calls.replace(0);
@ -388,8 +398,9 @@ impl ModeRequestHandler for ModeRequestHandlerMock {
}
}
#[derive(Default, Debug)]
#[derive(Debug)]
pub struct ModeReplyHandlerMock {
pub id: ComponentId,
mode_info_messages: VecDeque<(MessageMetadata, ModeAndSubmode)>,
mode_reply_messages: VecDeque<(MessageMetadata, ModeAndSubmode)>,
cant_reach_mode_messages: VecDeque<(MessageMetadata, ResultU16)>,
@ -397,6 +408,23 @@ pub struct ModeReplyHandlerMock {
}
impl ModeReplyHandlerMock {
pub fn new(id: ComponentId) -> Self {
Self {
id,
mode_info_messages: Default::default(),
mode_reply_messages: Default::default(),
cant_reach_mode_messages: Default::default(),
wrong_mode_messages: Default::default(),
}
}
pub fn num_of_received_mode_replies(&self) -> usize {
self.mode_info_messages.len()
+ self.mode_reply_messages.len()
+ self.cant_reach_mode_messages.len()
+ self.wrong_mode_messages.len()
}
pub fn handle_mode_reply(&mut self, request: &GenericMessage<ModeReply>) {
match request.message {
ModeReply::ModeInfo(mode_and_submode) => {
@ -481,16 +509,22 @@ struct AcsSubsystem {
pub target_mode_and_submode: Option<ModeAndSubmode>,
pub subsystem_helper: SubsystemCommandingHelper,
pub mode_req_mock: ModeRequestHandlerMock,
pub mode_reply_mock: ModeReplyHandlerMock,
}
impl AcsSubsystem {
pub fn id() -> ComponentId {
TestComponentId::AcsSubsystem as u64
}
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
Self {
mode_node,
mode_requestor_info: None,
target_mode_and_submode: None,
subsystem_helper: SubsystemCommandingHelper::default(),
mode_req_mock: Default::default(),
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
}
}
@ -542,6 +576,7 @@ impl AcsSubsystem {
let mut received_reply = false;
while let Some(mode_reply) = self.mode_node.try_recv_mode_reply().unwrap() {
received_reply = true;
self.mode_reply_mock.handle_mode_reply(&mode_reply);
let result = self
.subsystem_helper
.state_machine(Some(mode_reply), &self.mode_node);
@ -689,7 +724,7 @@ impl ModeRequestHandler for AcsSubsystem {
/// For example, this could be used in an Assembly component which manages multiple redundant
/// child components. It can also be used inside a manager component which only manages one device.
#[derive(Debug, Default)]
pub struct DevManagerCommandingHelper {
pub struct AssemblyCommandingHelper {
/// The IDs, modes and reply awaition status of all children are tracked in this data
/// structure.
pub children_mode_store: ModeStoreVec,
@ -700,7 +735,9 @@ pub struct DevManagerCommandingHelper {
pub state: ModeTreeHelperState,
}
impl DevManagerCommandingHelper {
pub type DevManagerCommandingHelper = AssemblyCommandingHelper;
impl AssemblyCommandingHelper {
pub fn send_mode_cmd_to_all_children_with_reply_awaition(
&mut self,
request_id: RequestId,
@ -817,20 +854,23 @@ struct MgmAssembly {
pub mode_node: ModeRequestorAndHandlerMpscBounded,
pub mode_requestor_info: Option<MessageMetadata>,
pub mode_and_submode: ModeAndSubmode,
pub commanding_helper: DevManagerCommandingHelper,
pub commanding_helper: AssemblyCommandingHelper,
pub mode_req_mock: ModeRequestHandlerMock,
pub mode_reply_mock: ModeReplyHandlerMock,
}
impl MgmAssembly {
pub fn id() -> ComponentId {
TestComponentId::MagnetometerAssembly as u64
}
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
Self {
mode_node,
mode_requestor_info: None,
mode_and_submode: UNKNOWN_MODE,
commanding_helper: Default::default(),
mode_req_mock: Default::default(),
mode_reply_mock: Default::default(),
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
}
}
@ -862,8 +902,8 @@ impl MgmAssembly {
AssemblyHelperResult::ModeCommandingDone => {
if self.commanding_helper.target_mode.is_some() {
// Complete the mode command.
self.handle_mode_reached(self.mode_requestor_info)?;
self.mode_and_submode = self.commanding_helper.target_mode.take().unwrap();
self.handle_mode_reached(self.mode_requestor_info)?;
}
}
}
@ -874,7 +914,7 @@ impl MgmAssembly {
impl ModeNode for MgmAssembly {
fn id(&self) -> ComponentId {
TestComponentId::MagnetometerAssembly as u64
Self::id()
}
}
impl ModeParent for MgmAssembly {
@ -982,7 +1022,7 @@ impl ModeRequestHandler for MgmAssembly {
struct DeviceManager {
name: &'static str,
pub id: ComponentId,
pub commanding_helper: DevManagerCommandingHelper,
pub commanding_helper: AssemblyCommandingHelper,
pub mode_node: ModeRequestorAndHandlerMpscBounded,
pub mode_requestor_info: Option<MessageMetadata>,
pub mode_and_submode: ModeAndSubmode,
@ -1003,8 +1043,8 @@ impl DeviceManager {
mode_requestor_info: None,
commanding_helper: Default::default(),
mode_and_submode: UNKNOWN_MODE,
mode_req_mock: Default::default(),
mode_reply_mock: Default::default(),
mode_req_mock: ModeRequestHandlerMock::new(id),
mode_reply_mock: ModeReplyHandlerMock::new(id),
}
}
@ -1041,6 +1081,18 @@ impl DeviceManager {
AssemblyHelperResult::TargetKeepingViolation(_id) => {
// TODO: Check whether enough children are available to keep the mode.
// Otherwise, we command everything OFF, because we can not keep the mode.
if self
.commanding_helper
.count_number_of_children_with_target_mode()
.unwrap()
< 1
{
if let Err(_e) = self.start_transition(
MessageMetadata::new(0, self.id()),
ModeAndSubmode::new(DefaultMode::OFF as Mode, 0),
false,
) {}
}
}
AssemblyHelperResult::ModeCommandingDone => {
if self.commanding_helper.target_mode.is_some() {
@ -1179,7 +1231,7 @@ impl CommonDevice {
id,
mode_node,
mode_and_submode: UNKNOWN_MODE,
mode_req_mock: Default::default(),
mode_req_mock: ModeRequestHandlerMock::new(id),
}
}
@ -1302,7 +1354,7 @@ impl AcsController {
mode_node,
mode_and_submode: UNKNOWN_MODE,
announce_mode_queue: Default::default(),
mode_req_mock: Default::default(),
mode_req_mock: ModeRequestHandlerMock::new(TestComponentId::AcsController as u64),
}
}
pub fn run(&mut self) {
@ -1508,7 +1560,7 @@ impl TreeTestbench {
let mut pus_service = PusModeService {
request_id_counter: Cell::new(0),
mode_node: mode_node_pus,
mode_reply_mock: Default::default(),
mode_reply_mock: ModeReplyHandlerMock::new(TestComponentId::PusModeService as u64),
};
// ACS subsystem tables
@ -1767,6 +1819,17 @@ fn command_safe_mode() {
drop(handle_mode_reached_ref);
assert_eq!(mock.send_mode_reply_calls.borrow().len(), 1);
let mode_reply_call = *mock.send_mode_reply_calls.borrow_mut().front().unwrap();
assert_eq!(mode_reply_call.0.request_id(), request_id);
if let ModeReply::ModeReply(mode_and_submode) = mode_reply_call.1 {
assert_eq!(
mode_and_submode, expected_mode_for_transition,
"unexpected mode for component {}",
mock.id
);
} else {
panic!("Unexpected mode reply for component {}", mock.id);
}
// TODO: Check all mode replies
assert_eq!(mock.mode_messages_received(), 3);
mock.clear();
@ -1776,6 +1839,15 @@ fn command_safe_mode() {
&mut tb.subsystem.mode_req_mock,
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
);
assert!(tb.subsystem.subsystem_helper.active_request_id.is_none());
assert_eq!(
tb.subsystem.subsystem_helper.state,
ModeTreeHelperState::TargetKeeping
);
assert_eq!(
tb.subsystem.subsystem_helper.current_mode,
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
);
generic_mock_check(
&mut tb.ctrl.mode_req_mock,
ModeAndSubmode::new(AcsMode::SAFE as u32, 0),