diff options
Diffstat (limited to 'vendor/thiserror/tests/test_display.rs')
| -rw-r--r-- | vendor/thiserror/tests/test_display.rs | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/vendor/thiserror/tests/test_display.rs b/vendor/thiserror/tests/test_display.rs new file mode 100644 index 00000000..bb7c9231 --- /dev/null +++ b/vendor/thiserror/tests/test_display.rs @@ -0,0 +1,478 @@ +#![allow( + clippy::elidable_lifetime_names, + clippy::needless_lifetimes, + clippy::needless_raw_string_hashes, + clippy::trivially_copy_pass_by_ref, + clippy::uninlined_format_args +)] + +use core::fmt::{self, Display}; +use thiserror::Error; + +fn assert<T: Display>(expected: &str, value: T) { + assert_eq!(expected, value.to_string()); +} + +#[test] +fn test_braced() { + #[derive(Error, Debug)] + #[error("braced error: {msg}")] + struct Error { + msg: String, + } + + let msg = "T".to_owned(); + assert("braced error: T", Error { msg }); +} + +#[test] +fn test_braced_unused() { + #[derive(Error, Debug)] + #[error("braced error")] + struct Error { + extra: usize, + } + + assert("braced error", Error { extra: 0 }); +} + +#[test] +fn test_tuple() { + #[derive(Error, Debug)] + #[error("tuple error: {0}")] + struct Error(usize); + + assert("tuple error: 0", Error(0)); +} + +#[test] +fn test_unit() { + #[derive(Error, Debug)] + #[error("unit error")] + struct Error; + + assert("unit error", Error); +} + +#[test] +fn test_enum() { + #[derive(Error, Debug)] + enum Error { + #[error("braced error: {id}")] + Braced { id: usize }, + #[error("tuple error: {0}")] + Tuple(usize), + #[error("unit error")] + Unit, + } + + assert("braced error: 0", Error::Braced { id: 0 }); + assert("tuple error: 0", Error::Tuple(0)); + assert("unit error", Error::Unit); +} + +#[test] +fn test_constants() { + #[derive(Error, Debug)] + #[error("{MSG}: {id:?} (code {CODE:?})")] + struct Error { + id: &'static str, + } + + const MSG: &str = "failed to do"; + const CODE: usize = 9; + + assert("failed to do: \"\" (code 9)", Error { id: "" }); +} + +#[test] +fn test_inherit() { + #[derive(Error, Debug)] + #[error("{0}")] + enum Error { + Some(&'static str), + #[error("other error")] + Other(&'static str), + } + + assert("some error", Error::Some("some error")); + assert("other error", Error::Other("...")); +} + +#[test] +fn test_brace_escape() { + #[derive(Error, Debug)] + #[error("fn main() {{}}")] + struct Error; + + assert("fn main() {}", Error); +} + +#[test] +fn test_expr() { + #[derive(Error, Debug)] + #[error("1 + 1 = {}", 1 + 1)] + struct Error; + assert("1 + 1 = 2", Error); +} + +#[test] +fn test_nested() { + #[derive(Error, Debug)] + #[error("!bool = {}", not(.0))] + struct Error(bool); + + #[allow(clippy::trivially_copy_pass_by_ref)] + fn not(bool: &bool) -> bool { + !*bool + } + + assert("!bool = false", Error(true)); +} + +#[test] +fn test_match() { + #[derive(Error, Debug)] + #[error("{intro}: {0}", intro = match .1 { + Some(n) => format!("error occurred with {}", n), + None => "there was an empty error".to_owned(), + })] + struct Error(String, Option<usize>); + + assert( + "error occurred with 1: ...", + Error("...".to_owned(), Some(1)), + ); + assert( + "there was an empty error: ...", + Error("...".to_owned(), None), + ); +} + +#[test] +fn test_nested_display() { + // Same behavior as the one in `test_match`, but without String allocations. + #[derive(Error, Debug)] + #[error("{}", { + struct Msg<'a>(&'a String, &'a Option<usize>); + impl<'a> Display for Msg<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.1 { + Some(n) => write!(formatter, "error occurred with {}", n), + None => write!(formatter, "there was an empty error"), + }?; + write!(formatter, ": {}", self.0) + } + } + Msg(.0, .1) + })] + struct Error(String, Option<usize>); + + assert( + "error occurred with 1: ...", + Error("...".to_owned(), Some(1)), + ); + assert( + "there was an empty error: ...", + Error("...".to_owned(), None), + ); +} + +#[test] +fn test_void() { + #[allow(clippy::empty_enum)] + #[derive(Error, Debug)] + #[error("...")] + pub enum Error {} + + let _: Error; +} + +#[test] +fn test_mixed() { + #[derive(Error, Debug)] + #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)] + struct Error { + a: usize, + d: usize, + } + + assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 }); +} + +#[test] +fn test_ints() { + #[derive(Error, Debug)] + enum Error { + #[error("error {0}")] + Tuple(usize, usize), + #[error("error {0}", '?')] + Struct { v: usize }, + } + + assert("error 9", Error::Tuple(9, 0)); + assert("error ?", Error::Struct { v: 0 }); +} + +#[test] +fn test_trailing_comma() { + #[derive(Error, Debug)] + #[error( + "error {0}", + )] + #[rustfmt::skip] + struct Error(char); + + assert("error ?", Error('?')); +} + +#[test] +fn test_field() { + #[derive(Debug)] + struct Inner { + data: usize, + } + + #[derive(Error, Debug)] + #[error("{}", .0.data)] + struct Error(Inner); + + assert("0", Error(Inner { data: 0 })); +} + +#[test] +fn test_nested_tuple_field() { + #[derive(Debug)] + struct Inner(usize); + + #[derive(Error, Debug)] + #[error("{}", .0.0)] + struct Error(Inner); + + assert("0", Error(Inner(0))); +} + +#[test] +fn test_pointer() { + #[derive(Error, Debug)] + #[error("{field:p}")] + pub struct Struct { + field: Box<i32>, + } + + let s = Struct { + field: Box::new(-1), + }; + assert_eq!(s.to_string(), format!("{:p}", s.field)); +} + +#[test] +fn test_macro_rules_variant_from_call_site() { + // Regression test for https://github.com/dtolnay/thiserror/issues/86 + + macro_rules! decl_error { + ($variant:ident($value:ident)) => { + #[derive(Error, Debug)] + pub enum Error0 { + #[error("{0:?}")] + $variant($value), + } + + #[derive(Error, Debug)] + #[error("{0:?}")] + pub enum Error1 { + $variant($value), + } + }; + } + + decl_error!(Repro(u8)); + + assert("0", Error0::Repro(0)); + assert("0", Error1::Repro(0)); +} + +#[test] +fn test_macro_rules_message_from_call_site() { + // Regression test for https://github.com/dtolnay/thiserror/issues/398 + + macro_rules! decl_error { + ($($errors:tt)*) => { + #[derive(Error, Debug)] + pub enum Error { + $($errors)* + } + }; + } + + decl_error! { + #[error("{0}")] + Unnamed(u8), + #[error("{x}")] + Named { x: u8 }, + } + + assert("0", Error::Unnamed(0)); + assert("0", Error::Named { x: 0 }); +} + +#[test] +fn test_raw() { + #[derive(Error, Debug)] + #[error("braced raw error: {fn}")] + struct Error { + r#fn: &'static str, + } + + assert("braced raw error: T", Error { r#fn: "T" }); +} + +#[test] +fn test_raw_enum() { + #[derive(Error, Debug)] + enum Error { + #[error("braced raw error: {fn}")] + Braced { r#fn: &'static str }, + } + + assert("braced raw error: T", Error::Braced { r#fn: "T" }); +} + +#[test] +fn test_keyword() { + #[derive(Error, Debug)] + #[error("error: {type}", type = 1)] + struct Error; + + assert("error: 1", Error); +} + +#[test] +fn test_self() { + #[derive(Error, Debug)] + #[error("error: {self:?}")] + struct Error; + + assert("error: Error", Error); +} + +#[test] +fn test_str_special_chars() { + #[derive(Error, Debug)] + pub enum Error { + #[error("brace left {{")] + BraceLeft, + #[error("brace left 2 \x7B\x7B")] + BraceLeft2, + #[error("brace left 3 \u{7B}\u{7B}")] + BraceLeft3, + #[error("brace right }}")] + BraceRight, + #[error("brace right 2 \x7D\x7D")] + BraceRight2, + #[error("brace right 3 \u{7D}\u{7D}")] + BraceRight3, + #[error( + "new_\ +line" + )] + NewLine, + #[error("escape24 \u{78}")] + Escape24, + } + + assert("brace left {", Error::BraceLeft); + assert("brace left 2 {", Error::BraceLeft2); + assert("brace left 3 {", Error::BraceLeft3); + assert("brace right }", Error::BraceRight); + assert("brace right 2 }", Error::BraceRight2); + assert("brace right 3 }", Error::BraceRight3); + assert("new_line", Error::NewLine); + assert("escape24 x", Error::Escape24); +} + +#[test] +fn test_raw_str() { + #[derive(Error, Debug)] + pub enum Error { + #[error(r#"raw brace left {{"#)] + BraceLeft, + #[error(r#"raw brace left 2 \x7B"#)] + BraceLeft2, + #[error(r#"raw brace right }}"#)] + BraceRight, + #[error(r#"raw brace right 2 \x7D"#)] + BraceRight2, + } + + assert(r#"raw brace left {"#, Error::BraceLeft); + assert(r#"raw brace left 2 \x7B"#, Error::BraceLeft2); + assert(r#"raw brace right }"#, Error::BraceRight); + assert(r#"raw brace right 2 \x7D"#, Error::BraceRight2); +} + +mod util { + use core::fmt::{self, Octal}; + + pub fn octal<T: Octal>(value: &T, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "0o{:o}", value) + } +} + +#[test] +fn test_fmt_path() { + fn unit(formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("unit=") + } + + fn pair(k: &i32, v: &i32, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "pair={k}:{v}") + } + + #[derive(Error, Debug)] + pub enum Error { + #[error(fmt = unit)] + Unit, + #[error(fmt = pair)] + Tuple(i32, i32), + #[error(fmt = pair)] + Entry { k: i32, v: i32 }, + #[error(fmt = crate::util::octal)] + I16(i16), + #[error(fmt = crate::util::octal::<i32>)] + I32 { n: i32 }, + #[error(fmt = core::fmt::Octal::fmt)] + I64(i64), + #[error("...{0}")] + Other(bool), + } + + assert("unit=", Error::Unit); + assert("pair=10:0", Error::Tuple(10, 0)); + assert("pair=10:0", Error::Entry { k: 10, v: 0 }); + assert("0o777", Error::I16(0o777)); + assert("0o777", Error::I32 { n: 0o777 }); + assert("777", Error::I64(0o777)); + assert("...false", Error::Other(false)); +} + +#[test] +fn test_fmt_path_inherited() { + #[derive(Error, Debug)] + #[error(fmt = crate::util::octal)] + pub enum Error { + I16(i16), + I32 { + n: i32, + }, + #[error(fmt = core::fmt::Octal::fmt)] + I64(i64), + #[error("...{0}")] + Other(bool), + } + + assert("0o777", Error::I16(0o777)); + assert("0o777", Error::I32 { n: 0o777 }); + assert("777", Error::I64(0o777)); + assert("...false", Error::Other(false)); +} |
