use snafu::{prelude::*, Location};
mod basics {
use super::*;
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Created at {location}"))]
Usage {
#[snafu(implicit)]
location: Location,
},
}
#[test]
fn location_tracks_file_line_and_column() {
let one = UsageSnafu.build();
let two = UsageSnafu.build();
let sep = std::path::MAIN_SEPARATOR;
assert_eq!(
one.to_string(),
format!("Created at tests{sep}location.rs:17:30")
);
assert_eq!(
two.to_string(),
format!("Created at tests{sep}location.rs:18:30")
);
}
}
mod track_caller {
use super::*;
#[derive(Debug, Copy, Clone, Snafu)]
struct InnerError {
#[snafu(implicit)]
location: Location,
}
#[derive(Debug, Snafu)]
struct WrapNoUserFieldsError {
source: InnerError,
#[snafu(implicit)]
location: Location,
}
#[derive(Debug, Snafu)]
#[snafu(context(false))]
struct WrapNoContext {
source: InnerError,
#[snafu(implicit)]
location: Location,
}
#[derive(Debug, Snafu)]
#[snafu(display("{message}"))]
#[snafu(whatever)]
pub struct MyWhatever {
#[snafu(source(from(Box<dyn std::error::Error>, Some)))]
source: Option<Box<dyn std::error::Error>>,
message: String,
#[snafu(implicit)]
location: Location,
}
#[test]
fn track_caller_is_applied_on_build() {
let base_line = line!();
let inner = InnerSnafu.build();
assert_eq!(
inner.location.line(),
base_line + 1,
"Actual location: {}",
inner.location,
);
}
#[test]
fn track_caller_is_applied_on_fail() {
let base_line = line!();
let inner = InnerSnafu.fail::<()>().unwrap_err();
assert_eq!(
inner.location.line(),
base_line + 1,
"Actual location: {}",
inner.location,
);
}
#[test]
fn track_caller_is_applied_on_ensure() {
let base_line = line!();
fn x() -> Result<(), InnerError> {
ensure!(false, InnerSnafu);
Ok(())
}
let inner = x().unwrap_err();
assert_eq!(
inner.location.line(),
base_line + 2,
"Actual location: {}",
inner.location,
);
}
#[test]
fn track_caller_is_applied_on_whatever() {
let base_line = line!();
fn x() -> Result<(), MyWhatever> {
whatever!("bang");
}
let inner = x().unwrap_err();
assert_eq!(
inner.location.line(),
base_line + 2,
"Actual location: {}",
inner.location,
);
}
#[test]
fn track_caller_is_applied_on_result_context() {
let base_line = line!();
let wrap_no_user_fields = InnerSnafu
.fail::<()>()
.context(WrapNoUserFieldsSnafu)
.unwrap_err();
assert_eq!(
wrap_no_user_fields.location.line(),
base_line + 3,
"Actual location: {}",
wrap_no_user_fields.location,
);
}
#[test]
fn track_caller_is_applied_on_result_with_context() {
let base_line = line!();
let wrap_no_user_fields = InnerSnafu
.fail::<()>()
.with_context(|_| WrapNoUserFieldsSnafu)
.unwrap_err();
assert_eq!(
wrap_no_user_fields.location.line(),
base_line + 3,
"Actual location: {}",
wrap_no_user_fields.location,
);
}
#[test]
fn track_caller_is_applied_without_context() {
let base_line = line!();
let wrap_no_context: WrapNoContext = InnerSnafu.build().into();
assert_eq!(
wrap_no_context.location.line(),
base_line + 1,
"Actual location: {}",
wrap_no_context.location,
);
}
#[test]
fn track_caller_is_applied_on_result_whatever_context() {
let base_line = line!();
let whatever: MyWhatever = InnerSnafu
.fail::<()>()
.whatever_context("bang")
.unwrap_err();
assert_eq!(
whatever.location.line(),
base_line + 3,
"Actual location: {}",
whatever.location,
);
}
#[test]
fn track_caller_is_applied_on_result_with_whatever_context() {
let base_line = line!();
let whatever: MyWhatever = InnerSnafu
.fail::<()>()
.with_whatever_context(|_| "bang")
.unwrap_err();
assert_eq!(
whatever.location.line(),
base_line + 3,
"Actual location: {}",
whatever.location,
);
}
#[test]
fn track_caller_is_applied_on_option_context() {
let base_line = line!();
let option_to_error_no_user_fields = None::<()>.context(InnerSnafu).unwrap_err();
assert_eq!(
option_to_error_no_user_fields.location.line(),
base_line + 1,
"Actual location: {}",
option_to_error_no_user_fields.location,
);
}
#[test]
fn track_caller_is_applied_on_option_with_context() {
let base_line = line!();
let option_to_error_no_user_fields = None::<()>.with_context(|| InnerSnafu).unwrap_err();
assert_eq!(
option_to_error_no_user_fields.location.line(),
base_line + 1,
"Actual location: {}",
option_to_error_no_user_fields.location,
);
}
#[test]
fn track_caller_is_applied_on_option_whatever_context() {
let base_line = line!();
let whatever: MyWhatever = None::<()>.whatever_context("bang").unwrap_err();
assert_eq!(
whatever.location.line(),
base_line + 1,
"Actual location: {}",
whatever.location,
);
}
#[test]
fn track_caller_is_applied_on_option_with_whatever_context() {
let base_line = line!();
let whatever: MyWhatever = None::<()>.with_whatever_context(|| "bang").unwrap_err();
assert_eq!(
whatever.location.line(),
base_line + 1,
"Actual location: {}",
whatever.location,
);
}
}