iai_callgrind_runner/
error.rs1use std::fmt::Display;
2use std::io::stderr;
3use std::os::unix::process::ExitStatusExt;
4use std::path::PathBuf;
5use std::process::{ExitStatus, Output};
6
7use version_compare::Cmp;
8
9use crate::runner::common::ModulePath;
10use crate::runner::tool::{ToolOutputPath, ValgrindTool};
11use crate::util::write_all_to_stderr;
12
13#[derive(Debug, PartialEq, Clone)]
14pub enum Error {
15 InitError(String),
16 VersionMismatch(version_compare::Cmp, String, String),
17 LaunchError(PathBuf, String),
18 ProcessError((String, Option<Output>, ExitStatus, Option<ToolOutputPath>)),
20 InvalidBoolArgument((String, String)),
21 ParseError((PathBuf, String)),
22 RegressionError(bool),
23 EnvironmentVariableError((String, String)),
24 SandboxError(String),
25 BenchmarkError(ValgrindTool, ModulePath, String),
26}
27
28impl std::error::Error for Error {}
29
30impl Display for Error {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 Self::InitError(message) => {
34 let runner_version = env!("CARGO_PKG_VERSION").to_owned();
35 write!(
36 f,
37 "Failed to initialize iai-callgrind-runner: {message}\n\nDetected version of \
38 iai-callgrind-runner is {runner_version}. This error can be caused by a \
39 version mismatch between iai-callgrind and iai-callgrind-runner. If you \
40 updated the library (iai-callgrind) in your Cargo.toml file, the binary \
41 (iai-callgrind-runner) needs to be updated to the same version and vice \
42 versa."
43 )
44 }
45 Self::VersionMismatch(cmp, runner_version, library_version) => match cmp {
46 Cmp::Lt => write!(
47 f,
48 "iai-callgrind-runner ({runner_version}) is older than iai-callgrind \
49 ({library_version}). Please update iai-callgrind-runner by calling 'cargo \
50 install --version {library_version} iai-callgrind-runner'"
51 ),
52 Cmp::Gt => write!(
53 f,
54 "iai-callgrind-runner ({runner_version}) is newer than iai-callgrind \
55 ({library_version}). Please update iai-callgrind to '{runner_version}' in \
56 your Cargo.toml file"
57 ),
58 Cmp::Ne => write!(
59 f,
60 "No version information found for iai-callgrind but iai-callgrind-runner \
61 ({runner_version}) is >= '0.3.0'. Please update iai-callgrind to \
62 '{runner_version}' in your Cargo.toml file"
63 ),
64 _ => unreachable!(),
65 },
66 Self::LaunchError(exec, message) => {
67 write!(f, "Error launching '{}': {message}", exec.display())
68 }
69 Self::ProcessError((process, output, status, output_path)) => {
70 if let Some(output_path) = output_path {
71 output_path
72 .dump_log(log::Level::Error, &mut stderr())
73 .expect("Printing error output should succeed");
74 }
75 if let Some(output) = output {
76 write_all_to_stderr(&output.stderr);
77 }
78
79 if let Some(code) = status.code() {
80 write!(f, "Error running '{process}': Exit code was: '{code}'")
81 } else if let Some(signal) = status.signal() {
82 write!(
83 f,
84 "Error running '{process}': Terminated by a signal '{signal}'"
85 )
86 } else {
87 write!(f, "Error running '{process}': Terminated abnormally")
88 }
89 }
90 Self::InvalidBoolArgument((option, value)) => {
91 write!(
92 f,
93 "Invalid argument for {option}: '{value}'. Valid values are 'yes' or 'no'"
94 )
95 }
96 Self::ParseError((path, message)) => {
97 write!(f, "Error parsing file '{}': {message}", path.display())
98 }
99 Self::RegressionError(is_fatal) => {
100 if *is_fatal {
101 write!(f, "Performance has regressed. Aborting ...",)
102 } else {
103 write!(f, "Performance has regressed.",)
104 }
105 }
106 Self::EnvironmentVariableError((var, reason)) => {
107 write!(f, "Failed parsing environment variable {var}: {reason}")
108 }
109 Self::SandboxError(message) => {
110 write!(f, "Error in sandbox: {message}")
111 }
112 Self::BenchmarkError(tool, module_path, message) => {
113 write!(f, "Error in {tool} benchmark {module_path}: {message}")
114 }
115 }
116 }
117}