Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,472 @@
// For creating backtraces with different addresses in tests.
#![allow(clippy::redundant_closure, clippy::redundant_closure_call)] // for testing
#![allow(dead_code)] // some code is tested for type checking only
use core::error::{request_ref, request_value};
use super::*;
derive_display!(TestErr);
#[derive(Debug, Error)]
enum TestErr {
Unit,
NamedImplicitNoBacktrace {
field: i32,
},
NamedImplicitBacktraceByFieldName {
backtrace: MyBacktrace,
field: i32,
},
NamedImplicitBacktraceByFieldType {
implicit_backtrace: Backtrace,
field: i32,
},
NamedExplicitNoBacktraceByFieldName {
#[error(not(backtrace))]
backtrace: MyBacktrace,
field: i32,
},
NamedExplicitNoBacktraceByFieldType {
#[error(not(backtrace))]
implicit_backtrace: Backtrace,
field: i32,
},
NamedExplicitBacktrace {
#[error(backtrace)]
explicit_backtrace: MyBacktrace,
field: i32,
},
NamedExplicitNoBacktraceRedundant {
#[error(not(backtrace))]
not_backtrace: MyBacktrace,
#[error(not(backtrace))]
field: i32,
},
NamedExplicitBacktraceByFieldNameRedundant {
#[error(backtrace)]
backtrace: MyBacktrace,
field: i32,
},
NamedExplicitBacktraceByFieldTypeRedundant {
#[error(backtrace)]
implicit_backtrace: Backtrace,
field: i32,
},
NamedExplicitSuppressesImplicit {
#[error(backtrace)]
not_backtrace: MyBacktrace,
backtrace: Backtrace,
field: i32,
},
NamedImplicitNoBacktraceFromSource {
#[error(source)]
err: BacktraceErr,
},
NamedExplicitNoBacktraceFromSource {
#[error(source, not(backtrace))]
err: BacktraceErr,
},
NamedExplicitBacktraceFromSource {
#[error(backtrace, source)]
err: BacktraceErr,
},
NamedImplicitDifferentSourceAndBacktrace {
#[error(source)]
err: BacktraceErr,
backtrace: Backtrace,
},
NamedExplicitDifferentSourceAndBacktrace {
#[error(source)]
err: BacktraceErr,
#[error(backtrace)]
backtrace: Backtrace,
},
UnnamedImplicitNoBacktrace(i32, i32),
UnnamedImplicitBacktrace(Backtrace, i32, i32),
UnnamedExplicitNoBacktrace(#[error(not(backtrace))] Backtrace, i32),
UnnamedExplicitBacktrace(#[error(backtrace)] MyBacktrace, i32, i32),
UnnamedExplicitNoBacktraceRedundant(
#[error(not(backtrace))] MyBacktrace,
#[error(not(backtrace))] i32,
),
UnnamedExplicitBacktraceRedundant(#[error(backtrace)] Backtrace, i32, i32),
UnnamedExplicitSuppressesImplicit(#[error(backtrace)] MyBacktrace, Backtrace, i32),
UnnamedImplicitNoBacktraceFromSource(BacktraceErr),
UnnamedExplicitNoBacktraceFromSource(#[error(not(backtrace))] BacktraceErr),
UnnamedExplicitBacktraceFromSource(#[error(backtrace)] BacktraceErr),
UnnamedImplicitDifferentSourceAndBacktrace(
#[error(source)] BacktraceErr,
Backtrace,
),
UnnamedExplicitDifferentSourceAndBacktrace(
#[error(source)] BacktraceErr,
#[error(backtrace)] Backtrace,
),
}
impl TestErr {
fn get_stored_backtrace(&self) -> &Backtrace {
match self {
Self::NamedImplicitBacktraceByFieldName { backtrace, .. }
| Self::NamedImplicitBacktraceByFieldType {
implicit_backtrace: backtrace,
..
}
| Self::NamedExplicitBacktrace {
explicit_backtrace: backtrace,
..
}
| Self::NamedExplicitBacktraceByFieldNameRedundant { backtrace, .. }
| Self::NamedExplicitBacktraceByFieldTypeRedundant {
implicit_backtrace: backtrace,
..
}
| Self::NamedExplicitSuppressesImplicit {
not_backtrace: backtrace,
..
}
| Self::NamedImplicitDifferentSourceAndBacktrace { backtrace, .. }
| Self::NamedExplicitDifferentSourceAndBacktrace { backtrace, .. }
| Self::UnnamedImplicitBacktrace(backtrace, _, _)
| Self::UnnamedExplicitBacktrace(backtrace, _, _)
| Self::UnnamedExplicitBacktraceRedundant(backtrace, _, _)
| Self::UnnamedExplicitSuppressesImplicit(backtrace, _, _)
| Self::UnnamedImplicitDifferentSourceAndBacktrace(_, backtrace)
| Self::UnnamedExplicitDifferentSourceAndBacktrace(_, backtrace) => {
backtrace
}
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
}
}
fn get_unused_backtrace(&self) -> &Backtrace {
match self {
Self::NamedExplicitSuppressesImplicit { backtrace, .. } => backtrace,
Self::UnnamedExplicitSuppressesImplicit(_, backtrace, _) => backtrace,
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
}
}
fn get_source_backtrace(&self) -> &Backtrace {
request_ref(match self {
Self::NamedExplicitBacktraceFromSource { err }
| Self::NamedExplicitDifferentSourceAndBacktrace { err, .. }
| Self::NamedImplicitDifferentSourceAndBacktrace { err, .. }
| Self::UnnamedExplicitBacktraceFromSource(err)
| Self::UnnamedExplicitDifferentSourceAndBacktrace(err, ..)
| Self::UnnamedImplicitDifferentSourceAndBacktrace(err, ..) => err,
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
})
.unwrap()
}
}
type MyBacktrace = Backtrace;
#[test]
fn unit() {
assert!(request_ref::<Backtrace>(&TestErr::Unit).is_none());
}
#[test]
fn named_implicit_no_backtrace() {
let err = TestErr::NamedImplicitNoBacktrace { field: 0 };
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_implicit_backtrace_by_field_name() {
let err = TestErr::NamedImplicitBacktraceByFieldName {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_implicit_backtrace_by_field_type() {
let err = TestErr::NamedImplicitBacktraceByFieldType {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_no_backtrace_by_field_name() {
let err = TestErr::NamedExplicitNoBacktraceByFieldName {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_by_field_type() {
let err = TestErr::NamedExplicitNoBacktraceByFieldType {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_backtrace() {
let err = TestErr::NamedExplicitBacktrace {
explicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_no_backtrace_redundant() {
let err = TestErr::NamedExplicitNoBacktraceRedundant {
not_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_by_field_name_redundant() {
let err = TestErr::NamedExplicitBacktraceByFieldNameRedundant {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_backtrace_by_field_type_redundant() {
let err = TestErr::NamedExplicitBacktraceByFieldTypeRedundant {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_suppresses_implicit() {
let err = TestErr::NamedExplicitSuppressesImplicit {
not_backtrace: Backtrace::force_capture(),
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_unused_backtrace);
}
#[test]
fn named_implicit_no_backtrace_from_source() {
let err = TestErr::NamedImplicitNoBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_from_source() {
let err = TestErr::NamedExplicitNoBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_from_source() {
let err = TestErr::NamedExplicitBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_source_backtrace);
}
#[test]
fn named_implicit_different_source_and_backtrace() {
let err = TestErr::NamedImplicitDifferentSourceAndBacktrace {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn named_explicit_different_source_and_backtrace() {
let err = TestErr::NamedExplicitDifferentSourceAndBacktrace {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn unnamed_implicit_no_backtrace() {
let err = TestErr::UnnamedImplicitNoBacktrace(0, 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_implicit_backtrace() {
let err = TestErr::UnnamedImplicitBacktrace(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_no_backtrace() {
let err = TestErr::UnnamedExplicitNoBacktrace(Backtrace::force_capture(), 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace() {
let err = TestErr::UnnamedExplicitBacktrace(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_no_backtrace_redundant() {
let err =
TestErr::UnnamedExplicitNoBacktraceRedundant(Backtrace::force_capture(), 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_redundant() {
let err =
TestErr::UnnamedExplicitBacktraceRedundant(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_suppresses_implicit() {
let err = TestErr::UnnamedExplicitSuppressesImplicit(
Backtrace::force_capture(),
(|| Backtrace::force_capture())(), // ensure backtraces are different
0,
);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_unused_backtrace);
}
#[test]
fn unnamed_implicit_no_backtrace_from_source() {
let err = TestErr::UnnamedImplicitNoBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_no_backtrace_from_source() {
let err = TestErr::UnnamedExplicitNoBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_from_source() {
let err = TestErr::UnnamedExplicitBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_source_backtrace);
}
#[test]
fn unnamed_implicit_different_source_and_backtrace() {
let err = TestErr::UnnamedImplicitDifferentSourceAndBacktrace(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn unnamed_explicit_different_source_and_backtrace() {
let err = TestErr::UnnamedExplicitDifferentSourceAndBacktrace(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}

View File

@@ -0,0 +1,481 @@
// For creating backtraces with different addresses in tests.
#![allow(clippy::redundant_closure, clippy::redundant_closure_call)] // for testing
#![allow(dead_code)] // some code is tested for type checking only
use core::error::{request_ref, request_value};
use super::*;
derive_display!(TestErr, T);
#[derive(Debug, Error)]
enum TestErr<T> {
Unit,
NamedImplicitNoBacktrace {
field: T,
},
NamedImplicitBacktraceByFieldName {
backtrace: MyBacktrace,
field: T,
},
NamedImplicitBacktraceByFieldType {
implicit_backtrace: Backtrace,
field: T,
},
NamedExplicitNoBacktraceByFieldName {
#[error(not(backtrace))]
backtrace: MyBacktrace,
field: T,
},
NamedExplicitNoBacktraceByFieldType {
#[error(not(backtrace))]
implicit_backtrace: Backtrace,
field: T,
},
NamedExplicitBacktrace {
#[error(backtrace)]
explicit_backtrace: MyBacktrace,
field: T,
},
NamedExplicitNoBacktraceRedundant {
#[error(not(backtrace))]
not_backtrace: MyBacktrace,
#[error(not(backtrace))]
field: T,
},
NamedExplicitBacktraceByFieldNameRedundant {
#[error(backtrace)]
backtrace: MyBacktrace,
field: T,
},
NamedExplicitBacktraceByFieldTypeRedundant {
#[error(backtrace)]
implicit_backtrace: Backtrace,
field: T,
},
NamedExplicitSuppressesImplicit {
#[error(backtrace)]
not_backtrace: MyBacktrace,
backtrace: Backtrace,
field: T,
},
UnnamedImplicitNoBacktrace(T, T),
UnnamedImplicitBacktrace(Backtrace, T, T),
UnnamedExplicitNoBacktrace(#[error(not(backtrace))] Backtrace, T),
UnnamedExplicitBacktrace(#[error(backtrace)] MyBacktrace, T, T),
UnnamedExplicitNoBacktraceRedundant(
#[error(not(backtrace))] MyBacktrace,
#[error(not(backtrace))] T,
),
UnnamedExplicitBacktraceRedundant(#[error(backtrace)] Backtrace, T, T),
UnnamedExplicitSuppressesImplicit(#[error(backtrace)] MyBacktrace, Backtrace, T),
}
impl<T> TestErr<T> {
fn get_stored_backtrace(&self) -> &Backtrace {
match self {
Self::NamedImplicitBacktraceByFieldName { backtrace, .. } => backtrace,
Self::NamedImplicitBacktraceByFieldType {
implicit_backtrace, ..
} => implicit_backtrace,
Self::NamedExplicitBacktrace {
explicit_backtrace, ..
} => explicit_backtrace,
Self::NamedExplicitBacktraceByFieldNameRedundant { backtrace, .. } => {
backtrace
}
Self::NamedExplicitBacktraceByFieldTypeRedundant {
implicit_backtrace,
..
} => implicit_backtrace,
Self::NamedExplicitSuppressesImplicit { not_backtrace, .. } => {
not_backtrace
}
Self::UnnamedImplicitBacktrace(backtrace, _, _) => backtrace,
Self::UnnamedExplicitBacktrace(backtrace, _, _) => backtrace,
Self::UnnamedExplicitBacktraceRedundant(backtrace, _, _) => backtrace,
Self::UnnamedExplicitSuppressesImplicit(backtrace, _, _) => backtrace,
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
}
}
fn get_unused_backtrace(&self) -> &Backtrace {
match self {
Self::NamedExplicitSuppressesImplicit { backtrace, .. } => backtrace,
Self::UnnamedExplicitSuppressesImplicit(_, backtrace, _) => backtrace,
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
}
}
}
type MyBacktrace = Backtrace;
#[test]
fn unit() {
assert!(request_ref::<Backtrace>(&TestErr::<i32>::Unit).is_none());
}
#[test]
fn named_implicit_no_backtrace() {
let err = TestErr::NamedImplicitNoBacktrace { field: 0 };
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_implicit_backtrace_by_field_name() {
let err = TestErr::NamedImplicitBacktraceByFieldName {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_implicit_backtrace_by_field_type() {
let err = TestErr::NamedImplicitBacktraceByFieldType {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_no_backtrace_by_field_name() {
let err = TestErr::NamedExplicitNoBacktraceByFieldName {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_by_field_type() {
let err = TestErr::NamedExplicitNoBacktraceByFieldType {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_backtrace() {
let err = TestErr::NamedExplicitBacktrace {
explicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_no_backtrace_redundant() {
let err = TestErr::NamedExplicitNoBacktraceRedundant {
not_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_by_field_name_redundant() {
let err = TestErr::NamedExplicitBacktraceByFieldNameRedundant {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_backtrace_by_field_type_redundant() {
let err = TestErr::NamedExplicitBacktraceByFieldTypeRedundant {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn named_explicit_suppresses_implicit() {
let err = TestErr::NamedExplicitSuppressesImplicit {
not_backtrace: Backtrace::force_capture(),
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_unused_backtrace);
}
#[test]
fn unnamed_implicit_no_backtrace() {
let err = TestErr::UnnamedImplicitNoBacktrace(0, 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_implicit_backtrace() {
let err = TestErr::UnnamedImplicitBacktrace(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_no_backtrace() {
let err = TestErr::UnnamedExplicitNoBacktrace(Backtrace::force_capture(), 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace() {
let err = TestErr::UnnamedExplicitBacktrace(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_no_backtrace_redundant() {
let err =
TestErr::UnnamedExplicitNoBacktraceRedundant(Backtrace::force_capture(), 0);
assert!(request_ref::<Backtrace>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_redundant() {
let err =
TestErr::UnnamedExplicitBacktraceRedundant(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
}
#[test]
fn unnamed_explicit_suppresses_implicit() {
let err = TestErr::UnnamedExplicitSuppressesImplicit(
Backtrace::force_capture(),
(|| Backtrace::force_capture())(), // ensure backtraces are different
0,
);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_unused_backtrace);
}
derive_display!(BoundedTestErr, T);
#[derive(Debug, Error)]
enum BoundedTestErr<T> {
NamedImplicitNoBacktraceFromSource {
#[error(source)]
err: T,
},
NamedExplicitNoBacktraceFromSource {
#[error(source, not(backtrace))]
err: T,
},
NamedExplicitBacktraceFromSource {
#[error(backtrace, source)]
err: T,
},
NamedImplicitDifferentSourceAndBacktrace {
#[error(source)]
err: T,
backtrace: Backtrace,
},
NamedExplicitDifferentSourceAndBacktrace {
#[error(source)]
err: T,
#[error(backtrace)]
backtrace: Backtrace,
},
UnnamedImplicitNoBacktraceFromSource(T),
UnnamedExplicitNoBacktraceFromSource(#[error(not(backtrace))] T),
UnnamedExplicitBacktraceFromSource(#[error(backtrace)] T),
UnnamedImplicitDifferentSourceAndBacktrace(#[error(source)] T, Backtrace),
UnnamedExplicitDifferentSourceAndBacktrace(
#[error(source)] T,
#[error(backtrace)] Backtrace,
),
}
impl<T: Error> BoundedTestErr<T> {
fn get_stored_backtrace(&self) -> &Backtrace {
match self {
Self::NamedImplicitDifferentSourceAndBacktrace { backtrace, .. }
| Self::NamedExplicitDifferentSourceAndBacktrace { backtrace, .. }
| Self::UnnamedImplicitDifferentSourceAndBacktrace(_, backtrace)
| Self::UnnamedExplicitDifferentSourceAndBacktrace(_, backtrace) => {
backtrace
}
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
}
}
fn get_source_backtrace(&self) -> &Backtrace {
request_ref(match self {
Self::NamedExplicitBacktraceFromSource { err }
| Self::NamedExplicitDifferentSourceAndBacktrace { err, .. }
| Self::NamedImplicitDifferentSourceAndBacktrace { err, .. }
| Self::UnnamedExplicitBacktraceFromSource(err)
| Self::UnnamedExplicitDifferentSourceAndBacktrace(err, ..)
| Self::UnnamedImplicitDifferentSourceAndBacktrace(err, ..) => err,
_ => panic!("ERROR IN TEST IMPLEMENTATION"),
})
.unwrap()
}
}
#[test]
fn named_implicit_no_backtrace_from_source() {
let err = BoundedTestErr::NamedImplicitNoBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_from_source() {
let err = BoundedTestErr::NamedExplicitNoBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_from_source() {
let err = BoundedTestErr::NamedExplicitBacktraceFromSource {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_source_backtrace);
}
#[test]
fn named_implicit_different_source_and_backtrace() {
let err = BoundedTestErr::NamedImplicitDifferentSourceAndBacktrace {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn named_explicit_different_source_and_backtrace() {
let err = BoundedTestErr::NamedExplicitDifferentSourceAndBacktrace {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn unnamed_implicit_no_backtrace_from_source() {
let err = BoundedTestErr::UnnamedImplicitNoBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_no_backtrace_from_source() {
let err = BoundedTestErr::UnnamedExplicitNoBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_from_source() {
let err = BoundedTestErr::UnnamedExplicitBacktraceFromSource(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_source_backtrace);
}
#[test]
fn unnamed_implicit_different_source_and_backtrace() {
let err = BoundedTestErr::UnnamedImplicitDifferentSourceAndBacktrace(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}
#[test]
fn unnamed_explicit_different_source_and_backtrace() {
let err = BoundedTestErr::UnnamedExplicitDifferentSourceAndBacktrace(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .get_stored_backtrace);
assert_bt!(!=, err, .get_source_backtrace);
}

View File

@@ -0,0 +1,478 @@
// For creating backtraces with different addresses in tests.
#![allow(clippy::redundant_closure, clippy::redundant_closure_call)] // for testing
#![allow(dead_code)] // some code is tested for type checking only
use core::error::{request_ref, request_value};
use super::*;
#[test]
fn named_implicit_no_backtrace() {
derive_display!(TestErr, T);
#[derive(Default, Debug, Error)]
struct TestErr<T> {
field: T,
}
assert!(request_ref::<Backtrace>(&TestErr::<i32>::default()).is_none());
}
#[test]
fn named_implicit_backtrace_by_field_name() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
backtrace: MyBacktrace,
field: T,
}
type MyBacktrace = Backtrace;
let err = TestErr {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err);
}
#[test]
fn named_implicit_backtrace_by_field_type() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
implicit_backtrace: Backtrace,
field: T,
}
let err = TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, implicit_backtrace);
}
#[test]
fn named_explicit_no_backtrace_by_field_name() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(not(backtrace))]
backtrace: MyBacktrace,
field: T,
}
type MyBacktrace = Backtrace;
assert!(request_ref::<Backtrace>(&TestErr {
backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_no_backtrace_by_field_type() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(not(backtrace))]
implicit_backtrace: Backtrace,
field: T,
}
assert!(request_ref::<Backtrace>(&TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(backtrace)]
explicit_backtrace: MyBacktrace,
field: T,
}
type MyBacktrace = Backtrace;
let err = TestErr {
explicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, explicit_backtrace);
}
#[test]
fn named_explicit_no_backtrace_redundant() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(not(backtrace))]
not_backtrace: MyBacktrace,
#[error(not(backtrace))]
field: T,
}
type MyBacktrace = Backtrace;
assert!(request_ref::<Backtrace>(&TestErr {
not_backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_backtrace_by_field_name_redundant() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(backtrace)]
backtrace: MyBacktrace,
field: T,
}
type MyBacktrace = Backtrace;
let err = TestErr {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err);
}
#[test]
fn named_explicit_backtrace_by_field_type_redundant() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(backtrace)]
implicit_backtrace: Backtrace,
field: T,
}
let err = TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, implicit_backtrace);
}
#[test]
fn named_explicit_suppresses_implicit() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(backtrace)]
not_backtrace: MyBacktrace,
backtrace: Backtrace,
field: T,
}
type MyBacktrace = Backtrace;
let err = TestErr {
not_backtrace: Backtrace::force_capture(),
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, not_backtrace);
assert_bt!(!=, err);
}
#[test]
fn named_implicit_no_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(source)]
err: T,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(source, not(backtrace))]
err: T,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(backtrace, source)]
err: T,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn named_implicit_different_source_and_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(source)]
err: T,
backtrace: Backtrace,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, backtrace);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn named_explicit_different_source_and_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T> {
#[error(source)]
err: T,
#[error(backtrace)]
backtrace: Backtrace,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, backtrace);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn unnamed_implicit_no_backtrace() {
derive_display!(TestErr, T);
#[derive(Default, Debug, Error)]
struct TestErr<T>(T, T);
assert!(request_ref::<Backtrace>(&TestErr::<i32>::default()).is_none());
}
#[test]
fn unnamed_implicit_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(Backtrace, T, T);
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_no_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(not(backtrace))] Backtrace, T);
assert!(
request_ref::<Backtrace>(&TestErr(Backtrace::force_capture(), 0)).is_none()
);
}
#[test]
fn unnamed_explicit_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(backtrace)] MyBacktrace, T, T);
type MyBacktrace = Backtrace;
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_no_backtrace_redundant() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(
#[error(not(backtrace))] MyBacktrace,
#[error(not(backtrace))] T,
);
type MyBacktrace = Backtrace;
assert!(
request_ref::<Backtrace>(&TestErr(Backtrace::force_capture(), 0)).is_none()
);
}
#[test]
fn unnamed_explicit_backtrace_redundant() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(backtrace)] Backtrace, T, T);
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_suppresses_implicit() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(backtrace)] MyBacktrace, Backtrace, T);
type MyBacktrace = Backtrace;
let err = TestErr(
Backtrace::force_capture(),
(|| Backtrace::force_capture())(), // ensure backtraces are different
0,
);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
assert_bt!(!=, err, .1);
}
#[test]
fn unnamed_implicit_no_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(T);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_no_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(not(backtrace))] T);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_from_source() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(backtrace)] T);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, request_ref::<Backtrace>(&err.0).unwrap());
}
#[test]
fn unnamed_implicit_different_source_and_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(source)] T, Backtrace);
let err = TestErr(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .1);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.0).unwrap());
}
#[test]
fn unnamed_explicit_different_source_and_backtrace() {
derive_display!(TestErr, T);
#[derive(Debug, Error)]
struct TestErr<T>(#[error(source)] T, #[error(backtrace)] Backtrace);
let err = TestErr(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .1);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.0).unwrap());
}

View File

@@ -0,0 +1,483 @@
// For creating backtraces with different addresses in tests.
#![allow(clippy::redundant_closure, clippy::redundant_closure_call)] // for testing
#![allow(dead_code)] // some code is tested for type checking only
use core::error::{request_ref, request_value};
use super::*;
#[test]
fn unit() {
assert!(request_ref::<Backtrace>(&SimpleErr).is_none());
}
#[test]
fn named_implicit_no_backtrace() {
derive_display!(TestErr);
#[derive(Default, Debug, Error)]
struct TestErr {
field: i32,
}
assert!(request_ref::<Backtrace>(&TestErr::default()).is_none());
}
#[test]
fn named_implicit_backtrace_by_field_name() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
backtrace: MyBacktrace,
field: i32,
}
type MyBacktrace = Backtrace;
let err = TestErr {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err);
}
#[test]
fn named_implicit_backtrace_by_field_type() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
implicit_backtrace: Backtrace,
field: i32,
}
let err = TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, implicit_backtrace);
}
#[test]
fn named_explicit_no_backtrace_by_field_name() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(not(backtrace))]
backtrace: MyBacktrace,
field: i32,
}
type MyBacktrace = Backtrace;
assert!(request_ref::<Backtrace>(&TestErr {
backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_no_backtrace_by_field_type() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(not(backtrace))]
implicit_backtrace: Backtrace,
field: i32,
}
assert!(request_ref::<Backtrace>(&TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(backtrace)]
explicit_backtrace: MyBacktrace,
field: i32,
}
type MyBacktrace = Backtrace;
let err = TestErr {
explicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, explicit_backtrace);
}
#[test]
fn named_explicit_no_backtrace_redundant() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(not(backtrace))]
not_backtrace: MyBacktrace,
#[error(not(backtrace))]
field: i32,
}
type MyBacktrace = Backtrace;
assert!(request_ref::<Backtrace>(&TestErr {
not_backtrace: Backtrace::force_capture(),
field: 0
})
.is_none());
}
#[test]
fn named_explicit_backtrace_by_field_name_redundant() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(backtrace)]
backtrace: MyBacktrace,
field: i32,
}
type MyBacktrace = Backtrace;
let err = TestErr {
backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err);
}
#[test]
fn named_explicit_backtrace_by_field_type_redundant() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(backtrace)]
implicit_backtrace: Backtrace,
field: i32,
}
let err = TestErr {
implicit_backtrace: Backtrace::force_capture(),
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, implicit_backtrace);
}
#[test]
fn named_explicit_suppresses_implicit() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(backtrace)]
not_backtrace: MyBacktrace,
backtrace: Backtrace,
field: i32,
}
type MyBacktrace = Backtrace;
let err = TestErr {
not_backtrace: Backtrace::force_capture(),
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
field: 0,
};
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, not_backtrace);
assert_bt!(!=, err);
}
#[test]
fn named_implicit_no_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(source)]
err: BacktraceErr,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_no_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(source, not(backtrace))]
err: BacktraceErr,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn named_explicit_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(backtrace, source)]
err: BacktraceErr,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn named_implicit_different_source_and_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(source)]
err: BacktraceErr,
backtrace: Backtrace,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, backtrace);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn named_explicit_different_source_and_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr {
#[error(source)]
err: BacktraceErr,
#[error(backtrace)]
backtrace: Backtrace,
}
let err = TestErr {
err: BacktraceErr {
backtrace: Backtrace::force_capture(),
},
backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different
};
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, backtrace);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.err).unwrap());
}
#[test]
fn unnamed_implicit_no_backtrace() {
derive_display!(TestErr);
#[derive(Default, Debug, Error)]
struct TestErr(i32, i32);
assert!(request_ref::<Backtrace>(&TestErr::default()).is_none());
}
#[test]
fn unnamed_implicit_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(Backtrace, i32, i32);
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_no_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(not(backtrace))] Backtrace, i32);
assert!(
request_ref::<Backtrace>(&TestErr(Backtrace::force_capture(), 0)).is_none()
);
}
#[test]
fn unnamed_explicit_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(backtrace)] MyBacktrace, i32, i32);
type MyBacktrace = Backtrace;
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_no_backtrace_redundant() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(
#[error(not(backtrace))] MyBacktrace,
#[error(not(backtrace))] i32,
);
type MyBacktrace = Backtrace;
assert!(
request_ref::<Backtrace>(&TestErr(Backtrace::force_capture(), 0)).is_none()
);
}
#[test]
fn unnamed_explicit_backtrace_redundant() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(backtrace)] Backtrace, i32, i32);
let err = TestErr(Backtrace::force_capture(), 0, 0);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
}
#[test]
fn unnamed_explicit_suppresses_implicit() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(backtrace)] MyBacktrace, Backtrace, i32);
type MyBacktrace = Backtrace;
let err = TestErr(
Backtrace::force_capture(),
(|| Backtrace::force_capture())(), // ensure backtraces are different
0,
);
assert!(request_ref::<Backtrace>(&err).is_some());
assert_bt!(==, err, .0);
assert_bt!(!=, err, .1);
}
#[test]
fn unnamed_implicit_no_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(BacktraceErr);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_no_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(not(backtrace))] BacktraceErr);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_none());
assert!(request_value::<i32>(&err).is_none());
}
#[test]
fn unnamed_explicit_backtrace_from_source() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(backtrace)] BacktraceErr);
let err = TestErr(BacktraceErr {
backtrace: Backtrace::force_capture(),
});
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, request_ref::<Backtrace>(&err.0).unwrap());
}
#[test]
fn unnamed_implicit_different_source_and_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(source)] BacktraceErr, Backtrace);
let err = TestErr(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .1);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.0).unwrap());
}
#[test]
fn unnamed_explicit_different_source_and_backtrace() {
derive_display!(TestErr);
#[derive(Debug, Error)]
struct TestErr(#[error(source)] BacktraceErr, #[error(backtrace)] Backtrace);
let err = TestErr(
BacktraceErr {
backtrace: Backtrace::force_capture(),
},
(|| Backtrace::force_capture())(), // ensure backtraces are different
);
assert!(err.source().is_some());
assert!(request_ref::<Backtrace>(&err).is_some());
assert_eq!(request_value::<i32>(&err), Some(42));
assert_bt!(==, err, .1);
assert_bt!(!=, err, request_ref::<Backtrace>(&err.0).unwrap());
}

View File

@@ -0,0 +1,93 @@
use std::backtrace::Backtrace;
use super::*;
/// Asserts that backtrace returned by `Error::backtrace` method equals/not-equals
/// backtrace stored in object itself.
///
/// Comparison is done by converting backtraces to strings
/// and then comparing these strings.
///
/// ## Syntax
///
/// * Equals: `assert_bt!(==, ...)`
/// * Not-equals: `assert_bt!(!=, ...)`
///
/// ### Backtrace Access
///
/// Shortcut for named-structs with `backtrace` field.
/// Access backtrace as `error.backtrace`.
///
/// ```
/// assert_bt!(==, error);
/// ```
///
/// Full form for named- and tuple-structs.
/// Access backtrace as `error.some_other_field` and `error.1` respectively.
///
/// ```
/// assert_bt!(!=, error, some_other_field);
/// assert_bt!(==, error, 1);
/// ```
///
/// Access as a method call.
/// Useful for enums (i.e., you can define a method that will match on enum variants
/// and return backtrace for each variant).
/// Access backtrace as `error.get_stored_backtrace_method()`.
///
/// ```
/// assert_bt!(!=, error, .get_stored_backtrace_method);
/// ```
macro_rules! assert_bt {
(@impl $macro:ident, $error:expr, $backtrace:expr) => {
$macro!(::core::error::request_ref::<Backtrace>(&$error).unwrap().to_string(), $backtrace.to_string());
};
(@expand $macro:ident, $error:expr, .$backtrace:ident) => {
assert_bt!(@impl $macro, $error, $error.$backtrace())
};
(@expand $macro:ident, $error:expr, .$backtrace:tt) => {
assert_bt!(@impl $macro, $error, $error.$backtrace)
};
(@expand $macro:ident, $error:expr, $backtrace:ident) => {
assert_bt!(@impl $macro, $error, $error.$backtrace)
};
(@expand $macro:ident, $error:expr, $backtrace:expr) => {
assert_bt!(@impl $macro, $error, $backtrace)
};
(@expand $macro:ident, $error:expr) => {
assert_bt!(@expand $macro, $error, backtrace)
};
(==, $($args:tt)*) => {
assert_bt!(@expand assert_eq, $($args)*)
};
(!=, $($args:tt)*) => {
assert_bt!(@expand assert_ne, $($args)*)
};
}
mod derives_for_enums_with_backtrace;
mod derives_for_generic_enums_with_backtrace;
mod derives_for_generic_structs_with_backtrace;
mod derives_for_structs_with_backtrace;
derive_display!(BacktraceErr);
#[derive(Debug)]
struct BacktraceErr {
backtrace: Backtrace,
}
impl Default for BacktraceErr {
fn default() -> Self {
Self {
backtrace: Backtrace::force_capture(),
}
}
}
impl Error for BacktraceErr {
fn provide<'a>(&'a self, request: &mut std::error::Request<'a>) {
request
.provide_ref::<Backtrace>(&self.backtrace)
.provide_value::<i32>(42);
}
}