ggen_e2e/
error.rs

1//! Comprehensive error types for E2E testing operations
2//!
3//! Provides type-safe error handling with context for all E2E operations.
4
5use std::io;
6use std::path::PathBuf;
7use std::time::Duration;
8use thiserror::Error;
9
10/// Top-level E2E error type
11#[derive(Debug, Error)]
12pub enum E2EError {
13    #[error("Platform error: {0}")]
14    Platform(#[from] PlatformError),
15
16    #[error("Fixture error: {0}")]
17    Fixture(#[from] FixtureError),
18
19    #[error("Golden file error: {0}")]
20    Golden(#[from] GoldenError),
21
22    #[error("Container error: {0}")]
23    Container(#[from] ContainerError),
24
25    #[error("Runner error: {0}")]
26    Runner(#[from] RunnerError),
27
28    #[error("Test timed out after {0:?}")]
29    Timeout(Duration),
30
31    #[error("Comparison error: {0}")]
32    Comparison(String),
33
34    #[error("IO error: {0}")]
35    Io(#[from] io::Error),
36}
37
38/// Platform detection and capability errors
39#[derive(Debug, Error)]
40pub enum PlatformError {
41    #[error("Unsupported OS: {0}")]
42    UnsupportedOs(String),
43
44    #[error("Unsupported architecture: {0}")]
45    UnsupportedArch(String),
46
47    #[error("Docker is not available on this platform")]
48    DockerUnavailable,
49
50    #[error("Failed to detect current platform: {0}")]
51    DetectionFailed(String),
52}
53
54/// Test fixture loading and validation errors
55#[derive(Debug, Error)]
56pub enum FixtureError {
57    #[error("Fixture not found: {0}")]
58    NotFound(PathBuf),
59
60    #[error("Invalid ggen.toml: {0}")]
61    InvalidManifest(String),
62
63    #[error("Missing required file: {0}")]
64    MissingFile(PathBuf),
65
66    #[error("Failed to copy fixture to temp directory: {0}")]
67    CopyFailed(String),
68
69    #[error("IO error: {0}")]
70    Io(#[from] io::Error),
71
72    #[error("Fixture configuration error: {0}")]
73    Configuration(String),
74}
75
76/// Golden file comparison and validation errors
77#[derive(Debug, Error)]
78pub enum GoldenError {
79    #[error("Golden file not found: {0}")]
80    NotFound(PathBuf),
81
82    #[error("Golden file mismatch for {file}: {reason}")]
83    Mismatch { file: PathBuf, reason: String },
84
85    #[error("Checksum mismatch: expected {expected}, got {actual}")]
86    ChecksumMismatch { expected: String, actual: String },
87
88    #[error("Failed to read golden file: {0}")]
89    ReadFailed(#[from] io::Error),
90
91    #[error("Failed to write golden file: {0}")]
92    WriteFailed(String),
93
94    #[error("Line ending normalization failed: {0}")]
95    LineEndingNormalization(String),
96}
97
98/// Container lifecycle and execution errors
99#[derive(Debug, Error)]
100pub enum ContainerError {
101    #[error("Failed to start container: {0}")]
102    StartFailed(String),
103
104    #[error("Container exited with non-zero code {0}: {1}")]
105    ExitCode(i32, String),
106
107    #[error("Failed to mount volume from {host} to {container}: {reason}")]
108    VolumeMountFailed {
109        host: PathBuf,
110        container: PathBuf,
111        reason: String,
112    },
113
114    #[error("Failed to inject ggen binary into container: {0}")]
115    BinaryInjectionFailed(String),
116
117    #[error("Container cleanup failed: {0}")]
118    CleanupFailed(String),
119
120    #[error("Failed to capture container logs: {0}")]
121    LogCaptureFailed(String),
122
123    #[error("Container operation timed out after {0:?}")]
124    Timeout(Duration),
125
126    #[error("Container configuration error: {0}")]
127    Configuration(String),
128}
129
130/// Test runner and execution errors
131#[derive(Debug, Error)]
132pub enum RunnerError {
133    #[error("ggen sync failed: {0}")]
134    SyncFailed(String),
135
136    #[error("Container error: {0}")]
137    Container(#[from] ContainerError),
138
139    #[error("Failed to locate ggen binary: {0}")]
140    BinaryNotFound(String),
141
142    #[error("Test execution error: {0}")]
143    ExecutionFailed(String),
144
145    #[error("Output capture failed: {0}")]
146    OutputCaptureFailed(String),
147
148    #[error("IO error: {0}")]
149    Io(#[from] io::Error),
150
151    #[error("Platform error: {0}")]
152    Platform(#[from] PlatformError),
153
154    #[error("Test runner configuration error: {0}")]
155    Configuration(String),
156}
157
158/// Result type for E2E operations
159pub type Result<T> = std::result::Result<T, E2EError>;
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test_platform_error_display() {
167        let err = PlatformError::UnsupportedOs("FreeBSD".to_string());
168        assert_eq!(err.to_string(), "Unsupported OS: FreeBSD");
169    }
170
171    #[test]
172    fn test_fixture_error_not_found() {
173        let path = PathBuf::from("/nonexistent/fixture");
174        let err = FixtureError::NotFound(path.clone());
175        assert!(err.to_string().contains("Fixture not found"));
176    }
177
178    #[test]
179    fn test_error_conversion() {
180        let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
181        let fixture_err: FixtureError = io_err.into();
182        assert!(fixture_err.to_string().contains("IO error"));
183    }
184}