rust/library/std/src/error/tests.rs
T-O-R-U-S 72a25d05bf Use implicit capture syntax in format_args
This updates the standard library's documentation to use the new syntax. The
documentation is worthwhile to update as it should be more idiomatic
(particularly for features like this, which are nice for users to get acquainted
with). The general codebase is likely more hassle than benefit to update: it'll
hurt git blame, and generally updates can be done by folks updating the code if
(and when) that makes things more readable with the new format.

A few places in the compiler and library code are updated (mostly just due to
already having been done when this commit was first authored).
2022-03-10 10:23:40 -05:00

443 lines
10 KiB
Rust

use super::Error;
use crate::fmt;
#[derive(Debug, PartialEq)]
struct A;
#[derive(Debug, PartialEq)]
struct B;
impl fmt::Display for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "A")
}
}
impl fmt::Display for B {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "B")
}
}
impl Error for A {}
impl Error for B {}
#[test]
fn downcasting() {
let mut a = A;
let a = &mut a as &mut (dyn Error + 'static);
assert_eq!(a.downcast_ref::<A>(), Some(&A));
assert_eq!(a.downcast_ref::<B>(), None);
assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
assert_eq!(a.downcast_mut::<B>(), None);
let a: Box<dyn Error> = Box::new(A);
match a.downcast::<B>() {
Ok(..) => panic!("expected error"),
Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
}
}
use crate::backtrace::Backtrace;
use crate::error::Report;
#[derive(Debug)]
struct SuperError {
source: SuperErrorSideKick,
}
impl fmt::Display for SuperError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SuperError is here!")
}
}
impl Error for SuperError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.source)
}
}
#[derive(Debug)]
struct SuperErrorSideKick;
impl fmt::Display for SuperErrorSideKick {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SuperErrorSideKick is here!")
}
}
impl Error for SuperErrorSideKick {}
#[test]
fn single_line_formatting() {
let error = SuperError { source: SuperErrorSideKick };
let report = Report::new(&error);
let actual = report.to_string();
let expected = String::from("SuperError is here!: SuperErrorSideKick is here!");
assert_eq!(expected, actual);
}
#[test]
fn multi_line_formatting() {
let error = SuperError { source: SuperErrorSideKick };
let report = Report::new(&error).pretty(true);
let actual = report.to_string();
let expected = String::from(
"\
SuperError is here!
Caused by:
SuperErrorSideKick is here!",
);
assert_eq!(expected, actual);
}
#[test]
fn error_with_no_sources_formats_single_line_correctly() {
let report = Report::new(SuperErrorSideKick);
let actual = report.to_string();
let expected = String::from("SuperErrorSideKick is here!");
assert_eq!(expected, actual);
}
#[test]
fn error_with_no_sources_formats_multi_line_correctly() {
let report = Report::new(SuperErrorSideKick).pretty(true);
let actual = report.to_string();
let expected = String::from("SuperErrorSideKick is here!");
assert_eq!(expected, actual);
}
#[test]
fn error_with_backtrace_outputs_correctly_with_one_source() {
let trace = Backtrace::force_capture();
let expected = format!(
"\
The source of the error
Caused by:
Error with backtrace
Stack backtrace:
{}",
trace
);
let error = GenericError::new("Error with backtrace");
let mut error = GenericError::new_with_source("The source of the error", error);
error.backtrace = Some(trace);
let report = Report::new(error).pretty(true).show_backtrace(true);
println!("Error: {report}");
assert_eq!(expected.trim_end(), report.to_string());
}
#[test]
fn error_with_backtrace_outputs_correctly_with_two_sources() {
let trace = Backtrace::force_capture();
let expected = format!(
"\
Error with two sources
Caused by:
0: The source of the error
1: Error with backtrace
Stack backtrace:
{}",
trace
);
let mut error = GenericError::new("Error with backtrace");
error.backtrace = Some(trace);
let error = GenericError::new_with_source("The source of the error", error);
let error = GenericError::new_with_source("Error with two sources", error);
let report = Report::new(error).pretty(true).show_backtrace(true);
println!("Error: {report}");
assert_eq!(expected.trim_end(), report.to_string());
}
#[derive(Debug)]
struct GenericError<D> {
message: D,
backtrace: Option<Backtrace>,
source: Option<Box<dyn Error + 'static>>,
}
impl<D> GenericError<D> {
fn new(message: D) -> GenericError<D> {
Self { message, backtrace: None, source: None }
}
fn new_with_source<E>(message: D, source: E) -> GenericError<D>
where
E: Error + 'static,
{
let source: Box<dyn Error + 'static> = Box::new(source);
let source = Some(source);
GenericError { message, backtrace: None, source }
}
}
impl<D> fmt::Display for GenericError<D>
where
D: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.message, f)
}
}
impl<D> Error for GenericError<D>
where
D: fmt::Debug + fmt::Display,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.source.as_deref()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.backtrace.as_ref()
}
}
#[test]
fn error_formats_single_line_with_rude_display_impl() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("line 1\nline 2")?;
f.write_str("\nline 3\nline 4\n")?;
f.write_str("line 5\nline 6")?;
Ok(())
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error);
let expected = "\
line 1
line 2
line 3
line 4
line 5
line 6: line 1
line 2
line 3
line 4
line 5
line 6: line 1
line 2
line 3
line 4
line 5
line 6: line 1
line 2
line 3
line 4
line 5
line 6";
let actual = report.to_string();
assert_eq!(expected, actual);
}
#[test]
fn error_formats_multi_line_with_rude_display_impl() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("line 1\nline 2")?;
f.write_str("\nline 3\nline 4\n")?;
f.write_str("line 5\nline 6")?;
Ok(())
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error).pretty(true);
let expected = "line 1
line 2
line 3
line 4
line 5
line 6
Caused by:
0: line 1
line 2
line 3
line 4
line 5
line 6
1: line 1
line 2
line 3
line 4
line 5
line 6
2: line 1
line 2
line 3
line 4
line 5
line 6";
let actual = report.to_string();
assert_eq!(expected, actual);
}
#[test]
fn errors_that_start_with_newline_formats_correctly() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("\nThe message\n")
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error).pretty(true);
let expected = "
The message
Caused by:
0: \
\n The message
\
\n 1: \
\n The message
";
let actual = report.to_string();
assert_eq!(expected, actual);
}
#[test]
fn errors_with_multiple_writes_on_same_line_dont_insert_erroneous_newlines() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("The message")?;
f.write_str(" goes on")?;
f.write_str(" and on.")
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error).pretty(true);
let expected = "\
The message goes on and on.
Caused by:
0: The message goes on and on.
1: The message goes on and on.";
let actual = report.to_string();
println!("{actual}");
assert_eq!(expected, actual);
}
#[test]
fn errors_with_string_interpolation_formats_correctly() {
#[derive(Debug)]
struct MyMessage(usize);
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Got an error code: ({}). ", self.0)?;
write!(f, "What would you like to do in response?")
}
}
let error = GenericError::new(MyMessage(10));
let error = GenericError::new_with_source(MyMessage(20), error);
let report = Report::new(error).pretty(true);
let expected = "\
Got an error code: (20). What would you like to do in response?
Caused by:
Got an error code: (10). What would you like to do in response?";
let actual = report.to_string();
assert_eq!(expected, actual);
}
#[test]
fn empty_lines_mid_message() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("line 1\n\nline 2")
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error).pretty(true);
let expected = "\
line 1
line 2
Caused by:
0: line 1
\
\n line 2
1: line 1
\
\n line 2";
let actual = report.to_string();
assert_eq!(expected, actual);
}
#[test]
fn only_one_source() {
#[derive(Debug)]
struct MyMessage;
impl fmt::Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("line 1\nline 2")
}
}
let error = GenericError::new(MyMessage);
let error = GenericError::new_with_source(MyMessage, error);
let report = Report::new(error).pretty(true);
let expected = "\
line 1
line 2
Caused by:
line 1
line 2";
let actual = report.to_string();
assert_eq!(expected, actual);
}