#![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::{Oopsie, oopsie};
#[cfg(any())]
pub struct GhostType;
#[derive(Debug, Oopsie)]
#[oopsie(module(false), suffix)]
pub enum CfgError {
#[cfg(all())]
#[oopsie("present: {n}")]
Present { n: u32 },
#[cfg(any())]
#[oopsie("gone")]
Gone { ghost: GhostType },
}
#[test]
fn cfg_satisfied_variant_builds() {
let err = PresentOopsie { n: 5u32 }.build();
assert!(matches!(err, CfgError::Present { n: 5 }));
assert_eq!(err.to_string(), "present: 5");
}
#[test]
fn cfg_gated_out_variant_emits_no_dangling_refs() {
let err = PresentOopsie { n: 1u32 }.build();
assert!(matches!(err, CfgError::Present { .. }));
}
#[cfg(any())]
pub struct AttrGhost;
#[oopsie]
#[oopsie(module(false), suffix)]
pub enum AttrCfgError {
#[cfg(test)]
#[oopsie("active: {n}")]
Active { n: u32 },
#[cfg(any())]
#[oopsie("inactive")]
Inactive { ghost: AttrGhost },
}
#[test]
fn attr_cfg_active_variant_builds() {
let err = ActiveOopsie { n: 7u32 }.build();
assert!(matches!(err, AttrCfgError::Active { n: 7 }));
assert_eq!(err.to_string(), "active: 7");
}
#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
pub enum CfgCollisionError {
#[cfg(all())]
#[oopsie("read")]
Read,
#[cfg(any())]
#[oopsie("read (io)")]
ReadError,
}
#[test]
fn cfg_gated_variants_may_share_selector_name() {
let err = Read.build();
assert_eq!(err.to_string(), "read");
}
#[cfg(any())]
pub struct FieldGhost;
#[oopsie]
#[oopsie(module(false), suffix)]
pub enum FieldCfgError {
#[oopsie("v: {keep}")]
V {
#[cfg(any())]
extra: FieldGhost,
keep: u32,
},
}
#[test]
fn field_cfg_stripped_field_drops_its_generated_mentions() {
let err = VOopsie { keep: 9u32 }.build();
assert!(matches!(err, FieldCfgError::V { keep: 9 }));
assert_eq!(err.to_string(), "v: 9");
}
#[oopsie]
#[oopsie(module(false), suffix = "Ctx")]
pub enum FieldCfgPresentError {
#[oopsie("v: {keep}")]
V {
#[cfg(all())]
extra: String,
keep: u32,
},
}
#[test]
fn field_cfg_active_field_is_present_and_usable() {
let err = VCtx {
extra: "details".to_owned(),
keep: 4u32,
}
.build();
assert!(matches!(err, FieldCfgPresentError::V { keep: 4, .. }));
assert_eq!(err.to_string(), "v: 4");
}
#[cfg(any())]
pub struct AllGoneGhost;
#[oopsie]
#[oopsie(module(false), suffix)]
pub enum AllStrippedError {
#[cfg(any())]
#[oopsie("a: {x}")]
A { x: u32 },
#[cfg(any())]
#[oopsie("b")]
B { ghost: AllGoneGhost },
}
#[test]
fn all_variants_stripped_still_compiles() {
fn _accepts(_: &AllStrippedError) {}
}
#[cfg(any())]
pub struct MixedGhost;
#[oopsie]
#[oopsie(module(false), suffix)]
pub enum MixedCfgError {
#[oopsie("kept: {n}")]
Kept { n: u32, source: std::io::Error },
#[cfg(any())]
#[oopsie("dropped")]
Dropped { ghost: MixedGhost },
}
#[test]
fn mixed_cfg_kept_variant_display_and_source_work() {
use oopsie::Contextual as _;
use std::error::Error as _;
let io = std::io::Error::other("boom");
let err = KeptOopsie { n: 3u32 }.build_error(io);
assert_eq!(err.to_string(), "kept: 3");
assert!(err.source().is_some());
}
#[oopsie]
#[oopsie(module(false), suffix = "Bt")]
pub enum BacktraceFieldCfgError {
#[oopsie("stripped: {keep}")]
Stripped {
#[cfg(any())]
#[oopsie(backtrace)]
bt: oopsie::Backtrace,
keep: u32,
},
#[oopsie("kept: {keep}")]
Kept {
#[cfg(all())]
#[oopsie(backtrace)]
bt: oopsie::Backtrace,
keep: u32,
},
}
#[test]
fn cfg_stripped_backtrace_field_falls_through_to_none() {
use oopsie::Diagnostic as _;
let err = StrippedBt { keep: 1u32 }.build();
assert!(err.oopsie_backtrace().is_none());
}
#[test]
fn cfg_kept_backtrace_field_accessor_returns_some() {
use oopsie::Diagnostic as _;
let err = KeptBt { keep: 2u32 }.build();
assert!(err.oopsie_backtrace().is_some());
}
#[oopsie]
#[oopsie(module(false), suffix = "Tr")]
pub enum TracesFieldCfgError {
#[oopsie("stripped: {keep}")]
Stripped {
#[cfg(any())]
#[oopsie(traces)]
t: (oopsie::Backtrace, oopsie::SpanTrace),
keep: u32,
},
#[oopsie("kept: {keep}")]
Kept {
#[cfg(all())]
#[oopsie(traces)]
t: (oopsie::Backtrace, oopsie::SpanTrace),
keep: u32,
},
}
#[test]
fn cfg_stripped_packed_traces_field_falls_through_to_none() {
use oopsie::Diagnostic as _;
let err = StrippedTr { keep: 1u32 }.build();
assert!(err.oopsie_backtrace().is_none());
assert!(err.oopsie_spantrace().is_none());
}
#[test]
fn cfg_kept_packed_traces_field_accessor_returns_some() {
use oopsie::Diagnostic as _;
let err = KeptTr { keep: 2u32 }.build();
assert!(err.oopsie_backtrace().is_some());
assert!(err.oopsie_spantrace().is_some());
}
#[oopsie]
#[oopsie(module(false), suffix = "Loc")]
pub enum LocationFieldCfgError {
#[oopsie("stripped: {keep}")]
Stripped {
#[cfg(any())]
#[oopsie(location)]
at: &'static std::panic::Location<'static>,
keep: u32,
},
#[oopsie("kept: {keep}")]
Kept {
#[cfg(all())]
#[oopsie(location)]
at: &'static std::panic::Location<'static>,
keep: u32,
},
}
#[test]
fn cfg_stripped_location_field_falls_through_to_none() {
use oopsie::Diagnostic as _;
let err = StrippedLoc { keep: 1u32 }.build();
assert!(err.oopsie_location().is_none());
}
#[test]
fn cfg_kept_location_field_accessor_returns_some() {
use oopsie::Diagnostic as _;
let err = KeptLoc { keep: 2u32 }.build();
assert!(err.oopsie_location().is_some());
}
#[oopsie]
#[oopsie(module(false))]
pub struct StructBtStrippedError {
#[cfg(any())]
#[oopsie(backtrace)]
bt: oopsie::Backtrace,
keep: u32,
}
#[test]
fn struct_cfg_stripped_backtrace_field_yields_none() {
use oopsie::Diagnostic as _;
let err = StructBtStrippedOopsie { keep: 1u32 }.build();
assert!(err.oopsie_backtrace().is_none());
}
#[oopsie]
#[oopsie(module(false))]
pub struct StructBtKeptError {
#[cfg(all())]
#[oopsie(backtrace)]
bt: oopsie::Backtrace,
keep: u32,
}
#[test]
fn struct_cfg_kept_backtrace_field_returns_some() {
use oopsie::Diagnostic as _;
let err = StructBtKeptOopsie { keep: 2u32 }.build();
assert!(err.oopsie_backtrace().is_some());
}
#[cfg(feature = "tracing")]
#[oopsie]
#[oopsie(module(false), suffix = "St")]
pub enum SpantraceFieldCfgError {
#[oopsie("stripped: {keep}")]
Stripped {
#[cfg(any())]
#[oopsie(spantrace)]
st: oopsie::SpanTrace,
keep: u32,
},
#[oopsie("kept: {keep}")]
Kept {
#[cfg(all())]
#[oopsie(spantrace)]
st: oopsie::SpanTrace,
keep: u32,
},
}
#[cfg(feature = "tracing")]
#[test]
fn cfg_stripped_spantrace_field_falls_through_to_none() {
use oopsie::Diagnostic as _;
let err = StrippedSt { keep: 1u32 }.build();
assert!(err.oopsie_spantrace().is_none());
}
#[cfg(feature = "tracing")]
#[test]
fn cfg_kept_spantrace_field_accessor_returns_some() {
use oopsie::Diagnostic as _;
let err = KeptSt { keep: 2u32 }.build();
assert!(err.oopsie_spantrace().is_some());
}
#[oopsie]
#[oopsie(module(false))]
pub struct StructHelpStrippedError {
#[cfg(any())]
#[oopsie(help)]
hint: String,
keep: u32,
}
#[test]
fn struct_cfg_stripped_help_field_yields_none() {
use oopsie::Diagnostic as _;
let err = StructHelpStrippedOopsie { keep: 1u32 }.build();
assert!(err.oopsie_help_text().is_none());
}
#[oopsie]
#[oopsie(module(false))]
pub struct StructHelpKeptError {
#[cfg(all())]
#[oopsie(help)]
hint: String,
keep: u32,
}
#[test]
fn struct_cfg_kept_help_field_returns_some() {
use oopsie::Diagnostic as _;
let err = StructHelpKeptOopsie {
hint: "do this".to_owned(),
keep: 2u32,
}
.build();
assert_eq!(&*err.oopsie_help_text().unwrap(), "do this");
}
#[oopsie]
#[oopsie(module(false), suffix = "He")]
pub enum EnumHelpCfgError {
#[oopsie("stripped: {keep}")]
Stripped {
#[cfg(any())]
#[oopsie(help)]
hint: String,
keep: u32,
},
#[oopsie("kept: {keep}")]
Kept {
#[cfg(all())]
#[oopsie(help)]
hint: String,
keep: u32,
},
}
#[test]
fn enum_cfg_stripped_help_field_falls_through_to_none() {
use oopsie::Diagnostic as _;
let err = StrippedHe { keep: 1u32 }.build();
assert!(err.oopsie_help_text().is_none());
}
#[test]
fn enum_cfg_kept_help_field_returns_some() {
use oopsie::Diagnostic as _;
let err = KeptHe {
hint: "fix it".to_owned(),
keep: 2u32,
}
.build();
assert_eq!(&*err.oopsie_help_text().unwrap(), "fix it");
}