iai_callgrind_runner/
error.rs1use std::fmt::Display;
4use std::io::stderr;
5use std::os::unix::process::ExitStatusExt;
6use std::path::PathBuf;
7use std::process::{ExitStatus, Output};
8
9use version_compare::Cmp;
10
11use crate::api::ValgrindTool;
12use crate::runner::common::ModulePath;
13use crate::runner::format::Header;
14use crate::runner::tool::path::ToolOutputPath;
15use crate::util::write_all_to_stderr;
16
17#[derive(Debug, PartialEq, Clone, Eq)]
19pub enum Error {
20 BenchmarkError(ValgrindTool, ModulePath, String),
24 ConfigurationError(ModulePath, Option<String>, String),
28 InitError(String),
32 InvalidBoolArgument(String, String),
36 LaunchError(PathBuf, String),
40 ParseError(PathBuf, String),
44 ProcessError(String, Option<Output>, ExitStatus, Option<ToolOutputPath>),
55 RegressionError(bool),
60 SandboxError(String),
64 VersionMismatch(version_compare::Cmp, String, String),
68}
69
70impl Display for Error {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 match self {
73 Self::InitError(message) => {
74 let runner_version = env!("CARGO_PKG_VERSION").to_owned();
75 write!(
76 f,
77 "Failed to initialize iai-callgrind-runner: {message}\n\nDetected version of \
78 iai-callgrind-runner is {runner_version}. This error can be caused by a \
79 version mismatch between iai-callgrind and iai-callgrind-runner. If you \
80 updated the library (iai-callgrind) in your Cargo.toml file, the binary \
81 (iai-callgrind-runner) needs to be updated to the same version and vice \
82 versa."
83 )
84 }
85 Self::VersionMismatch(cmp, runner_version, library_version) => match cmp {
86 Cmp::Lt => write!(
87 f,
88 "iai-callgrind-runner ({runner_version}) is older than iai-callgrind \
89 ({library_version}). Please update iai-callgrind-runner by calling 'cargo \
90 install --version {library_version} iai-callgrind-runner'"
91 ),
92 Cmp::Gt => write!(
93 f,
94 "iai-callgrind-runner ({runner_version}) is newer than iai-callgrind \
95 ({library_version}). Please update iai-callgrind to '{runner_version}' in \
96 your Cargo.toml file"
97 ),
98 Cmp::Ne => write!(
99 f,
100 "No version information found for iai-callgrind but iai-callgrind-runner \
101 ({runner_version}) is >= '0.3.0'. Please update iai-callgrind to \
102 '{runner_version}' in your Cargo.toml file"
103 ),
104 _ => unreachable!(),
105 },
106 Self::LaunchError(exec, message) => {
107 write!(f, "Error launching '{}': {message}", exec.display())
108 }
109 Self::ProcessError(process, output, status, output_path) => {
110 if let Some(output_path) = output_path {
111 let _ = output_path.dump_log(log::Level::Error, &mut stderr());
112 }
113 if let Some(output) = output {
114 write_all_to_stderr(&output.stderr);
115 }
116
117 if let Some(code) = status.code() {
118 write!(f, "Error running '{process}': Exit code was: '{code}'")
119 } else if let Some(signal) = status.signal() {
120 write!(
121 f,
122 "Error running '{process}': Terminated by a signal '{signal}'"
123 )
124 } else {
125 write!(f, "Error running '{process}': Terminated abnormally")
126 }
127 }
128 Self::InvalidBoolArgument(option, value) => {
129 write!(
130 f,
131 "Invalid argument for {option}: '{value}'. Valid values are 'yes' or 'no'"
132 )
133 }
134 Self::ParseError(path, message) => {
135 write!(f, "Error parsing file '{}': {message}", path.display())
136 }
137 Self::RegressionError(is_fatal) => {
138 if *is_fatal {
139 write!(
140 f,
141 "Performance has regressed. Fail-fast is set. Aborting ...",
142 )
143 } else {
144 write!(f, "Performance has regressed.",)
145 }
146 }
147 Self::SandboxError(message) => {
148 write!(f, "Error in sandbox: {message}")
149 }
150 Self::BenchmarkError(tool, module_path, message) => {
151 write!(f, "Error in {tool} benchmark {module_path}: {message}")
152 }
153 Self::ConfigurationError(module_path, id, message) => {
154 let header = Header::without_description(module_path, id.clone());
155 write!(f, "Misconfiguration in: {header}\nCaused by:\n {message}",)
156 }
157 }
158 }
159}
160
161impl std::error::Error for Error {}