nextest_metadata/
errors.rs

1// Copyright (c) The nextest Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::{error, fmt};
5
6/// An error that occurs while running a `cargo nextest` command.
7#[derive(Debug)]
8pub enum CommandError {
9    /// Executing the process resulted in an error.
10    Exec(std::io::Error),
11
12    /// The command exited with a non-zero code.
13    CommandFailed {
14        /// The exit code for the process. Exit codes can be cross-referenced against
15        /// [`NextestExitCode`](crate::NextestExitCode).
16        exit_code: Option<i32>,
17
18        /// Standard error for the process.
19        stderr: Vec<u8>,
20    },
21
22    /// Error parsing JSON output.
23    Json(serde_json::Error),
24}
25
26impl fmt::Display for CommandError {
27    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28        match self {
29            Self::Exec(_) => {
30                write!(f, "`cargo nextest` process execution failed")
31            }
32            Self::CommandFailed { exit_code, stderr } => {
33                let exit_code_str =
34                    exit_code.map_or(String::new(), |code| format!(" with exit code {code}"));
35                let stderr = String::from_utf8_lossy(stderr);
36                write!(
37                    f,
38                    "`cargo nextest` failed{exit_code_str}, stderr:\n{stderr}\n"
39                )
40            }
41            Self::Json(_) => {
42                write!(f, "parsing `cargo nextest` JSON output failed")
43            }
44        }
45    }
46}
47
48impl error::Error for CommandError {
49    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
50        match self {
51            Self::Exec(err) => Some(err),
52            Self::CommandFailed { .. } => None,
53            Self::Json(err) => Some(err),
54        }
55    }
56}