chrome_for_testing_manager/
error.rs1use crate::{Port, VersionRequest};
2use chrome_for_testing::{Platform, Version};
3use std::{
4 fmt::{Display, Formatter},
5 path::PathBuf,
6 time::Duration,
7};
8use thiserror::Error;
9use tokio::runtime::RuntimeFlavor;
10
11pub type Result<T> = std::result::Result<T, rootcause::Report<ChromeForTestingManagerError>>;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26#[non_exhaustive]
27pub enum ChromeForTestingArtifact {
28 Chrome,
30
31 ChromeHeadlessShell,
33
34 ChromeDriver,
36}
37
38impl Display for ChromeForTestingArtifact {
39 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 match self {
41 Self::Chrome => f.write_str("chrome"),
42 Self::ChromeHeadlessShell => f.write_str("chrome-headless-shell"),
43 Self::ChromeDriver => f.write_str("chromedriver"),
44 }
45 }
46}
47
48#[derive(Debug, Error)]
50#[non_exhaustive]
51pub enum ChromeForTestingManagerError {
52 #[error("chromedriver requires a multi-threaded Tokio runtime; detected {runtime_flavor:?}")]
55 UnsupportedRuntime {
56 runtime_flavor: RuntimeFlavor,
58 },
59
60 #[error("unsupported chrome-for-testing platform")]
62 UnsupportedPlatform,
63
64 #[error("failed to determine cache directory; is $HOME set?")]
67 DetermineCacheDir,
68
69 #[error("failed to create cache directory {}", .cache_dir.display())]
71 CreateCacheDir {
72 cache_dir: PathBuf,
74 },
75
76 #[error("failed to remove cache directory {}", .cache_dir.display())]
78 RemoveCacheDir {
79 cache_dir: PathBuf,
81 },
82
83 #[error("failed to recreate cache directory {}", .cache_dir.display())]
85 RecreateCacheDir {
86 cache_dir: PathBuf,
88 },
89
90 #[error("failed to request versions for {version_request:?}")]
92 RequestVersions {
93 version_request: VersionRequest,
95 },
96
97 #[error("could not determine a version for {version_request:?}")]
99 NoMatchingVersion {
100 version_request: VersionRequest,
102 },
103
104 #[error("at least one Chrome binary must be requested")]
106 EmptyChromeBinaryDownloadRequest,
107
108 #[error("no chrome download for version {version} on {platform}")]
110 NoChromeDownload {
111 version: Version,
113 platform: Platform,
115 },
116
117 #[error("no chrome-headless-shell download for version {version} on {platform}")]
119 NoChromeHeadlessShellDownload {
120 version: Version,
122 platform: Platform,
124 },
125
126 #[error("no chromedriver download for version {version} on {platform}")]
128 NoChromedriverDownload {
129 version: Version,
131 platform: Platform,
133 },
134
135 #[error("failed to create platform directory {}", .platform_dir.display())]
137 CreatePlatformDir {
138 platform_dir: PathBuf,
140 },
141
142 #[error("failed to download {artifact} from {url}")]
145 Download {
146 artifact: ChromeForTestingArtifact,
148 url: String,
150 },
151
152 #[error("failed to create {artifact} download file {}", .path.display())]
154 CreateDownloadFile {
155 artifact: ChromeForTestingArtifact,
157 path: PathBuf,
159 },
160
161 #[error("failed to write {artifact} download chunk")]
163 WriteDownloadFile {
164 artifact: ChromeForTestingArtifact,
166 },
167
168 #[error("failed to flush {artifact} download file")]
170 FlushDownloadFile {
171 artifact: ChromeForTestingArtifact,
173 },
174
175 #[error(
177 "{artifact} download timed out after {consecutive_stalls} consecutive stalls of {chunk_timeout:?}"
178 )]
179 DownloadStalled {
180 artifact: ChromeForTestingArtifact,
182 consecutive_stalls: u32,
184 chunk_timeout: Duration,
186 },
187
188 #[error("failed to open downloaded ZIP archive {}", .path.display())]
190 OpenDownloadedZip {
191 path: PathBuf,
193 },
194
195 #[error("downloaded file {} is not a valid ZIP archive", .path.display())]
197 InvalidZip {
198 path: PathBuf,
200 },
201
202 #[error(
204 "downloaded ZIP archive {} decompressed size {size} exceeds safety limit {max_size}",
205 .path.display()
206 )]
207 ZipTooLarge {
208 path: PathBuf,
210 size: u128,
212 max_size: u128,
214 },
215
216 #[error(
218 "failed to extract ZIP archive {} to {}",
219 .path.display(),
220 .unpack_dir.display()
221 )]
222 ExtractZip {
223 path: PathBuf,
225 unpack_dir: PathBuf,
227 },
228
229 #[error("failed to remove downloaded ZIP archive {}", .path.display())]
231 RemoveDownloadedZip {
232 path: PathBuf,
234 },
235
236 #[error("failed to spawn chromedriver process {}", .path.display())]
239 SpawnChromedriver {
240 path: PathBuf,
242 },
243
244 #[error("failed to spawn browser process {}", .path.display())]
246 SpawnBrowser {
247 path: PathBuf,
249 },
250
251 #[error(
253 "Chrome Headless Shell sessions require a TCP remote debugging port; unsupported argument {arg:?}"
254 )]
255 UnsupportedHeadlessShellRemoteDebuggingArg {
256 arg: String,
258 },
259
260 #[error(
262 "Chrome Headless Shell sessions require --remote-debugging-port=<0-65535>; invalid argument {arg:?}"
263 )]
264 InvalidHeadlessShellRemoteDebuggingPortArg {
265 arg: String,
267 },
268
269 #[error(
271 "Chrome Headless Shell sessions require exactly one TCP remote debugging port; conflicting arguments {first_arg:?} and {second_arg:?}"
272 )]
273 ConflictingHeadlessShellRemoteDebuggingArgs {
274 first_arg: String,
276 second_arg: String,
278 },
279
280 #[error("failed while waiting for chromedriver {} to start", .path.display())]
282 WaitForChromedriverStartup {
283 path: PathBuf,
285 },
286
287 #[error("failed while waiting for browser {} to expose DevTools", .path.display())]
289 WaitForBrowserStartup {
290 path: PathBuf,
292 },
293
294 #[error("failed to create initial browser page through DevTools at {debugger_address}")]
296 CreateInitialBrowserPage {
297 debugger_address: String,
299 },
300
301 #[error("failed to terminate chromedriver process on port {port}")]
303 TerminateChromedriver {
304 port: Port,
306 },
307
308 #[error("failed to terminate browser process attached at {debugger_address}")]
310 TerminateBrowser {
311 debugger_address: String,
313 },
314
315 #[error(
318 "failed to prepare Chrome capabilities for {}",
319 .browser_executable.display()
320 )]
321 PrepareChromeCapabilities {
322 browser_executable: PathBuf,
324 },
325
326 #[error("failed to configure Chrome capabilities")]
328 ConfigureSessionCapabilities,
329
330 #[error("failed to start WebDriver session on port {port}")]
332 StartWebDriverSession {
333 port: Port,
335 },
336
337 #[error("session callback failed")]
339 RunSessionCallback,
340
341 #[error("failed to quit WebDriver session")]
343 QuitSession,
344}