5 #[derive(Debug, PartialEq)]
7 #[derive(Debug, PartialEq)]
10 impl fmt::Display for A {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 impl fmt::Display for B {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 let a = &mut a as &mut (dyn Error + 'static);
28 assert_eq!(a.downcast_ref::<A>(), Some(&A));
29 assert_eq!(a.downcast_ref::<B>(), None);
30 assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
31 assert_eq!(a.downcast_mut::<B>(), None);
33 let a: Box<dyn Error> = Box::new(A);
34 match a.downcast::<B>() {
35 Ok(..) => panic!("expected error"),
36 Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
40 use crate::backtrace::Backtrace;
41 use crate::error::Report;
45 source: SuperErrorSideKick,
48 impl fmt::Display for SuperError {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "SuperError is here!")
54 impl Error for SuperError {
55 fn source(&self) -> Option<&(dyn Error + 'static)> {
61 struct SuperErrorSideKick;
63 impl fmt::Display for SuperErrorSideKick {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 write!(f, "SuperErrorSideKick is here!")
69 impl Error for SuperErrorSideKick {}
72 fn single_line_formatting() {
73 let error = SuperError { source: SuperErrorSideKick };
74 let report = Report::new(&error);
75 let actual = report.to_string();
76 let expected = String::from("SuperError is here!: SuperErrorSideKick is here!");
78 assert_eq!(expected, actual);
82 fn multi_line_formatting() {
83 let error = SuperError { source: SuperErrorSideKick };
84 let report = Report::new(&error).pretty(true);
85 let actual = report.to_string();
86 let expected = String::from(
91 SuperErrorSideKick is here!",
94 assert_eq!(expected, actual);
98 fn error_with_no_sources_formats_single_line_correctly() {
99 let report = Report::new(SuperErrorSideKick);
100 let actual = report.to_string();
101 let expected = String::from("SuperErrorSideKick is here!");
103 assert_eq!(expected, actual);
107 fn error_with_no_sources_formats_multi_line_correctly() {
108 let report = Report::new(SuperErrorSideKick).pretty(true);
109 let actual = report.to_string();
110 let expected = String::from("SuperErrorSideKick is here!");
112 assert_eq!(expected, actual);
116 fn error_with_backtrace_outputs_correctly_with_one_source() {
117 let trace = Backtrace::force_capture();
118 let expected = format!(
120 The source of the error
129 let error = GenericError::new("Error with backtrace");
130 let mut error = GenericError::new_with_source("The source of the error", error);
131 error.backtrace = Some(trace);
132 let report = Report::new(error).pretty(true).show_backtrace(true);
134 println!("Error: {report}");
135 assert_eq!(expected.trim_end(), report.to_string());
139 fn error_with_backtrace_outputs_correctly_with_two_sources() {
140 let trace = Backtrace::force_capture();
141 let expected = format!(
143 Error with two sources
146 0: The source of the error
147 1: Error with backtrace
153 let mut error = GenericError::new("Error with backtrace");
154 error.backtrace = Some(trace);
155 let error = GenericError::new_with_source("The source of the error", error);
156 let error = GenericError::new_with_source("Error with two sources", error);
157 let report = Report::new(error).pretty(true).show_backtrace(true);
159 println!("Error: {report}");
160 assert_eq!(expected.trim_end(), report.to_string());
164 struct GenericError<D> {
166 backtrace: Option<Backtrace>,
167 source: Option<Box<dyn Error + 'static>>,
170 impl<D> GenericError<D> {
171 fn new(message: D) -> GenericError<D> {
172 Self { message, backtrace: None, source: None }
175 fn new_with_source<E>(message: D, source: E) -> GenericError<D>
179 let source: Box<dyn Error + 'static> = Box::new(source);
180 let source = Some(source);
181 GenericError { message, backtrace: None, source }
185 impl<D> fmt::Display for GenericError<D>
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 fmt::Display::fmt(&self.message, f)
194 impl<D> Error for GenericError<D>
196 D: fmt::Debug + fmt::Display,
198 fn source(&self) -> Option<&(dyn Error + 'static)> {
199 self.source.as_deref()
202 fn provide<'a>(&'a self, req: &mut Demand<'a>) {
203 self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt));
208 fn error_formats_single_line_with_rude_display_impl() {
212 impl fmt::Display for MyMessage {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 f.write_str("line 1\nline 2")?;
215 f.write_str("\nline 3\nline 4\n")?;
216 f.write_str("line 5\nline 6")?;
221 let error = GenericError::new(MyMessage);
222 let error = GenericError::new_with_source(MyMessage, error);
223 let error = GenericError::new_with_source(MyMessage, error);
224 let error = GenericError::new_with_source(MyMessage, error);
225 let report = Report::new(error);
249 let actual = report.to_string();
250 assert_eq!(expected, actual);
254 fn error_formats_multi_line_with_rude_display_impl() {
258 impl fmt::Display for MyMessage {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 f.write_str("line 1\nline 2")?;
261 f.write_str("\nline 3\nline 4\n")?;
262 f.write_str("line 5\nline 6")?;
267 let error = GenericError::new(MyMessage);
268 let error = GenericError::new_with_source(MyMessage, error);
269 let error = GenericError::new_with_source(MyMessage, error);
270 let error = GenericError::new_with_source(MyMessage, error);
271 let report = Report::new(error).pretty(true);
272 let expected = "line 1
299 let actual = report.to_string();
300 assert_eq!(expected, actual);
304 fn errors_that_start_with_newline_formats_correctly() {
308 impl fmt::Display for MyMessage {
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 f.write_str("\nThe message\n")
314 let error = GenericError::new(MyMessage);
315 let error = GenericError::new_with_source(MyMessage, error);
316 let error = GenericError::new_with_source(MyMessage, error);
317 let report = Report::new(error).pretty(true);
330 let actual = report.to_string();
331 assert_eq!(expected, actual);
335 fn errors_with_multiple_writes_on_same_line_dont_insert_erroneous_newlines() {
339 impl fmt::Display for MyMessage {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 f.write_str("The message")?;
342 f.write_str(" goes on")?;
343 f.write_str(" and on.")
347 let error = GenericError::new(MyMessage);
348 let error = GenericError::new_with_source(MyMessage, error);
349 let error = GenericError::new_with_source(MyMessage, error);
350 let report = Report::new(error).pretty(true);
352 The message goes on and on.
355 0: The message goes on and on.
356 1: The message goes on and on.";
358 let actual = report.to_string();
359 println!("{actual}");
360 assert_eq!(expected, actual);
364 fn errors_with_string_interpolation_formats_correctly() {
366 struct MyMessage(usize);
368 impl fmt::Display for MyMessage {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 write!(f, "Got an error code: ({}). ", self.0)?;
371 write!(f, "What would you like to do in response?")
375 let error = GenericError::new(MyMessage(10));
376 let error = GenericError::new_with_source(MyMessage(20), error);
377 let report = Report::new(error).pretty(true);
379 Got an error code: (20). What would you like to do in response?
382 Got an error code: (10). What would you like to do in response?";
383 let actual = report.to_string();
384 assert_eq!(expected, actual);
388 fn empty_lines_mid_message() {
392 impl fmt::Display for MyMessage {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 f.write_str("line 1\n\nline 2")
398 let error = GenericError::new(MyMessage);
399 let error = GenericError::new_with_source(MyMessage, error);
400 let error = GenericError::new_with_source(MyMessage, error);
401 let report = Report::new(error).pretty(true);
415 let actual = report.to_string();
416 assert_eq!(expected, actual);
420 fn only_one_source() {
424 impl fmt::Display for MyMessage {
425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426 f.write_str("line 1\nline 2")
430 let error = GenericError::new(MyMessage);
431 let error = GenericError::new_with_source(MyMessage, error);
432 let report = Report::new(error).pretty(true);
441 let actual = report.to_string();
442 assert_eq!(expected, actual);