4 #[derive(Debug, PartialEq)]
6 #[derive(Debug, PartialEq)]
9 impl fmt::Display for A {
10 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 impl fmt::Display for B {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 let a = &mut a as &mut (dyn Error + 'static);
27 assert_eq!(a.downcast_ref::<A>(), Some(&A));
28 assert_eq!(a.downcast_ref::<B>(), None);
29 assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
30 assert_eq!(a.downcast_mut::<B>(), None);
32 let a: Box<dyn Error> = Box::new(A);
33 match a.downcast::<B>() {
34 Ok(..) => panic!("expected error"),
35 Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
39 use crate::backtrace::Backtrace;
40 use crate::error::Report;
44 source: SuperErrorSideKick,
47 impl fmt::Display for SuperError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(f, "SuperError is here!")
53 impl Error for SuperError {
54 fn source(&self) -> Option<&(dyn Error + 'static)> {
60 struct SuperErrorSideKick;
62 impl fmt::Display for SuperErrorSideKick {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "SuperErrorSideKick is here!")
68 impl Error for SuperErrorSideKick {}
71 fn single_line_formatting() {
72 let error = SuperError { source: SuperErrorSideKick };
73 let report = Report::new(&error);
74 let actual = report.to_string();
75 let expected = String::from("SuperError is here!: SuperErrorSideKick is here!");
77 assert_eq!(expected, actual);
81 fn multi_line_formatting() {
82 let error = SuperError { source: SuperErrorSideKick };
83 let report = Report::new(&error).pretty(true);
84 let actual = report.to_string();
85 let expected = String::from(
90 SuperErrorSideKick is here!",
93 assert_eq!(expected, actual);
97 fn error_with_no_sources_formats_single_line_correctly() {
98 let report = Report::new(SuperErrorSideKick);
99 let actual = report.to_string();
100 let expected = String::from("SuperErrorSideKick is here!");
102 assert_eq!(expected, actual);
106 fn error_with_no_sources_formats_multi_line_correctly() {
107 let report = Report::new(SuperErrorSideKick).pretty(true);
108 let actual = report.to_string();
109 let expected = String::from("SuperErrorSideKick is here!");
111 assert_eq!(expected, actual);
115 fn error_with_backtrace_outputs_correctly_with_one_source() {
116 let trace = Backtrace::force_capture();
117 let expected = format!(
119 The source of the error
128 let error = GenericError::new("Error with backtrace");
129 let mut error = GenericError::new_with_source("The source of the error", error);
130 error.backtrace = Some(trace);
131 let report = Report::new(error).pretty(true).show_backtrace(true);
133 println!("Error: {}", report);
134 assert_eq!(expected.trim_end(), report.to_string());
138 fn error_with_backtrace_outputs_correctly_with_two_sources() {
139 let trace = Backtrace::force_capture();
140 let expected = format!(
142 Error with two sources
145 0: The source of the error
146 1: Error with backtrace
152 let mut error = GenericError::new("Error with backtrace");
153 error.backtrace = Some(trace);
154 let error = GenericError::new_with_source("The source of the error", error);
155 let error = GenericError::new_with_source("Error with two sources", error);
156 let report = Report::new(error).pretty(true).show_backtrace(true);
158 println!("Error: {}", report);
159 assert_eq!(expected.trim_end(), report.to_string());
163 struct GenericError<D> {
165 backtrace: Option<Backtrace>,
166 source: Option<Box<dyn Error + 'static>>,
169 impl<D> GenericError<D> {
170 fn new(message: D) -> GenericError<D> {
171 Self { message, backtrace: None, source: None }
174 fn new_with_source<E>(message: D, source: E) -> GenericError<D>
178 let source: Box<dyn Error + 'static> = Box::new(source);
179 let source = Some(source);
180 GenericError { message, backtrace: None, source }
184 impl<D> fmt::Display for GenericError<D>
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 fmt::Display::fmt(&self.message, f)
193 impl<D> Error for GenericError<D>
195 D: fmt::Debug + fmt::Display,
197 fn source(&self) -> Option<&(dyn Error + 'static)> {
198 self.source.as_deref()
201 fn backtrace(&self) -> Option<&Backtrace> {
202 self.backtrace.as_ref()
207 fn error_formats_single_line_with_rude_display_impl() {
211 impl fmt::Display for MyMessage {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 f.write_str("line 1\nline 2")?;
214 f.write_str("\nline 3\nline 4\n")?;
215 f.write_str("line 5\nline 6")?;
220 let error = GenericError::new(MyMessage);
221 let error = GenericError::new_with_source(MyMessage, error);
222 let error = GenericError::new_with_source(MyMessage, error);
223 let error = GenericError::new_with_source(MyMessage, error);
224 let report = Report::new(error);
248 let actual = report.to_string();
249 assert_eq!(expected, actual);
253 fn error_formats_multi_line_with_rude_display_impl() {
257 impl fmt::Display for MyMessage {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.write_str("line 1\nline 2")?;
260 f.write_str("\nline 3\nline 4\n")?;
261 f.write_str("line 5\nline 6")?;
266 let error = GenericError::new(MyMessage);
267 let error = GenericError::new_with_source(MyMessage, error);
268 let error = GenericError::new_with_source(MyMessage, error);
269 let error = GenericError::new_with_source(MyMessage, error);
270 let report = Report::new(error).pretty(true);
271 let expected = "line 1
298 let actual = report.to_string();
299 assert_eq!(expected, actual);
303 fn errors_that_start_with_newline_formats_correctly() {
307 impl fmt::Display for MyMessage {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 f.write_str("\nThe message\n")
313 let error = GenericError::new(MyMessage);
314 let error = GenericError::new_with_source(MyMessage, error);
315 let error = GenericError::new_with_source(MyMessage, error);
316 let report = Report::new(error).pretty(true);
329 let actual = report.to_string();
330 assert_eq!(expected, actual);
334 fn errors_with_multiple_writes_on_same_line_dont_insert_erroneous_newlines() {
338 impl fmt::Display for MyMessage {
339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 f.write_str("The message")?;
341 f.write_str(" goes on")?;
342 f.write_str(" and on.")
346 let error = GenericError::new(MyMessage);
347 let error = GenericError::new_with_source(MyMessage, error);
348 let error = GenericError::new_with_source(MyMessage, error);
349 let report = Report::new(error).pretty(true);
351 The message goes on and on.
354 0: The message goes on and on.
355 1: The message goes on and on.";
357 let actual = report.to_string();
358 println!("{}", actual);
359 assert_eq!(expected, actual);
363 fn errors_with_string_interpolation_formats_correctly() {
365 struct MyMessage(usize);
367 impl fmt::Display for MyMessage {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 write!(f, "Got an error code: ({}). ", self.0)?;
370 write!(f, "What would you like to do in response?")
374 let error = GenericError::new(MyMessage(10));
375 let error = GenericError::new_with_source(MyMessage(20), error);
376 let report = Report::new(error).pretty(true);
378 Got an error code: (20). What would you like to do in response?
381 Got an error code: (10). What would you like to do in response?";
382 let actual = report.to_string();
383 assert_eq!(expected, actual);
387 fn empty_lines_mid_message() {
391 impl fmt::Display for MyMessage {
392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
393 f.write_str("line 1\n\nline 2")
397 let error = GenericError::new(MyMessage);
398 let error = GenericError::new_with_source(MyMessage, error);
399 let error = GenericError::new_with_source(MyMessage, error);
400 let report = Report::new(error).pretty(true);
414 let actual = report.to_string();
415 assert_eq!(expected, actual);
419 fn only_one_source() {
423 impl fmt::Display for MyMessage {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 f.write_str("line 1\nline 2")
429 let error = GenericError::new(MyMessage);
430 let error = GenericError::new_with_source(MyMessage, error);
431 let report = Report::new(error).pretty(true);
440 let actual = report.to_string();
441 assert_eq!(expected, actual);