1use std::io;
6use std::path::PathBuf;
7use std::time::Duration;
8use thiserror::Error;
9
10#[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#[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#[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#[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#[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#[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
158pub 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}