#![cfg_attr(
feature = "unstable-error-generic-member-access",
feature(error_generic_member_access)
)]
#![allow(
unused,
clippy::all,
reason = "derive-macro test fixtures intentionally trip style lints"
)]
use oopsie::{Contextual as _, Oopsie};
use std::io;
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum AutoExcludedError {
#[oopsie("missing item: {name}")]
Missing {
name: String,
#[oopsie(capture)]
bt: Box<oopsie::Backtrace>,
},
}
#[test]
fn auto_excluded_from_selector() {
let err = Missing { name: "widget" }.build();
assert!(matches!(err, AutoExcludedError::Missing { name, .. } if name == "widget"));
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum AutoBtError {
#[oopsie("something broke")]
Broke {
#[oopsie(capture)]
bt: Box<oopsie::Backtrace>,
},
}
#[test]
fn auto_backtrace_generated() {
let err = Broke.build();
assert!(matches!(err, AutoBtError::Broke { .. }));
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum AutoWithSourceError {
#[oopsie("io problem")]
IoProblem {
source: io::Error,
#[oopsie(capture)]
bt: Box<oopsie::Backtrace>,
},
}
#[test]
fn auto_with_source() {
let io_err = io::Error::new(io::ErrorKind::Other, "disk full");
let err: AutoWithSourceError = IoProblem.build_error(io_err);
assert!(matches!(err, AutoWithSourceError::IoProblem { .. }));
}
#[cfg(feature = "tracing")]
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum MultiAutoError {
#[oopsie("multi auto")]
Multi {
label: String,
#[oopsie(capture)]
bt: Box<oopsie::Backtrace>,
#[oopsie(capture)]
st: Box<oopsie::SpanTrace>,
},
}
#[cfg(feature = "tracing")]
#[test]
fn multiple_auto_fields() {
let err = Multi { label: "test" }.build();
assert!(matches!(err, MultiAutoError::Multi { label, .. } if label == "test"));
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum InnerDiagError {
#[oopsie("inner")]
Inner,
}
#[cfg(feature = "tracing")]
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum OptionalCaptureError {
#[oopsie("wraps a diagnostic source")]
Wrap {
source: InnerDiagError,
#[oopsie(capture)]
st: oopsie::OptionalSpanTrace,
},
}
#[cfg(feature = "tracing")]
#[test]
fn optional_span_trace_capture_with_diagnostic_source() {
let err: OptionalCaptureError = Wrap.build_error(InnerDiagError::Inner);
assert!(matches!(err, OptionalCaptureError::Wrap { .. }));
}
#[cfg(feature = "tracing")]
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum TripleCaptureError {
#[oopsie("triple")]
Triple {
label: String,
#[oopsie(capture)]
bt: Box<oopsie::Backtrace>,
#[oopsie(capture)]
st: Box<oopsie::SpanTrace>,
#[oopsie(capture)]
ost: oopsie::OptionalSpanTrace,
},
}
#[cfg(feature = "tracing")]
#[test]
fn three_heterogeneous_capture_fields_all_initialize() {
oopsie::backtrace::set_override(oopsie::RustBacktrace::Enabled);
let err = Triple { label: "x" }.build();
let TripleCaptureError::Triple { bt, st, ost, .. } = &err;
assert!(!bt.frames().is_empty(), "backtrace must capture frames");
let _ = st.status();
let _ = ost.to_string();
}
#[cfg(feature = "tracing")]
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum TupleCaptureError {
#[oopsie("tuple")]
Tuple {
#[oopsie(capture)]
traces: (oopsie::Backtrace, oopsie::SpanTrace),
},
}
#[cfg(feature = "tracing")]
#[test]
fn tuple_capture_field_initializes_both_elements() {
oopsie::backtrace::set_override(oopsie::RustBacktrace::Enabled);
let err = Tuple.build();
let TupleCaptureError::Tuple { traces } = &err;
assert!(
!traces.0.frames().is_empty(),
"tuple backtrace half must capture frames"
);
let _ = traces.1.status();
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum NeverError {}
#[test]
fn empty_enum_derives() {
fn assert_error<E: std::error::Error>() {}
assert_error::<NeverError>();
}
#[derive(Debug, Default)]
struct Marker {
captured: bool,
}
impl oopsie::Capturable for Marker {
fn capture() -> Self {
Self { captured: true }
}
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum CustomCaptureError {
#[oopsie("custom capture")]
Custom {
info: String,
#[oopsie(capture)]
marker: Marker,
},
}
#[test]
fn user_defined_capturable_field_is_captured() {
let err = Custom { info: "x" }.build();
let CustomCaptureError::Custom { marker, .. } = &err;
assert!(
marker.captured,
"custom Capturable::capture must populate the field"
);
}
#[test]
fn cfg_attr_gated_debug_is_not_duplicated() {
#[oopsie::oopsie]
#[cfg_attr(test, derive(Debug))]
#[oopsie(module(false))]
enum CfgDebugError {
#[oopsie("x")]
X,
}
let _ = format!("{:?}", X.build());
}