mod debug_struct { use std::fmt; #[test] fn test_empty() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo").finish() } } assert_eq!("Foo", format!("{Foo:?}")); assert_eq!("Foo", format!("{Foo:#?}")); } #[test] fn test_single() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo").field("bar", &true).finish() } } assert_eq!("Foo { bar: true }", format!("{Foo:?}")); assert_eq!( "Foo { bar: true, }", format!("{Foo:#?}") ); } #[test] fn test_multiple() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo") .field("bar", &true) .field("baz", &format_args!("{}/{}", 10, 20)) .finish() } } assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{Foo:?}")); assert_eq!( "Foo { bar: true, baz: 10/20, }", format!("{Foo:#?}") ); } #[test] fn test_nested() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo") .field("bar", &true) .field("baz", &format_args!("{}/{}", 10, 20)) .finish() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Bar").field("foo", &Foo).field("hello", &"world").finish() } } assert_eq!( r#"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: "world" }"#, format!("{Bar:?}") ); assert_eq!( r#"Bar { foo: Foo { bar: true, baz: 10/20, }, hello: "world", }"#, format!("{Bar:#?}") ); } #[test] fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo").finish_non_exhaustive() } } assert_eq!("Foo { .. }", format!("{Foo:?}")); assert_eq!("Foo { .. }", format!("{Foo:#?}")); } #[test] fn test_multiple_and_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo") .field("bar", &true) .field("baz", &format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{Foo:?}")); assert_eq!( "Foo { bar: true, baz: 10/20, .. }", format!("{Foo:#?}") ); } #[test] fn test_nested_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Foo") .field("bar", &true) .field("baz", &format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Bar") .field("foo", &Foo) .field("hello", &"world") .finish_non_exhaustive() } } assert_eq!( r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#, format!("{Bar:?}") ); assert_eq!( r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#, format!("{Bar:#?}") ); } } mod debug_tuple { use std::fmt; #[test] fn test_empty() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo").finish() } } assert_eq!("Foo", format!("{Foo:?}")); assert_eq!("Foo", format!("{Foo:#?}")); } #[test] fn test_single() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo").field(&true).finish() } } assert_eq!("Foo(true)", format!("{Foo:?}")); assert_eq!( "Foo( true, )", format!("{Foo:#?}") ); } #[test] fn test_multiple() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo").field(&true).field(&format_args!("{}/{}", 10, 20)).finish() } } assert_eq!("Foo(true, 10/20)", format!("{Foo:?}")); assert_eq!( "Foo( true, 10/20, )", format!("{Foo:#?}") ); } #[test] fn test_nested() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo").field(&true).field(&format_args!("{}/{}", 10, 20)).finish() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish() } } assert_eq!(r#"Bar(Foo(true, 10/20), "world")"#, format!("{Bar:?}")); assert_eq!( r#"Bar( Foo( true, 10/20, ), "world", )"#, format!("{Bar:#?}") ); } #[test] fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo").finish_non_exhaustive() } } assert_eq!("Foo(..)", format!("{Foo:?}")); assert_eq!("Foo(..)", format!("{Foo:#?}")); } #[test] fn test_multiple_and_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo") .field(&true) .field(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } assert_eq!("Foo(true, 10/20, ..)", format!("{Foo:?}")); assert_eq!( "Foo( true, 10/20, .. )", format!("{Foo:#?}") ); } #[test] fn test_nested_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Foo") .field(&true) .field(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish_non_exhaustive() } } assert_eq!(r#"Bar(Foo(true, 10/20, ..), "world", ..)"#, format!("{Bar:?}")); assert_eq!( r#"Bar( Foo( true, 10/20, .. ), "world", .. )"#, format!("{Bar:#?}") ); } } mod debug_map { use std::fmt; #[test] fn test_empty() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().finish() } } assert_eq!("{}", format!("{Foo:?}")); assert_eq!("{}", format!("{Foo:#?}")); } #[test] fn test_single() { struct Entry; impl fmt::Debug for Entry { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().entry(&"bar", &true).finish() } } struct KeyValue; impl fmt::Debug for KeyValue { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().key(&"bar").value(&true).finish() } } assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); assert_eq!(r#"{"bar": true}"#, format!("{Entry:?}")); assert_eq!( r#"{ "bar": true, }"#, format!("{Entry:#?}") ); } #[test] fn test_multiple() { struct Entry; impl fmt::Debug for Entry { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .entry(&"bar", &true) .entry(&10, &format_args!("{}/{}", 10, 20)) .finish() } } struct KeyValue; impl fmt::Debug for KeyValue { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .key(&"bar") .value(&true) .key(&10) .value(&format_args!("{}/{}", 10, 20)) .finish() } } assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); assert_eq!(r#"{"bar": true, 10: 10/20}"#, format!("{Entry:?}")); assert_eq!( r#"{ "bar": true, 10: 10/20, }"#, format!("{Entry:#?}") ); } #[test] fn test_nested() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .entry(&"bar", &true) .entry(&10, &format_args!("{}/{}", 10, 20)) .finish() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish() } } assert_eq!( r#"{"foo": {"bar": true, 10: 10/20}, {"bar": true, 10: 10/20}: "world"}"#, format!("{Bar:?}") ); assert_eq!( r#"{ "foo": { "bar": true, 10: 10/20, }, { "bar": true, 10: 10/20, }: "world", }"#, format!("{Bar:#?}") ); } #[test] fn test_entry_err() { // Ensure errors in a map entry don't trigger panics (#65231) use std::fmt::Write; struct ErrorFmt; impl fmt::Debug for ErrorFmt { fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { Err(fmt::Error) } } struct KeyValue(usize, K, V); impl fmt::Debug for KeyValue where K: fmt::Debug, V: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut map = fmt.debug_map(); for _ in 0..self.0 { map.entry(&self.1, &self.2); } map.finish() } } let mut buf = String::new(); assert!(write!(&mut buf, "{:?}", KeyValue(1, ErrorFmt, "bar")).is_err()); assert!(write!(&mut buf, "{:?}", KeyValue(1, "foo", ErrorFmt)).is_err()); assert!(write!(&mut buf, "{:?}", KeyValue(2, ErrorFmt, "bar")).is_err()); assert!(write!(&mut buf, "{:?}", KeyValue(2, "foo", ErrorFmt)).is_err()); } #[test] #[should_panic] fn test_invalid_key_when_entry_is_incomplete() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().key(&"bar").key(&"invalid").finish() } } let _ = format!("{Foo:?}"); } #[test] #[should_panic] fn test_invalid_finish_incomplete_entry() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().key(&"bar").finish() } } let _ = format!("{Foo:?}"); } #[test] #[should_panic] fn test_invalid_value_before_key() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().value(&"invalid").key(&"bar").finish() } } let _ = format!("{Foo:?}"); } #[test] fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().finish_non_exhaustive() } } assert_eq!("{..}", format!("{Foo:?}")); assert_eq!("{..}", format!("{Foo:#?}")); } #[test] fn test_multiple_and_non_exhaustive() { struct Entry; impl fmt::Debug for Entry { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .entry(&"bar", &true) .entry(&10, &format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct KeyValue; impl fmt::Debug for KeyValue { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .key(&"bar") .value(&true) .key(&10) .value(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); assert_eq!(r#"{"bar": true, 10: 10/20, ..}"#, format!("{Entry:?}")); assert_eq!( r#"{ "bar": true, 10: 10/20, .. }"#, format!("{Entry:#?}") ); } #[test] fn test_nested_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map() .entry(&"bar", &true) .entry(&10, &format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish_non_exhaustive() } } assert_eq!( r#"{"foo": {"bar": true, 10: 10/20, ..}, {"bar": true, 10: 10/20, ..}: "world", ..}"#, format!("{Bar:?}") ); assert_eq!( r#"{ "foo": { "bar": true, 10: 10/20, .. }, { "bar": true, 10: 10/20, .. }: "world", .. }"#, format!("{Bar:#?}") ); } } mod debug_set { use std::fmt; #[test] fn test_empty() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().finish() } } assert_eq!("{}", format!("{Foo:?}")); assert_eq!("{}", format!("{Foo:#?}")); } #[test] fn test_single() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().entry(&true).finish() } } assert_eq!("{true}", format!("{Foo:?}")); assert_eq!( "{ true, }", format!("{Foo:#?}") ); } #[test] fn test_multiple() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish() } } assert_eq!("{true, 10/20}", format!("{Foo:?}")); assert_eq!( "{ true, 10/20, }", format!("{Foo:#?}") ); } #[test] fn test_nested() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().entry(&Foo).entry(&"world").finish() } } assert_eq!(r#"{{true, 10/20}, "world"}"#, format!("{Bar:?}")); assert_eq!( r#"{ { true, 10/20, }, "world", }"#, format!("{Bar:#?}") ); } #[test] fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().finish_non_exhaustive() } } assert_eq!("{..}", format!("{Foo:?}")); assert_eq!("{..}", format!("{Foo:#?}")); } #[test] fn test_multiple_and_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set() .entry(&true) .entry(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } assert_eq!("{true, 10/20, ..}", format!("{Foo:?}")); assert_eq!( "{ true, 10/20, .. }", format!("{Foo:#?}") ); } #[test] fn test_nested_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set() .entry(&true) .entry(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_set().entry(&Foo).entry(&"world").finish_non_exhaustive() } } assert_eq!(r#"{{true, 10/20, ..}, "world", ..}"#, format!("{Bar:?}")); assert_eq!( r#"{ { true, 10/20, .. }, "world", .. }"#, format!("{Bar:#?}") ); } } mod debug_list { use std::fmt; #[test] fn test_empty() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().finish() } } assert_eq!("[]", format!("{Foo:?}")); assert_eq!("[]", format!("{Foo:#?}")); } #[test] fn test_single() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().entry(&true).finish() } } assert_eq!("[true]", format!("{Foo:?}")); assert_eq!( "[ true, ]", format!("{Foo:#?}") ); } #[test] fn test_multiple() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish() } } assert_eq!("[true, 10/20]", format!("{Foo:?}")); assert_eq!( "[ true, 10/20, ]", format!("{Foo:#?}") ); } #[test] fn test_nested() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().entry(&true).entry(&format_args!("{}/{}", 10, 20)).finish() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().entry(&Foo).entry(&"world").finish() } } assert_eq!(r#"[[true, 10/20], "world"]"#, format!("{Bar:?}")); assert_eq!( r#"[ [ true, 10/20, ], "world", ]"#, format!("{Bar:#?}") ); } #[test] fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().finish_non_exhaustive() } } assert_eq!("[..]", format!("{Foo:?}")); assert_eq!("[..]", format!("{Foo:#?}")); } #[test] fn test_multiple_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list() .entry(&true) .entry(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } assert_eq!("[true, 10/20, ..]", format!("{Foo:?}")); assert_eq!( "[ true, 10/20, .. ]", format!("{Foo:#?}") ); } #[test] fn test_nested_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list() .entry(&true) .entry(&format_args!("{}/{}", 10, 20)) .finish_non_exhaustive() } } struct Bar; impl fmt::Debug for Bar { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_list().entry(&Foo).entry(&"world").finish_non_exhaustive() } } assert_eq!(r#"[[true, 10/20, ..], "world", ..]"#, format!("{Bar:?}")); assert_eq!( r#"[ [ true, 10/20, .. ], "world", .. ]"#, format!("{Bar:#?}") ); } } #[test] fn test_formatting_parameters_are_forwarded() { use std::collections::{BTreeMap, BTreeSet}; #[derive(Debug)] #[allow(dead_code)] struct Foo { bar: u32, baz: u32, } let struct_ = Foo { bar: 1024, baz: 7 }; let tuple = (1024, 7); let list = [1024, 7]; let mut map = BTreeMap::new(); map.insert("bar", 1024); map.insert("baz", 7); let mut set = BTreeSet::new(); set.insert(1024); set.insert(7); assert_eq!(format!("{struct_:03?}"), "Foo { bar: 1024, baz: 007 }"); assert_eq!(format!("{tuple:03?}"), "(1024, 007)"); assert_eq!(format!("{list:03?}"), "[1024, 007]"); assert_eq!(format!("{map:03?}"), r#"{"bar": 1024, "baz": 007}"#); assert_eq!(format!("{set:03?}"), "{007, 1024}"); assert_eq!( format!("{struct_:#03?}"), " Foo { bar: 1024, baz: 007, } " .trim() ); assert_eq!( format!("{tuple:#03?}"), " ( 1024, 007, ) " .trim() ); assert_eq!( format!("{list:#03?}"), " [ 1024, 007, ] " .trim() ); assert_eq!( format!("{map:#03?}"), r#" { "bar": 1024, "baz": 007, } "# .trim() ); assert_eq!( format!("{set:#03?}"), " { 007, 1024, } " .trim() ); }