use crate::cell_diff::CellDiff;
use crate::doc_string_diff::DocStringDiff;
use std::any::Any;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HandlerError {
pub message: String,
}
impl HandlerError {
pub fn new(message: impl Into<String>) -> HandlerError {
HandlerError {
message: message.into(),
}
}
pub fn from_panic(payload: Box<dyn Any + Send>) -> HandlerError {
let message = if let Some(s) = payload.downcast_ref::<&str>() {
(*s).to_string()
} else if let Some(s) = payload.downcast_ref::<String>() {
s.clone()
} else {
"handler panicked".to_string()
};
HandlerError { message }
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum StepError {
CellMismatch(Vec<CellDiff>),
DocStringMismatch(DocStringDiff),
ReturnShape(String),
UnexpectedPass,
Handler(HandlerError),
}
impl StepError {
pub fn message(&self) -> String {
match self {
StepError::CellMismatch(cells) => cells
.iter()
.map(|c| format!("{}: expected {} but was {}", c.column, c.expected, c.actual))
.collect::<Vec<_>>()
.join("; "),
StepError::DocStringMismatch(diff) => {
format!(
"doc string: expected {} but was {}",
quote(&diff.expected),
quote(&diff.actual)
)
}
StepError::ReturnShape(msg) => msg.clone(),
StepError::UnexpectedPass => "expected the example to fail, but it passed".to_string(),
StepError::Handler(e) => e.message.clone(),
}
}
pub fn as_cell_mismatch(&self) -> Option<&[CellDiff]> {
match self {
StepError::CellMismatch(cells) => Some(cells),
_ => None,
}
}
pub fn as_doc_string_mismatch(&self) -> Option<&DocStringDiff> {
match self {
StepError::DocStringMismatch(diff) => Some(diff),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FailureLocation {
pub label: String,
pub path: String,
pub line: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct StepFailure {
pub error: StepError,
pub location: Option<FailureLocation>,
}
impl StepFailure {
pub fn bare(error: StepError) -> StepFailure {
StepFailure {
error,
location: None,
}
}
}
fn quote(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 2);
out.push('"');
for c in s.chars() {
match c {
'\\' => out.push_str("\\\\"),
'"' => out.push_str("\\\""),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
'\u{08}' => out.push_str("\\b"),
'\u{0c}' => out.push_str("\\f"),
c if (c as u32) < 0x20 => out.push_str(&format!("\\u{:04x}", c as u32)),
c => out.push(c),
}
}
out.push('"');
out
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RegistryError {
DuplicateStep(String),
Expression(String),
}