]> git.proxmox.com Git - rustc.git/blob - library/std/src/error/tests.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / std / src / error / tests.rs
1 use super::Error;
2 use crate::fmt;
3
4 #[derive(Debug, PartialEq)]
5 struct A;
6 #[derive(Debug, PartialEq)]
7 struct B;
8
9 impl fmt::Display for A {
10 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11 write!(f, "A")
12 }
13 }
14 impl fmt::Display for B {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(f, "B")
17 }
18 }
19
20 impl Error for A {}
21 impl Error for B {}
22
23 #[test]
24 fn downcasting() {
25 let mut a = A;
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);
31
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),
36 }
37 }
38
39 use crate::backtrace::Backtrace;
40 use crate::error::Report;
41
42 #[derive(Debug)]
43 struct SuperError {
44 source: SuperErrorSideKick,
45 }
46
47 impl fmt::Display for SuperError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(f, "SuperError is here!")
50 }
51 }
52
53 impl Error for SuperError {
54 fn source(&self) -> Option<&(dyn Error + 'static)> {
55 Some(&self.source)
56 }
57 }
58
59 #[derive(Debug)]
60 struct SuperErrorSideKick;
61
62 impl fmt::Display for SuperErrorSideKick {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "SuperErrorSideKick is here!")
65 }
66 }
67
68 impl Error for SuperErrorSideKick {}
69
70 #[test]
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!");
76
77 assert_eq!(expected, actual);
78 }
79
80 #[test]
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(
86 "\
87 SuperError is here!
88
89 Caused by:
90 SuperErrorSideKick is here!",
91 );
92
93 assert_eq!(expected, actual);
94 }
95
96 #[test]
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!");
101
102 assert_eq!(expected, actual);
103 }
104
105 #[test]
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!");
110
111 assert_eq!(expected, actual);
112 }
113
114 #[test]
115 fn error_with_backtrace_outputs_correctly_with_one_source() {
116 let trace = Backtrace::force_capture();
117 let expected = format!(
118 "\
119 The source of the error
120
121 Caused by:
122 Error with backtrace
123
124 Stack backtrace:
125 {}",
126 trace
127 );
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);
132
133 println!("Error: {report}");
134 assert_eq!(expected.trim_end(), report.to_string());
135 }
136
137 #[test]
138 fn error_with_backtrace_outputs_correctly_with_two_sources() {
139 let trace = Backtrace::force_capture();
140 let expected = format!(
141 "\
142 Error with two sources
143
144 Caused by:
145 0: The source of the error
146 1: Error with backtrace
147
148 Stack backtrace:
149 {}",
150 trace
151 );
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);
157
158 println!("Error: {report}");
159 assert_eq!(expected.trim_end(), report.to_string());
160 }
161
162 #[derive(Debug)]
163 struct GenericError<D> {
164 message: D,
165 backtrace: Option<Backtrace>,
166 source: Option<Box<dyn Error + 'static>>,
167 }
168
169 impl<D> GenericError<D> {
170 fn new(message: D) -> GenericError<D> {
171 Self { message, backtrace: None, source: None }
172 }
173
174 fn new_with_source<E>(message: D, source: E) -> GenericError<D>
175 where
176 E: Error + 'static,
177 {
178 let source: Box<dyn Error + 'static> = Box::new(source);
179 let source = Some(source);
180 GenericError { message, backtrace: None, source }
181 }
182 }
183
184 impl<D> fmt::Display for GenericError<D>
185 where
186 D: fmt::Display,
187 {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 fmt::Display::fmt(&self.message, f)
190 }
191 }
192
193 impl<D> Error for GenericError<D>
194 where
195 D: fmt::Debug + fmt::Display,
196 {
197 fn source(&self) -> Option<&(dyn Error + 'static)> {
198 self.source.as_deref()
199 }
200
201 fn backtrace(&self) -> Option<&Backtrace> {
202 self.backtrace.as_ref()
203 }
204 }
205
206 #[test]
207 fn error_formats_single_line_with_rude_display_impl() {
208 #[derive(Debug)]
209 struct MyMessage;
210
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")?;
216 Ok(())
217 }
218 }
219
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);
225 let expected = "\
226 line 1
227 line 2
228 line 3
229 line 4
230 line 5
231 line 6: line 1
232 line 2
233 line 3
234 line 4
235 line 5
236 line 6: line 1
237 line 2
238 line 3
239 line 4
240 line 5
241 line 6: line 1
242 line 2
243 line 3
244 line 4
245 line 5
246 line 6";
247
248 let actual = report.to_string();
249 assert_eq!(expected, actual);
250 }
251
252 #[test]
253 fn error_formats_multi_line_with_rude_display_impl() {
254 #[derive(Debug)]
255 struct MyMessage;
256
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")?;
262 Ok(())
263 }
264 }
265
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
272 line 2
273 line 3
274 line 4
275 line 5
276 line 6
277
278 Caused by:
279 0: line 1
280 line 2
281 line 3
282 line 4
283 line 5
284 line 6
285 1: line 1
286 line 2
287 line 3
288 line 4
289 line 5
290 line 6
291 2: line 1
292 line 2
293 line 3
294 line 4
295 line 5
296 line 6";
297
298 let actual = report.to_string();
299 assert_eq!(expected, actual);
300 }
301
302 #[test]
303 fn errors_that_start_with_newline_formats_correctly() {
304 #[derive(Debug)]
305 struct MyMessage;
306
307 impl fmt::Display for MyMessage {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 f.write_str("\nThe message\n")
310 }
311 }
312
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);
317 let expected = "
318 The message
319
320
321 Caused by:
322 0: \
323 \n The message
324 \
325 \n 1: \
326 \n The message
327 ";
328
329 let actual = report.to_string();
330 assert_eq!(expected, actual);
331 }
332
333 #[test]
334 fn errors_with_multiple_writes_on_same_line_dont_insert_erroneous_newlines() {
335 #[derive(Debug)]
336 struct MyMessage;
337
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.")
343 }
344 }
345
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);
350 let expected = "\
351 The message goes on and on.
352
353 Caused by:
354 0: The message goes on and on.
355 1: The message goes on and on.";
356
357 let actual = report.to_string();
358 println!("{actual}");
359 assert_eq!(expected, actual);
360 }
361
362 #[test]
363 fn errors_with_string_interpolation_formats_correctly() {
364 #[derive(Debug)]
365 struct MyMessage(usize);
366
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?")
371 }
372 }
373
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);
377 let expected = "\
378 Got an error code: (20). What would you like to do in response?
379
380 Caused by:
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);
384 }
385
386 #[test]
387 fn empty_lines_mid_message() {
388 #[derive(Debug)]
389 struct MyMessage;
390
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")
394 }
395 }
396
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);
401 let expected = "\
402 line 1
403
404 line 2
405
406 Caused by:
407 0: line 1
408 \
409 \n line 2
410 1: line 1
411 \
412 \n line 2";
413
414 let actual = report.to_string();
415 assert_eq!(expected, actual);
416 }
417
418 #[test]
419 fn only_one_source() {
420 #[derive(Debug)]
421 struct MyMessage;
422
423 impl fmt::Display for MyMessage {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 f.write_str("line 1\nline 2")
426 }
427 }
428
429 let error = GenericError::new(MyMessage);
430 let error = GenericError::new_with_source(MyMessage, error);
431 let report = Report::new(error).pretty(true);
432 let expected = "\
433 line 1
434 line 2
435
436 Caused by:
437 line 1
438 line 2";
439
440 let actual = report.to_string();
441 assert_eq!(expected, actual);
442 }