1use crate::pus::{
2 PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmWrapper,
3};
4use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
5use spacepackets::ecss::PusPacket;
6use spacepackets::SpHeader;
7
8use super::{EcssTcInMemConverter, PusServiceBase, PusServiceHelper};
9
10pub struct PusService17TestHandler<TcInMemConverter: EcssTcInMemConverter> {
13 pub service_helper: PusServiceHelper<TcInMemConverter>,
14}
15
16impl<TcInMemConverter: EcssTcInMemConverter> PusService17TestHandler<TcInMemConverter> {
17 pub fn new(service_helper: PusServiceHelper<TcInMemConverter>) -> Self {
18 Self { service_helper }
19 }
20
21 pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
22 let possible_packet = self.service_helper.retrieve_and_accept_next_packet()?;
23 if possible_packet.is_none() {
24 return Ok(PusPacketHandlerResult::Empty);
25 }
26 let ecss_tc_and_token = possible_packet.unwrap();
27 let tc = self
28 .service_helper
29 .tc_in_mem_converter
30 .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?;
31 if tc.service() != 17 {
32 return Err(PusPacketHandlingError::WrongService(tc.service()));
33 }
34 if tc.subservice() == 1 {
35 let mut partial_error = None;
36 let time_stamp = PusServiceBase::get_current_timestamp(&mut partial_error);
37 let result = self
38 .service_helper
39 .common
40 .verification_handler
41 .get_mut()
42 .start_success(ecss_tc_and_token.token, Some(&time_stamp))
43 .map_err(|_| PartialPusHandlingError::Verification);
44 let start_token = if let Ok(result) = result {
45 Some(result)
46 } else {
47 partial_error = Some(result.unwrap_err());
48 None
49 };
50 let mut reply_header =
52 SpHeader::tm_unseg(self.service_helper.common.tm_apid, 0, 0).unwrap();
53 let tc_header = PusTmSecondaryHeader::new_simple(17, 2, &time_stamp);
54 let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true);
55 let result = self
56 .service_helper
57 .common
58 .tm_sender
59 .send_tm(PusTmWrapper::Direct(ping_reply))
60 .map_err(PartialPusHandlingError::TmSend);
61 if let Err(err) = result {
62 partial_error = Some(err);
63 }
64
65 if let Some(start_token) = start_token {
66 if self
67 .service_helper
68 .common
69 .verification_handler
70 .get_mut()
71 .completion_success(start_token, Some(&time_stamp))
72 .is_err()
73 {
74 partial_error = Some(PartialPusHandlingError::Verification)
75 }
76 }
77 if let Some(partial_error) = partial_error {
78 return Ok(PusPacketHandlerResult::RequestHandledPartialSuccess(
79 partial_error,
80 ));
81 };
82 } else {
83 return Ok(PusPacketHandlerResult::CustomSubservice(
84 tc.subservice(),
85 ecss_tc_and_token.token,
86 ));
87 }
88 Ok(PusPacketHandlerResult::RequestHandled)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::pus::tests::{
95 PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon, PusTestHarness,
96 SimplePusPacketHandler, TEST_APID,
97 };
98 use crate::pus::verification::RequestId;
99 use crate::pus::verification::{TcStateAccepted, VerificationToken};
100 use crate::pus::{
101 EcssTcInSharedStoreConverter, EcssTcInVecConverter, PusPacketHandlerResult,
102 PusPacketHandlingError,
103 };
104 use delegate::delegate;
105 use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
106 use spacepackets::ecss::tm::PusTmReader;
107 use spacepackets::ecss::PusPacket;
108 use spacepackets::{SequenceFlags, SpHeader};
109
110 use super::PusService17TestHandler;
111
112 struct Pus17HandlerWithStoreTester {
113 common: PusServiceHandlerWithSharedStoreCommon,
114 handler: PusService17TestHandler<EcssTcInSharedStoreConverter>,
115 }
116
117 impl Pus17HandlerWithStoreTester {
118 pub fn new() -> Self {
119 let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
120 let pus_17_handler = PusService17TestHandler::new(srv_handler);
121 Self {
122 common,
123 handler: pus_17_handler,
124 }
125 }
126 }
127
128 impl PusTestHarness for Pus17HandlerWithStoreTester {
129 delegate! {
130 to self.common {
131 fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
132 fn read_next_tm(&mut self) -> PusTmReader<'_>;
133 fn check_no_tm_available(&self) -> bool;
134 fn check_next_verification_tm(
135 &self,
136 subservice: u8,
137 expected_request_id: RequestId
138 );
139 }
140 }
141 }
142 impl SimplePusPacketHandler for Pus17HandlerWithStoreTester {
143 delegate! {
144 to self.handler {
145 fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError>;
146 }
147 }
148 }
149
150 struct Pus17HandlerWithVecTester {
151 common: PusServiceHandlerWithVecCommon,
152 handler: PusService17TestHandler<EcssTcInVecConverter>,
153 }
154
155 impl Pus17HandlerWithVecTester {
156 pub fn new() -> Self {
157 let (common, srv_handler) = PusServiceHandlerWithVecCommon::new();
158 Self {
159 common,
160 handler: PusService17TestHandler::new(srv_handler),
161 }
162 }
163 }
164
165 impl PusTestHarness for Pus17HandlerWithVecTester {
166 delegate! {
167 to self.common {
168 fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
169 fn read_next_tm(&mut self) -> PusTmReader<'_>;
170 fn check_no_tm_available(&self) -> bool;
171 fn check_next_verification_tm(
172 &self,
173 subservice: u8,
174 expected_request_id: RequestId,
175 );
176 }
177 }
178 }
179 impl SimplePusPacketHandler for Pus17HandlerWithVecTester {
180 delegate! {
181 to self.handler {
182 fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError>;
183 }
184 }
185 }
186
187 fn ping_test(test_harness: &mut (impl PusTestHarness + SimplePusPacketHandler)) {
188 let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
190 let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
191 let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
192 let token = test_harness.send_tc(&ping_tc);
193 let request_id = token.req_id();
194 let result = test_harness.handle_one_tc();
195 assert!(result.is_ok());
196 test_harness.check_next_verification_tm(1, request_id);
201
202 test_harness.check_next_verification_tm(3, request_id);
204
205 let tm = test_harness.read_next_tm();
207 assert_eq!(tm.service(), 17);
208 assert_eq!(tm.subservice(), 2);
209 assert!(tm.user_data().is_empty());
210
211 test_harness.check_next_verification_tm(7, request_id);
213 }
214
215 #[test]
216 fn test_basic_ping_processing_using_store() {
217 let mut test_harness = Pus17HandlerWithStoreTester::new();
218 ping_test(&mut test_harness);
219 }
220
221 #[test]
222 fn test_basic_ping_processing_using_vec() {
223 let mut test_harness = Pus17HandlerWithVecTester::new();
224 ping_test(&mut test_harness);
225 }
226
227 #[test]
228 fn test_empty_tc_queue() {
229 let mut test_harness = Pus17HandlerWithStoreTester::new();
230 let result = test_harness.handle_one_tc();
231 assert!(result.is_ok());
232 let result = result.unwrap();
233 if let PusPacketHandlerResult::Empty = result {
234 } else {
235 panic!("unexpected result type {result:?}")
236 }
237 }
238
239 #[test]
240 fn test_sending_unsupported_service() {
241 let mut test_harness = Pus17HandlerWithStoreTester::new();
242 let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
243 let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
244 let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
245 test_harness.send_tc(&ping_tc);
246 let result = test_harness.handle_one_tc();
247 assert!(result.is_err());
248 let error = result.unwrap_err();
249 if let PusPacketHandlingError::WrongService(num) = error {
250 assert_eq!(num, 3);
251 } else {
252 panic!("unexpected error type {error}")
253 }
254 }
255
256 #[test]
257 fn test_sending_custom_subservice() {
258 let mut test_harness = Pus17HandlerWithStoreTester::new();
259 let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
260 let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
261 let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
262 test_harness.send_tc(&ping_tc);
263 let result = test_harness.handle_one_tc();
264 assert!(result.is_ok());
265 let result = result.unwrap();
266 if let PusPacketHandlerResult::CustomSubservice(subservice, _) = result {
267 assert_eq!(subservice, 200);
268 } else {
269 panic!("unexpected result type {result:?}")
270 }
271 }
272}