1#[macro_export]
16macro_rules! debug_trace_data {
17 ( $description:expr, $offset:expr, $data:expr, $data_size:expr $(,)? ) => {
18 #[cfg(feature = "debug-trace")]
19 {
20 let mediator = $crate::mediator::Mediator::current();
21
22 if mediator.debug_output {
23 mediator.debug_print(format!(
24 "{} data of size: {} at offset: {} (0x{:08x})\n",
25 $description, $data_size, $offset, $offset
26 ));
27 mediator.debug_print_data($data, true);
28 }
29 }
30 };
31}
32
33#[macro_export]
35macro_rules! debug_trace_data_and_structure {
36 ( $description:expr, $offset:expr, $data:expr, $data_size:expr, $structure:expr $(,)? ) => {
37 #[cfg(feature = "debug-trace")]
38 {
39 let mediator = $crate::mediator::Mediator::current();
40
41 if mediator.debug_output {
42 mediator.debug_print(format!(
43 "{} data of size: {} at offset: {} (0x{:08x})\n",
44 $description, $data_size, $offset, $offset
45 ));
46 mediator.debug_print_data($data, true);
47 mediator.debug_print($structure);
48 }
49 }
50 };
51}
52
53#[macro_export]
55macro_rules! debug_trace_structure {
56 ( $structure:expr $(,)? ) => {
57 #[cfg(feature = "debug-trace")]
58 {
59 let mediator = $crate::mediator::Mediator::current();
60
61 if mediator.debug_output {
62 mediator.debug_print($structure);
63 }
64 }
65 };
66}
67
68#[macro_export]
70macro_rules! error_trace_function {
71 () => {{
72 fn f() {}
73 fn type_name_of<T>(_: T) -> &'static str {
74 std::any::type_name::<T>()
75 }
76 let name = type_name_of(f);
77 name.strip_suffix("::f").unwrap()
78 }};
79}
80
81#[macro_export]
83macro_rules! error_trace_new {
84 ( $message:expr $(,)? ) => {
85 $crate::ErrorTrace::new(format!("{}: {}", $crate::error_trace_function!(), $message))
86 };
87}
88
89#[macro_export]
91macro_rules! error_trace_new_with_error {
92 ( $message:expr, $error:expr $(,)? ) => {
93 $crate::ErrorTrace::new(format!(
94 "{}: {} with error: {}",
95 $crate::error_trace_function!(),
96 $message,
97 $error.to_string(),
98 ))
99 };
100}
101
102#[macro_export]
104macro_rules! error_trace_add_frame {
105 ( $error:expr, $message:expr $(,)? ) => {
106 $error.add_frame(format!("{}: {}", $crate::error_trace_function!(), $message))
107 };
108}
109
110#[macro_export]
112macro_rules! data_stream_get_size {
113 ( $data_stream:expr $(,)? ) => {
114 match $data_stream.write() {
115 Ok(mut data_stream) => match data_stream.get_size() {
116 Ok(size) => size,
117 Err(mut error) => {
118 $crate::error_trace_add_frame!(
119 error,
120 "Unable to determine size of data stream"
121 );
122 return Err(error);
123 }
124 },
125 Err(error) => {
126 return Err($crate::error_trace_new_with_error!(
127 "Unable to obtain write lock on data stream",
128 error
129 ));
130 }
131 }
132 };
133}
134
135#[macro_export]
137macro_rules! data_stream_read_at_position {
138 ( $data_stream:expr, $buf:expr, $pos:expr $(,)? ) => {
139 match $data_stream.write() {
140 Ok(mut data_stream) => match data_stream.read_at_position($buf, $pos) {
141 Ok(read_count) => read_count,
142 Err(mut error) => {
143 $crate::error_trace_add_frame!(error, "Unable to read from data stream");
144 return Err(error);
145 }
146 },
147 Err(error) => {
148 return Err($crate::error_trace_new_with_error!(
149 "Unable to obtain write lock on data stream",
150 error
151 ));
152 }
153 }
154 };
155}
156
157#[macro_export]
159macro_rules! data_stream_read_exact_at_position {
160 ( $data_stream:expr, $buf:expr, $pos:expr $(,)? ) => {
161 match $data_stream.write() {
162 Ok(mut data_stream) => match data_stream.read_exact_at_position($buf, $pos) {
163 Ok(offset) => offset,
164 Err(mut error) => {
165 $crate::error_trace_add_frame!(error, "Unable to read from data stream");
166 return Err(error);
167 }
168 },
169 Err(error) => {
170 return Err($crate::error_trace_new_with_error!(
171 "Unable to obtain write lock on data stream",
172 error
173 ));
174 }
175 }
176 };
177}
178
179#[cfg(test)]
180mod tests {
181 use std::io::SeekFrom;
182 use std::sync::mpsc::channel;
183 use std::sync::{Arc, RwLock};
184 use std::thread::spawn;
185
186 use crate::data_stream::{DataStream, DataStreamReference};
187 use crate::errors::ErrorTrace;
188 use crate::fake_data_stream::open_fake_data_stream;
189
190 struct TestFailingDataStream {}
192
193 impl DataStream for TestFailingDataStream {
194 fn get_offset(&mut self) -> Result<u64, ErrorTrace> {
196 Err(ErrorTrace::new(String::from("test error")))
197 }
198
199 fn get_size(&mut self) -> Result<u64, ErrorTrace> {
201 Err(ErrorTrace::new(String::from("test error")))
202 }
203
204 fn read(&mut self, _buf: &mut [u8]) -> Result<usize, ErrorTrace> {
206 Err(ErrorTrace::new(String::from("test error")))
207 }
208
209 fn seek(&mut self, _pos: SeekFrom) -> Result<u64, ErrorTrace> {
211 Err(ErrorTrace::new(String::from("test error")))
212 }
213 }
214
215 fn get_test_data() -> Vec<u8> {
216 (0..16).collect()
217 }
218
219 fn get_test_data_stream() -> DataStreamReference {
220 open_fake_data_stream(&get_test_data())
221 }
222
223 fn get_test_failing_data_stream() -> DataStreamReference {
224 Arc::new(RwLock::new(TestFailingDataStream {}))
225 }
226
227 fn get_test_poisoned_data_stream() -> DataStreamReference {
228 let data_stream: DataStreamReference = get_test_data_stream();
229 let poisoned_data_stream: DataStreamReference = data_stream.clone();
230 let (sender, receiver) = channel::<()>();
231 let thread = spawn(move || {
232 let _guard = poisoned_data_stream
233 .write()
234 .expect("unable to obtain write lock");
235
236 sender.send(()).expect("unable to send");
237 panic!("poison the data stream");
238 });
239 receiver.recv().expect("unable to receive");
240 let _thread_result = thread.join();
241
242 data_stream
243 }
244
245 fn data_stream_get_size_helper(data_stream: DataStreamReference) -> Result<u64, ErrorTrace> {
247 let size: u64 = data_stream_get_size!(data_stream);
248
249 Ok(size)
250 }
251
252 fn data_stream_read_at_position_helper(
254 data_stream: DataStreamReference,
255 buf: &mut [u8],
256 pos: SeekFrom,
257 ) -> Result<usize, ErrorTrace> {
258 let read_count: usize = data_stream_read_at_position!(data_stream, buf, pos);
259
260 Ok(read_count)
261 }
262
263 fn data_stream_read_exact_at_position_helper(
265 data_stream: DataStreamReference,
266 buf: &mut [u8],
267 pos: SeekFrom,
268 ) -> Result<u64, ErrorTrace> {
269 let offset: u64 = data_stream_read_exact_at_position!(data_stream, buf, pos);
270
271 Ok(offset)
272 }
273
274 #[test]
275 fn test_error_trace_function() {
276 let function_name: &str = error_trace_function!();
277
278 assert!(function_name.contains("test_error_trace_function"));
279 }
280
281 #[test]
282 fn test_error_trace_new() {
283 let error: ErrorTrace = error_trace_new!("test error");
284
285 let error_message: String = error.to_string();
286 assert!(error_message.starts_with("#0 "));
287 assert!(error_message.contains("test_error_trace_new: test error"));
288 }
289
290 #[test]
291 fn test_error_trace_new_with_error() {
292 let error: ErrorTrace = error_trace_new_with_error!(
293 "test message",
294 ErrorTrace::new(String::from("inner error")),
295 );
296
297 let error_message: String = error.to_string();
298 assert!(error_message.starts_with("#0 "));
299 assert!(
300 error_message.contains(
301 "test_error_trace_new_with_error: test message with error: #0 inner error"
302 )
303 );
304 }
305
306 #[test]
307 fn test_error_trace_add_frame() {
308 let mut error: ErrorTrace = ErrorTrace::new(String::from("original error"));
309
310 error_trace_add_frame!(error, "additional frame");
311
312 let error_message: String = error.to_string();
313 assert!(error_message.contains("#0 original error"));
314 assert!(error_message.contains("#1 "));
315 assert!(error_message.contains("test_error_trace_add_frame: additional frame"));
316 }
317
318 #[test]
319 fn test_data_stream_get_size() -> Result<(), ErrorTrace> {
320 let data_stream: DataStreamReference = get_test_data_stream();
321
322 let size: u64 = data_stream_get_size!(data_stream);
323 assert_eq!(size, 16);
324
325 Ok(())
326 }
327
328 #[test]
329 fn test_data_stream_get_size_with_failing_size() {
330 let test_data_stream: DataStreamReference = get_test_failing_data_stream();
331
332 let result: Result<u64, ErrorTrace> = data_stream_get_size_helper(test_data_stream);
333 let error: ErrorTrace = result.expect_err("expected error");
334
335 let error_message: String = error.to_string();
336 assert!(error_message.contains("Unable to determine size of data stream"));
337 assert!(error_message.contains("test error"));
338 }
339
340 #[test]
341 fn test_data_stream_get_size_with_poisoned_data_stream() {
342 let test_data_stream: DataStreamReference = get_test_poisoned_data_stream();
343
344 let result: Result<u64, ErrorTrace> = data_stream_get_size_helper(test_data_stream);
345 let error: ErrorTrace = result.expect_err("expected error");
346
347 let error_message: String = error.to_string();
348 assert!(error_message.contains("Unable to obtain write lock on data stream"));
349 }
350
351 #[test]
352 fn test_data_stream_read_at_position() -> Result<(), ErrorTrace> {
353 let data_stream: DataStreamReference = get_test_data_stream();
354
355 let mut data: Vec<u8> = vec![0; 4];
356 let read_count: usize =
357 data_stream_read_at_position!(data_stream, &mut data, SeekFrom::Start(2));
358
359 assert_eq!(read_count, 4);
360 assert_eq!(&data, &[2, 3, 4, 5]);
361
362 Ok(())
363 }
364
365 #[test]
366 fn test_data_stream_read_at_position_beyond_size() -> Result<(), ErrorTrace> {
367 let data_stream: DataStreamReference = get_test_data_stream();
368
369 let mut data: Vec<u8> = vec![0; 24];
370 let read_count: usize =
371 data_stream_read_at_position!(data_stream, &mut data, SeekFrom::Start(8));
372
373 assert_eq!(read_count, 8);
374 assert_eq!(&data[0..8], &[8, 9, 10, 11, 12, 13, 14, 15]);
375 assert_eq!(&data[8..24], &[0; 16]);
376
377 Ok(())
378 }
379
380 #[test]
381 fn test_data_stream_read_at_position_with_failing_read() {
382 let test_data_stream: DataStreamReference = get_test_failing_data_stream();
383
384 let mut data: Vec<u8> = vec![0; 4];
385 let result: Result<usize, ErrorTrace> =
386 data_stream_read_at_position_helper(test_data_stream, &mut data, SeekFrom::Start(0));
387 let error: ErrorTrace = result.expect_err("expected error");
388
389 let error_message: String = error.to_string();
390 assert!(error_message.contains("Unable to read from data stream"));
391 assert!(error_message.contains("test error"));
392 }
393
394 #[test]
395 fn test_data_stream_read_at_position_with_poisoned_data_stream() {
396 let test_data_stream: DataStreamReference = get_test_poisoned_data_stream();
397
398 let mut data: Vec<u8> = vec![0; 4];
399 let result: Result<usize, ErrorTrace> =
400 data_stream_read_at_position_helper(test_data_stream, &mut data, SeekFrom::Start(0));
401 let error: ErrorTrace = result.expect_err("expected error");
402
403 let error_message: String = error.to_string();
404 assert!(error_message.contains("Unable to obtain write lock on data stream"));
405 }
406
407 #[test]
408 fn test_data_stream_read_exact_at_position() -> Result<(), ErrorTrace> {
409 let data_stream: DataStreamReference = get_test_data_stream();
410
411 let mut data: Vec<u8> = vec![0; 4];
412 let offset: u64 =
413 data_stream_read_exact_at_position!(data_stream, &mut data, SeekFrom::Start(2));
414
415 assert_eq!(offset, 2);
416 assert_eq!(&data, &[2, 3, 4, 5]);
417
418 Ok(())
419 }
420
421 #[test]
422 fn test_data_stream_read_exact_at_position_beyond_size() {
423 let data_stream: DataStreamReference = get_test_data_stream();
424
425 let mut data: Vec<u8> = vec![0; 24];
426 let result: Result<u64, ErrorTrace> =
427 data_stream_read_exact_at_position_helper(data_stream, &mut data, SeekFrom::Start(0));
428 let error: ErrorTrace = result.expect_err("expected error");
429
430 let error_message: String = error.to_string();
431 assert!(error_message.contains("Unable to read the exact amount"));
432 assert!(error_message.contains("Unable to read from data stream"));
433 }
434
435 #[test]
436 fn test_data_stream_read_exact_at_position_with_failing_read() {
437 let test_data_stream: DataStreamReference = get_test_failing_data_stream();
438
439 let mut data: Vec<u8> = vec![0; 4];
440 let result: Result<u64, ErrorTrace> = data_stream_read_exact_at_position_helper(
441 test_data_stream,
442 &mut data,
443 SeekFrom::Start(0),
444 );
445 let error: ErrorTrace = result.expect_err("expected error");
446
447 let error_message: String = error.to_string();
448 assert!(error_message.contains("Unable to read from data stream"));
449 assert!(error_message.contains("test error"));
450 }
451
452 #[cfg(feature = "debug-trace")]
453 #[test]
454 fn test_debug_trace_data() {
455 crate::mediator::Mediator::new(true).make_current();
456
457 let data: Vec<u8> = get_test_data();
458 debug_trace_data!("test data", 0, &data, 16);
459 }
460
461 #[cfg(feature = "debug-trace")]
462 #[test]
463 fn test_debug_trace_data_with_debug_output_disabled() {
464 crate::mediator::Mediator::new(false).make_current();
465
466 let data: Vec<u8> = get_test_data();
467 debug_trace_data!("test data", 0, &data, 16);
468 }
469
470 #[cfg(feature = "debug-trace")]
471 #[test]
472 fn test_debug_trace_data_and_structure() {
473 crate::mediator::Mediator::new(true).make_current();
474
475 let data: Vec<u8> = get_test_data();
476 debug_trace_data_and_structure!("test data", 0, &data, 16, String::from("structure"));
477 }
478
479 #[cfg(feature = "debug-trace")]
480 #[test]
481 fn test_debug_trace_data_and_structure_with_debug_output_disabled() {
482 crate::mediator::Mediator::new(false).make_current();
483
484 let data: Vec<u8> = get_test_data();
485 debug_trace_data_and_structure!("test data", 0, &data, 16, String::from("structure"));
486 }
487
488 #[cfg(feature = "debug-trace")]
489 #[test]
490 fn test_debug_trace_structure() {
491 crate::mediator::Mediator::new(true).make_current();
492
493 debug_trace_structure!(String::from("structure"));
494 }
495
496 #[cfg(feature = "debug-trace")]
497 #[test]
498 fn test_debug_trace_structure_with_debug_output_disabled() {
499 crate::mediator::Mediator::new(false).make_current();
500
501 debug_trace_structure!(String::from("structure"));
502 }
503}