1use std::fmt;
6
7#[derive(Debug)]
9pub enum LinuxError {
10 Xsk(XskError),
12 Umem(UmemError),
14 Ring(RingError),
16 Descriptor(DescriptorError),
18 Syscall {
20 syscall: &'static str,
22 errno: i32,
24 },
25 InsufficientResources(String),
27 Unsupported(String),
29}
30
31impl fmt::Display for LinuxError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 LinuxError::Xsk(e) => write!(f, "AF_XDP error: {}", e),
35 LinuxError::Umem(e) => write!(f, "UMEM error: {}", e),
36 LinuxError::Ring(e) => write!(f, "Ring error: {}", e),
37 LinuxError::Descriptor(e) => write!(f, "Descriptor error: {}", e),
38 LinuxError::Syscall { syscall, errno } => {
39 write!(f, "Syscall '{}' failed with errno {}", syscall, errno)
40 }
41 LinuxError::InsufficientResources(msg) => {
42 write!(f, "Insufficient resources: {}", msg)
43 }
44 LinuxError::Unsupported(msg) => write!(f, "Unsupported: {}", msg),
45 }
46 }
47}
48
49impl std::error::Error for LinuxError {}
50
51impl From<XskError> for LinuxError {
52 fn from(e: XskError) -> Self {
53 LinuxError::Xsk(e)
54 }
55}
56
57impl From<UmemError> for LinuxError {
58 fn from(e: UmemError) -> Self {
59 LinuxError::Umem(e)
60 }
61}
62
63impl From<RingError> for LinuxError {
64 fn from(e: RingError) -> Self {
65 LinuxError::Ring(e)
66 }
67}
68
69impl From<DescriptorError> for LinuxError {
70 fn from(e: DescriptorError) -> Self {
71 LinuxError::Descriptor(e)
72 }
73}
74
75#[derive(Debug)]
77pub enum XskError {
78 SocketCreate(String),
80 SocketOption(String),
82 BindFailed(String),
84 QueueNotFound(u32),
86 AlreadyBound,
88 NotBound,
90 CloseFailed(String),
92 NotifyFailed(String),
94 InvalidDescriptor(u64),
96 InvalidState(String),
98}
99
100impl fmt::Display for XskError {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 match self {
103 XskError::SocketCreate(msg) => write!(f, "Socket creation failed: {}", msg),
104 XskError::SocketOption(msg) => write!(f, "Socket option failed: {}", msg),
105 XskError::BindFailed(msg) => write!(f, "Bind failed: {}", msg),
106 XskError::QueueNotFound(q) => write!(f, "Queue not found: {}", q),
107 XskError::AlreadyBound => write!(f, "XSK already bound"),
108 XskError::NotBound => write!(f, "XSK not bound"),
109 XskError::CloseFailed(msg) => write!(f, "Close failed: {}", msg),
110 XskError::NotifyFailed(msg) => write!(f, "XSK wakeup notify failed: {}", msg),
111 XskError::InvalidDescriptor(d) => write!(f, "Invalid descriptor: {}", d),
112 XskError::InvalidState(msg) => write!(f, "Invalid XSK state: {}", msg),
113 }
114 }
115}
116
117impl std::error::Error for XskError {}
118
119#[derive(Debug)]
121pub enum UmemError {
122 MmapFailed(String),
124 LockFailed(String),
126 NotAligned {
128 actual: usize,
130 expected: usize,
132 },
133 InsufficientSize {
135 actual: usize,
137 required: usize,
139 },
140 HugePageNotAvailable,
142 AlreadyCreated,
144 NotCreated,
146 MunmapFailed(String),
148}
149
150impl fmt::Display for UmemError {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 match self {
153 UmemError::MmapFailed(msg) => write!(f, "mmap failed: {}", msg),
154 UmemError::LockFailed(msg) => write!(f, "mlock failed: {}", msg),
155 UmemError::NotAligned { actual, expected } => {
156 write!(f, "Memory not aligned: actual {}, expected {}", actual, expected)
157 }
158 UmemError::InsufficientSize { actual, required } => {
159 write!(
160 f,
161 "Insufficient memory: actual {} bytes, required {} bytes",
162 actual, required
163 )
164 }
165 UmemError::HugePageNotAvailable => write!(f, "HugePage not available"),
166 UmemError::AlreadyCreated => write!(f, "UMEM already created"),
167 UmemError::NotCreated => write!(f, "UMEM not created"),
168 UmemError::MunmapFailed(msg) => write!(f, "munmap failed: {}", msg),
169 }
170 }
171}
172
173impl std::error::Error for UmemError {}
174
175#[derive(Debug)]
177pub enum RingError {
178 RingFull,
180 RingEmpty,
182 InvalidDescriptor(u64),
184 IndexOutOfBounds {
186 index: u32,
188 capacity: u32,
190 },
191 ProducerConsumerConflict,
193 BatchSizeExceeded {
195 requested: u32,
197 maximum: u32,
199 },
200 InvalidOffsets(String),
202}
203
204impl fmt::Display for RingError {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 match self {
207 RingError::RingFull => write!(f, "Ring is full"),
208 RingError::RingEmpty => write!(f, "Ring is empty"),
209 RingError::InvalidDescriptor(d) => write!(f, "Invalid descriptor: {}", d),
210 RingError::IndexOutOfBounds { index, capacity } => {
211 write!(
212 f,
213 "Ring index {} out of bounds (capacity {})",
214 index, capacity
215 )
216 }
217 RingError::ProducerConsumerConflict => {
218 write!(f, "Producer-consumer conflict")
219 }
220 RingError::BatchSizeExceeded { requested, maximum } => {
221 write!(
222 f,
223 "Batch size {} exceeded maximum {}",
224 requested, maximum
225 )
226 }
227 RingError::InvalidOffsets(msg) => write!(f, "Invalid ring offsets: {}", msg),
228 }
229 }
230}
231
232impl std::error::Error for RingError {}
233
234#[derive(Debug)]
236pub enum DescriptorError {
237 ZeroDescriptor,
239 OutOfRange {
241 descriptor: u64,
243 max_valid: u64,
245 },
246 AlreadyFreed(u64),
248 AlreadyInUse(u64),
250 AlreadyAllocated(u64),
252 InvalidCapacity(u64),
254 OwnershipMismatch {
256 expected: u32,
258 actual: u32,
260 },
261 GenerationMismatch {
263 expected: u64,
265 actual: u64,
267 },
268 InvalidFrameShift(u32),
274 TransactionFailed(String),
276}
277
278impl fmt::Display for DescriptorError {
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 match self {
281 DescriptorError::ZeroDescriptor => write!(f, "Zero descriptor (invalid)"),
282 DescriptorError::OutOfRange {
283 descriptor,
284 max_valid,
285 } => write!(
286 f,
287 "Descriptor {} out of range (max valid: {})",
288 descriptor, max_valid
289 ),
290 DescriptorError::AlreadyFreed(d) => write!(f, "Descriptor {} already freed", d),
291 DescriptorError::AlreadyInUse(d) => write!(f, "Descriptor {} already in use", d),
292 DescriptorError::AlreadyAllocated(frame) => {
295 write!(f, "Frame {} already allocated", frame)
296 }
297 DescriptorError::InvalidCapacity(c) => write!(
298 f,
299 "Descriptor capacity {c} exceeds 20-bit frame index domain (max 2^20 frames)"
300 ),
301 DescriptorError::OwnershipMismatch { expected, actual } => {
302 write!(
303 f,
304 "Ownership mismatch: expected {}, actual {}",
305 expected, actual
306 )
307 }
308 DescriptorError::InvalidFrameShift(shift) => write!(
309 f,
310 "Invalid frame_shift {shift}: must be in 11..=15 (frame size 2048..=32768 bytes)"
311 ),
312 DescriptorError::GenerationMismatch { expected, actual } => {
313 write!(
314 f,
315 "Generation mismatch: expected {}, actual {}",
316 expected, actual
317 )
318 }
319 DescriptorError::TransactionFailed(msg) => {
320 write!(f, "Transaction failed: {}", msg)
321 }
322 }
323 }
324}
325
326impl std::error::Error for DescriptorError {}
327
328pub type Result<T> = std::result::Result<T, LinuxError>;
330
331pub use zenith_foundation::error::ErrorSeverity;
335
336impl LinuxError {
337 pub fn severity(&self) -> ErrorSeverity {
339 match self {
340 LinuxError::Syscall { .. } => ErrorSeverity::Error,
341 LinuxError::InsufficientResources(_) => ErrorSeverity::Critical,
342 LinuxError::Unsupported(_) => ErrorSeverity::Critical,
343 LinuxError::Xsk(e) => e.severity(),
344 LinuxError::Umem(e) => e.severity(),
345 LinuxError::Ring(e) => e.severity(),
346 LinuxError::Descriptor(e) => e.severity(),
347 }
348 }
349
350 pub fn is_syscall_error(&self) -> bool {
352 matches!(self, LinuxError::Syscall { .. })
353 }
354
355 pub fn is_config_error(&self) -> bool {
357 matches!(
358 self,
359 LinuxError::Xsk(XskError::SocketOption(_))
360 | LinuxError::Umem(UmemError::NotAligned { .. })
361 | LinuxError::Umem(UmemError::InsufficientSize { .. })
362 | LinuxError::Ring(RingError::BatchSizeExceeded { .. })
363 | LinuxError::Descriptor(DescriptorError::OutOfRange { .. })
364 )
365 }
366
367 pub fn is_resource_error(&self) -> bool {
369 matches!(
370 self,
371 LinuxError::InsufficientResources(_)
372 | LinuxError::Umem(UmemError::MmapFailed(_))
373 | LinuxError::Umem(UmemError::LockFailed(_))
374 | LinuxError::Ring(RingError::RingFull)
375 | LinuxError::Ring(RingError::RingEmpty)
376 )
377 }
378}
379
380impl XskError {
381 pub fn severity(&self) -> ErrorSeverity {
383 match self {
384 XskError::SocketCreate(_) => ErrorSeverity::Critical,
385 XskError::SocketOption(_) => ErrorSeverity::Error,
386 XskError::BindFailed(_) => ErrorSeverity::Error,
387 XskError::QueueNotFound(_) => ErrorSeverity::Warning,
388 XskError::AlreadyBound => ErrorSeverity::Warning,
389 XskError::NotBound => ErrorSeverity::Warning,
390 XskError::CloseFailed(_) => ErrorSeverity::Warning,
391 XskError::NotifyFailed(_) => ErrorSeverity::Error,
392 XskError::InvalidDescriptor(_) => ErrorSeverity::Error,
393 XskError::InvalidState(_) => ErrorSeverity::Warning,
394 }
395 }
396}
397
398impl UmemError {
399 pub fn severity(&self) -> ErrorSeverity {
401 match self {
402 UmemError::MmapFailed(_) => ErrorSeverity::Critical,
403 UmemError::LockFailed(_) => ErrorSeverity::Error,
404 UmemError::NotAligned { .. } => ErrorSeverity::Error,
405 UmemError::InsufficientSize { .. } => ErrorSeverity::Error,
406 UmemError::HugePageNotAvailable => ErrorSeverity::Warning,
407 UmemError::AlreadyCreated => ErrorSeverity::Warning,
408 UmemError::NotCreated => ErrorSeverity::Warning,
409 UmemError::MunmapFailed(_) => ErrorSeverity::Warning,
410 }
411 }
412}
413
414impl RingError {
415 pub fn severity(&self) -> ErrorSeverity {
417 match self {
418 RingError::RingFull => ErrorSeverity::Warning,
419 RingError::RingEmpty => ErrorSeverity::Info,
420 RingError::InvalidDescriptor(_) => ErrorSeverity::Error,
421 RingError::IndexOutOfBounds { .. } => ErrorSeverity::Error,
422 RingError::ProducerConsumerConflict => ErrorSeverity::Critical,
423 RingError::BatchSizeExceeded { .. } => ErrorSeverity::Warning,
424 RingError::InvalidOffsets(_) => ErrorSeverity::Error,
425 }
426 }
427}
428
429impl DescriptorError {
430 pub fn severity(&self) -> ErrorSeverity {
432 match self {
433 DescriptorError::ZeroDescriptor => ErrorSeverity::Error,
434 DescriptorError::OutOfRange { .. } => ErrorSeverity::Error,
435 DescriptorError::AlreadyFreed(_) => ErrorSeverity::Warning,
436 DescriptorError::AlreadyInUse(_) => ErrorSeverity::Warning,
437 DescriptorError::AlreadyAllocated(_) => ErrorSeverity::Warning,
438 DescriptorError::InvalidCapacity(_) => ErrorSeverity::Error,
439 DescriptorError::OwnershipMismatch { .. } => ErrorSeverity::Error,
440 DescriptorError::InvalidFrameShift(_) => ErrorSeverity::Error,
441 DescriptorError::GenerationMismatch { .. } => ErrorSeverity::Warning,
442 DescriptorError::TransactionFailed(_) => ErrorSeverity::Error,
443 }
444 }
445}
446
447impl From<LinuxError> for std::io::Error {
448 fn from(err: LinuxError) -> Self {
449 match err {
450 LinuxError::Syscall { errno, .. } => std::io::Error::from_raw_os_error(errno),
451 LinuxError::Umem(UmemError::MmapFailed(msg)) => {
452 std::io::Error::new(std::io::ErrorKind::OutOfMemory, msg)
453 }
454 LinuxError::Umem(UmemError::LockFailed(msg)) => {
455 std::io::Error::new(std::io::ErrorKind::PermissionDenied, msg)
456 }
457 LinuxError::InsufficientResources(msg) => {
458 std::io::Error::new(std::io::ErrorKind::OutOfMemory, msg)
459 }
460 other => std::io::Error::other(other.to_string()),
461 }
462 }
463}
464
465#[cfg(test)]
466mod tests {
467 use super::*;
468
469 #[test]
470 fn test_linux_error_xsk_display() {
471 let err = LinuxError::Xsk(XskError::SocketCreate("test error".to_string()));
472 let display = format!("{}", err);
473 assert!(display.contains("AF_XDP error"));
474 assert!(display.contains("Socket creation failed"));
475 assert!(display.contains("test error"));
476 }
477
478 #[test]
479 fn test_linux_error_umem_display() {
480 let err = LinuxError::Umem(UmemError::MmapFailed("mmap test".to_string()));
481 let display = format!("{}", err);
482 assert!(display.contains("UMEM error"));
483 assert!(display.contains("mmap failed"));
484 assert!(display.contains("mmap test"));
485 }
486
487 #[test]
488 fn test_linux_error_ring_display() {
489 let err = LinuxError::Ring(RingError::RingFull);
490 let display = format!("{}", err);
491 assert!(display.contains("Ring error"));
492 assert!(display.contains("Ring is full"));
493 }
494
495 #[test]
496 fn test_linux_error_descriptor_display() {
497 let err = LinuxError::Descriptor(DescriptorError::ZeroDescriptor);
498 let display = format!("{}", err);
499 assert!(display.contains("Descriptor error"));
500 assert!(display.contains("Zero descriptor"));
501 }
502
503 #[test]
504 fn test_linux_error_syscall_display() {
505 let err = LinuxError::Syscall {
506 syscall: "socket",
507 errno: 13,
508 };
509 let display = format!("{}", err);
510 assert!(display.contains("Syscall 'socket' failed"));
511 assert!(display.contains("errno 13"));
512 }
513
514 #[test]
515 fn test_linux_error_insufficient_resources_display() {
516 let err = LinuxError::InsufficientResources("out of memory".to_string());
517 let display = format!("{}", err);
518 assert!(display.contains("Insufficient resources"));
519 assert!(display.contains("out of memory"));
520 }
521
522 #[test]
523 fn test_linux_error_unsupported_display() {
524 let err = LinuxError::Unsupported("feature not available".to_string());
525 let display = format!("{}", err);
526 assert!(display.contains("Unsupported"));
527 assert!(display.contains("feature not available"));
528 }
529
530 #[test]
531 fn test_xsk_error_variants_display() {
532 let cases = vec![
533 (
534 XskError::SocketCreate("a".to_string()),
535 "Socket creation failed",
536 ),
537 (
538 XskError::SocketOption("b".to_string()),
539 "Socket option failed",
540 ),
541 (XskError::BindFailed("c".to_string()), "Bind failed"),
542 (XskError::QueueNotFound(5), "Queue not found: 5"),
543 (XskError::AlreadyBound, "XSK already bound"),
544 (XskError::NotBound, "XSK not bound"),
545 (XskError::CloseFailed("d".to_string()), "Close failed"),
546 (
547 XskError::NotifyFailed("e".to_string()),
548 "XSK wakeup notify failed",
549 ),
550 (XskError::InvalidDescriptor(42), "Invalid descriptor: 42"),
551 ];
552
553 for (err, expected) in cases {
554 let display = format!("{}", err);
555 assert!(display.contains(expected), "Expected '{}' in '{}'", expected, display);
556 }
557 }
558
559 #[test]
560 fn test_umem_error_variants_display() {
561 let cases = vec![
562 (UmemError::MmapFailed("a".to_string()), "mmap failed"),
563 (UmemError::LockFailed("b".to_string()), "mlock failed"),
564 (
565 UmemError::NotAligned {
566 actual: 100,
567 expected: 4096,
568 },
569 "Memory not aligned",
570 ),
571 (
572 UmemError::InsufficientSize {
573 actual: 100,
574 required: 200,
575 },
576 "Insufficient memory",
577 ),
578 (UmemError::HugePageNotAvailable, "HugePage not available"),
579 (UmemError::AlreadyCreated, "UMEM already created"),
580 (UmemError::NotCreated, "UMEM not created"),
581 (UmemError::MunmapFailed("c".to_string()), "munmap failed"),
582 ];
583
584 for (err, expected) in cases {
585 let display = format!("{}", err);
586 assert!(display.contains(expected), "Expected '{}' in '{}'", expected, display);
587 }
588 }
589
590 #[test]
591 fn test_ring_error_variants_display() {
592 let cases = vec![
593 (RingError::RingFull, "Ring is full"),
594 (RingError::RingEmpty, "Ring is empty"),
595 (RingError::InvalidDescriptor(123), "Invalid descriptor: 123"),
596 (
597 RingError::IndexOutOfBounds {
598 index: 10,
599 capacity: 5,
600 },
601 "Ring index 10 out of bounds",
602 ),
603 (RingError::ProducerConsumerConflict, "Producer-consumer conflict"),
604 (
605 RingError::BatchSizeExceeded {
606 requested: 100,
607 maximum: 50,
608 },
609 "Batch size 100 exceeded maximum 50",
610 ),
611 ];
612
613 for (err, expected) in cases {
614 let display = format!("{}", err);
615 assert!(display.contains(expected), "Expected '{}' in '{}'", expected, display);
616 }
617 }
618
619 #[test]
620 fn test_descriptor_error_variants_display() {
621 let cases = vec![
622 (DescriptorError::ZeroDescriptor, "Zero descriptor"),
623 (
624 DescriptorError::OutOfRange {
625 descriptor: 100,
626 max_valid: 50,
627 },
628 "Descriptor 100 out of range",
629 ),
630 (DescriptorError::AlreadyFreed(42), "Descriptor 42 already freed"),
631 (DescriptorError::AlreadyInUse(99), "Descriptor 99 already in use"),
632 (
633 DescriptorError::AlreadyAllocated(7),
634 "Frame 7 already allocated",
635 ),
636 (
637 DescriptorError::InvalidCapacity(1 << 21),
638 "exceeds 20-bit frame index domain",
639 ),
640 (
641 DescriptorError::OwnershipMismatch {
642 expected: 1,
643 actual: 2,
644 },
645 "Ownership mismatch",
646 ),
647 (
648 DescriptorError::GenerationMismatch {
649 expected: 3,
650 actual: 5,
651 },
652 "Generation mismatch",
653 ),
654 (
655 DescriptorError::TransactionFailed("tx fail".to_string()),
656 "Transaction failed",
657 ),
658 ];
659
660 for (err, expected) in cases {
661 let display = format!("{}", err);
662 assert!(display.contains(expected), "Expected '{}' in '{}'", expected, display);
663 }
664 }
665
666 #[test]
667 fn test_error_from_conversions() {
668 let xsk_err = XskError::AlreadyBound;
669 let linux_err: LinuxError = xsk_err.into();
670 assert!(matches!(linux_err, LinuxError::Xsk(XskError::AlreadyBound)));
671
672 let umem_err = UmemError::NotCreated;
673 let linux_err: LinuxError = umem_err.into();
674 assert!(matches!(linux_err, LinuxError::Umem(UmemError::NotCreated)));
675
676 let ring_err = RingError::RingFull;
677 let linux_err: LinuxError = ring_err.into();
678 assert!(matches!(linux_err, LinuxError::Ring(RingError::RingFull)));
679
680 let desc_err = DescriptorError::ZeroDescriptor;
681 let linux_err: LinuxError = desc_err.into();
682 assert!(matches!(
683 linux_err,
684 LinuxError::Descriptor(DescriptorError::ZeroDescriptor)
685 ));
686 }
687
688 #[test]
689 fn test_error_severity() {
690 assert_eq!(
691 LinuxError::Syscall {
692 syscall: "test",
693 errno: 1
694 }
695 .severity(),
696 ErrorSeverity::Error
697 );
698 assert_eq!(
699 LinuxError::InsufficientResources("x".to_string()).severity(),
700 ErrorSeverity::Critical
701 );
702 assert_eq!(
703 LinuxError::Unsupported("x".to_string()).severity(),
704 ErrorSeverity::Critical
705 );
706 assert_eq!(
707 LinuxError::Xsk(XskError::SocketCreate("x".to_string())).severity(),
708 ErrorSeverity::Critical
709 );
710 assert_eq!(
711 LinuxError::Xsk(XskError::QueueNotFound(0)).severity(),
712 ErrorSeverity::Warning
713 );
714 assert_eq!(
715 LinuxError::Umem(UmemError::MmapFailed("x".to_string())).severity(),
716 ErrorSeverity::Critical
717 );
718 assert_eq!(
719 LinuxError::Umem(UmemError::HugePageNotAvailable).severity(),
720 ErrorSeverity::Warning
721 );
722 assert_eq!(
723 LinuxError::Ring(RingError::RingEmpty).severity(),
724 ErrorSeverity::Info
725 );
726 assert_eq!(
727 LinuxError::Ring(RingError::ProducerConsumerConflict).severity(),
728 ErrorSeverity::Critical
729 );
730 assert_eq!(
731 LinuxError::Descriptor(DescriptorError::ZeroDescriptor).severity(),
732 ErrorSeverity::Error
733 );
734 assert_eq!(
735 LinuxError::Descriptor(DescriptorError::AlreadyFreed(0)).severity(),
736 ErrorSeverity::Warning
737 );
738 }
739
740 #[test]
741 fn test_error_classification() {
742 let syscall_err = LinuxError::Syscall {
743 syscall: "socket",
744 errno: 1,
745 };
746 assert!(syscall_err.is_syscall_error());
747 assert!(!syscall_err.is_config_error());
748 assert!(!syscall_err.is_resource_error());
749
750 let config_err = LinuxError::Umem(UmemError::NotAligned {
751 actual: 100,
752 expected: 4096,
753 });
754 assert!(!config_err.is_syscall_error());
755 assert!(config_err.is_config_error());
756 assert!(!config_err.is_resource_error());
757
758 let resource_err = LinuxError::InsufficientResources("oom".to_string());
759 assert!(!resource_err.is_syscall_error());
760 assert!(!resource_err.is_config_error());
761 assert!(resource_err.is_resource_error());
762
763 let ring_full = LinuxError::Ring(RingError::RingFull);
764 assert!(ring_full.is_resource_error());
765 }
766
767 #[test]
768 fn test_linux_error_to_io_error() {
769 let syscall_err = LinuxError::Syscall {
770 syscall: "test",
771 errno: 12, };
773 let io_err: std::io::Error = syscall_err.into();
774 assert_eq!(io_err.raw_os_error(), Some(12));
775
776 let mmap_err = LinuxError::Umem(UmemError::MmapFailed("failed".to_string()));
777 let io_err: std::io::Error = mmap_err.into();
778 assert_eq!(io_err.kind(), std::io::ErrorKind::OutOfMemory);
779
780 let lock_err = LinuxError::Umem(UmemError::LockFailed("denied".to_string()));
781 let io_err: std::io::Error = lock_err.into();
782 assert_eq!(io_err.kind(), std::io::ErrorKind::PermissionDenied);
783
784 let oom_err = LinuxError::InsufficientResources("oom".to_string());
785 let io_err: std::io::Error = oom_err.into();
786 assert_eq!(io_err.kind(), std::io::ErrorKind::OutOfMemory);
787
788 let other_err = LinuxError::Xsk(XskError::AlreadyBound);
789 let io_err: std::io::Error = other_err.into();
790 assert_eq!(io_err.kind(), std::io::ErrorKind::Other);
791 }
792
793 #[test]
794 fn test_error_trait_implementation() {
795 let err: Box<dyn std::error::Error> =
796 Box::new(LinuxError::Syscall {
797 syscall: "test",
798 errno: 1,
799 });
800 assert!(err.source().is_none());
801
802 let err: Box<dyn std::error::Error> = Box::new(XskError::AlreadyBound);
803 assert!(err.source().is_none());
804
805 let err: Box<dyn std::error::Error> = Box::new(UmemError::NotCreated);
806 assert!(err.source().is_none());
807
808 let err: Box<dyn std::error::Error> = Box::new(RingError::RingEmpty);
809 assert!(err.source().is_none());
810
811 let err: Box<dyn std::error::Error> = Box::new(DescriptorError::ZeroDescriptor);
812 assert!(err.source().is_none());
813 }
814
815 #[test]
816 fn test_result_type_alias() {
817 let ok: Result<i32> = Ok(42);
818 assert!(ok.is_ok());
819
820 let err: Result<i32> = Err(LinuxError::Unsupported("test".to_string()));
821 assert!(err.is_err());
822 }
823
824 #[test]
825 fn test_error_debug_format() {
826 let err = LinuxError::Syscall {
827 syscall: "mmap",
828 errno: 12,
829 };
830 let debug = format!("{:?}", err);
831 assert!(debug.contains("Syscall"));
832 assert!(debug.contains("mmap"));
833 assert!(debug.contains("12"));
834 }
835}