Skip to main content

java_manager/
error.rs

1//! Error types for Java environment detection and execution.
2
3use std::fmt;
4use std::io;
5
6/// Errors that can occur when working with Java installations.
7#[derive(Debug)]
8pub enum JavaError {
9    /// The provided Java path is invalid (does not exist or cannot be used).
10    InvalidJavaPath(String),
11
12    /// A required Java executable or file was not found.
13    NotFound(String),
14
15    /// A stale registry entry points to a path where `java` no longer exists.
16    StaleRegistryEntry(String),
17
18    /// An I/O error occurred (e.g., reading a file or spawning a process).
19    IoError(io::Error),
20
21    /// An error during command execution (e.g., `java -version` failed).
22    ExecuteError(String),
23
24    /// A runtime error, such as unexpected output format.
25    RuntimeError(String),
26
27    /// Execution of a Java process failed (non-zero exit code).
28    ExecutionFailed(String),
29
30    /// An error during Java download.
31    DownloadError(String),
32
33    /// An error during archive extraction.
34    ExtractError(String),
35
36    /// A generic error with a custom message.
37    Other(String),
38}
39
40impl fmt::Display for JavaError {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        match self {
43            JavaError::InvalidJavaPath(msg) => write!(f, "Invalid Java path: {}", msg),
44            JavaError::NotFound(msg) => write!(f, "Not found: {}", msg),
45            JavaError::StaleRegistryEntry(msg) => write!(f, "Stale registry entry: {}", msg),
46            JavaError::IoError(err) => write!(f, "IO error: {}", err),
47            JavaError::ExecuteError(msg) => write!(f, "Execute error: {}", msg),
48            JavaError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
49            JavaError::ExecutionFailed(msg) => write!(f, "Execution failed: {}", msg),
50            JavaError::DownloadError(msg) => write!(f, "Download error: {}", msg),
51            JavaError::ExtractError(msg) => write!(f, "Extraction error: {}", msg),
52            JavaError::Other(msg) => write!(f, "Other error: {}", msg),
53        }
54    }
55}
56
57impl std::error::Error for JavaError {
58    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
59        match self {
60            JavaError::IoError(err) => Some(err),
61            _ => None,
62        }
63    }
64}
65
66impl From<io::Error> for JavaError {
67    fn from(err: io::Error) -> Self {
68        JavaError::IoError(err)
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use std::error::Error;
76
77    #[test]
78    fn test_display_invalid_path() {
79        let err = JavaError::InvalidJavaPath("bad/path".into());
80        assert_eq!(err.to_string(), "Invalid Java path: bad/path");
81    }
82
83    #[test]
84    fn test_display_not_found() {
85        let err = JavaError::NotFound("missing.exe".into());
86        assert_eq!(err.to_string(), "Not found: missing.exe");
87    }
88
89    #[test]
90    fn test_display_stale_registry() {
91        let err = JavaError::StaleRegistryEntry("HKLM\\..".into());
92        assert_eq!(err.to_string(), "Stale registry entry: HKLM\\..");
93    }
94
95    #[test]
96    fn test_display_execution_failed() {
97        let err = JavaError::ExecutionFailed("exit code 1".into());
98        assert_eq!(err.to_string(), "Execution failed: exit code 1");
99    }
100
101    #[test]
102    fn test_display_extract_error() {
103        let err = JavaError::ExtractError("corrupt archive".into());
104        assert_eq!(err.to_string(), "Extraction error: corrupt archive");
105    }
106
107    #[test]
108    fn test_display_download_error() {
109        let err = JavaError::DownloadError("network".into());
110        assert_eq!(err.to_string(), "Download error: network");
111    }
112
113    #[test]
114    fn test_from_io_error() {
115        let io_err = io::Error::new(io::ErrorKind::NotFound, "file missing");
116        let java_err: JavaError = io_err.into();
117        assert!(matches!(java_err, JavaError::IoError(_)));
118        assert!(java_err.to_string().contains("IO error"));
119    }
120
121    #[test]
122    fn test_error_source_io() {
123        let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "denied");
124        let java_err = JavaError::IoError(io_err);
125        assert!(java_err.source().is_some());
126    }
127
128    #[test]
129    fn test_error_source_other_variants() {
130        let err = JavaError::Other("msg".into());
131        assert!(err.source().is_none());
132    }
133
134    #[test]
135    fn test_debug_format() {
136        let err = JavaError::ExecuteError("boom".into());
137        let debug = format!("{err:?}");
138        assert!(debug.contains("ExecuteError"));
139        assert!(debug.contains("boom"));
140    }
141}