rust/library/alloc/tests/fmt.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

324 lines
10 KiB
Rust

#![deny(warnings)]
use std::cell::RefCell;
use std::fmt::{self, Write};
#[test]
fn test_format() {
let s = fmt::format(format_args!("Hello, {}!", "world"));
assert_eq!(s, "Hello, world!");
}
struct A;
struct B;
struct C;
struct D;
impl fmt::LowerHex for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("aloha")
}
}
impl fmt::UpperHex for B {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("adios")
}
}
impl fmt::Display for C {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad_integral(true, "", "123")
}
}
impl fmt::Binary for D {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("aa")?;
f.write_char('☃')?;
f.write_str("bb")
}
}
macro_rules! t {
($a:expr, $b:expr) => {
assert_eq!($a, $b)
};
}
#[test]
fn test_format_macro_interface() {
// Various edge cases without formats
t!(format!(""), "");
t!(format!("hello"), "hello");
t!(format!("hello {{"), "hello {");
// default formatters should work
t!(format!("{}", 1.0f32), "1");
t!(format!("{}", 1.0f64), "1");
t!(format!("{}", "a"), "a");
t!(format!("{}", "a".to_string()), "a");
t!(format!("{}", false), "false");
t!(format!("{}", 'a'), "a");
// At least exercise all the formats
t!(format!("{}", true), "true");
t!(format!("{}", '☃'), "");
t!(format!("{}", 10), "10");
t!(format!("{}", 10_usize), "10");
t!(format!("{:?}", '☃'), "'☃'");
t!(format!("{:?}", 10), "10");
t!(format!("{:?}", 10_usize), "10");
t!(format!("{:?}", "true"), "\"true\"");
t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#);
t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#);
t!(format!("{:o}", 10_usize), "12");
t!(format!("{:x}", 10_usize), "a");
t!(format!("{:X}", 10_usize), "A");
t!(format!("{}", "foo"), "foo");
t!(format!("{}", "foo".to_string()), "foo");
if cfg!(target_pointer_width = "32") {
t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234");
t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234");
} else {
t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234");
t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234");
}
t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
t!(format!("{A:x}"), "aloha");
t!(format!("{B:X}"), "adios");
t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
t!(format!("{1} {0}", 0, 1), "1 0");
t!(format!("{foo} {bar}", foo = 0, bar = 1), "0 1");
t!(format!("{foo} {1} {bar} {0}", 0, 1, foo = 2, bar = 3), "2 1 3 0");
t!(format!("{} {0}", "a"), "a a");
t!(format!("{_foo}", _foo = 6usize), "6");
t!(format!("{foo_bar}", foo_bar = 1), "1");
t!(format!("{}", 5 + 5), "10");
t!(format!("{C:#4}"), "☃123");
t!(format!("{D:b}"), "aa☃bb");
let a: &dyn fmt::Debug = &1;
t!(format!("{a:?}"), "1");
// Formatting strings and their arguments
t!(format!("{}", "a"), "a");
t!(format!("{:4}", "a"), "a ");
t!(format!("{:4}", ""), "");
t!(format!("{:>4}", "a"), " a");
t!(format!("{:<4}", "a"), "a ");
t!(format!("{:^5}", "a"), " a ");
t!(format!("{:^5}", "aa"), " aa ");
t!(format!("{:^4}", "a"), " a ");
t!(format!("{:^4}", "aa"), " aa ");
t!(format!("{:.4}", "a"), "a");
t!(format!("{:4.4}", "a"), "a ");
t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa");
t!(format!("{:2.4}", "aaaaa"), "aaaa");
t!(format!("{:2.4}", "aaaa"), "aaaa");
t!(format!("{:2.4}", "aaa"), "aaa");
t!(format!("{:2.4}", "aa"), "aa");
t!(format!("{:2.4}", "a"), "a ");
t!(format!("{:0>2}", "a"), "0a");
t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa");
t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a = 4), "aaaa");
t!(format!("{:._a$}", "aaaaaaaaaaaaaaaaaa", _a = 4), "aaaa");
t!(format!("{:1$}", "a", 4), "a ");
t!(format!("{1:0$}", 4, "a"), "a ");
t!(format!("{:a$}", "a", a = 4), "a ");
t!(format!("{:-#}", "a"), "a");
t!(format!("{:+#}", "a"), "a");
t!(format!("{:/^10.8}", "1234567890"), "/12345678/");
// Some float stuff
t!(format!("{:}", 1.0f32), "1");
t!(format!("{:}", 1.0f64), "1");
t!(format!("{:.3}", 1.0f64), "1.000");
t!(format!("{:10.3}", 1.0f64), " 1.000");
t!(format!("{:+10.3}", 1.0f64), " +1.000");
t!(format!("{:+10.3}", -1.0f64), " -1.000");
t!(format!("{:e}", 1.2345e6f32), "1.2345e6");
t!(format!("{:e}", 1.2345e6f64), "1.2345e6");
t!(format!("{:E}", 1.2345e6f64), "1.2345E6");
t!(format!("{:.3e}", 1.2345e6f64), "1.234e6");
t!(format!("{:10.3e}", 1.2345e6f64), " 1.234e6");
t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6");
t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6");
// Float edge cases
t!(format!("{}", -0.0), "-0");
t!(format!("{:?}", 0.0), "0.0");
// sign aware zero padding
t!(format!("{:<3}", 1), "1 ");
t!(format!("{:>3}", 1), " 1");
t!(format!("{:^3}", 1), " 1 ");
t!(format!("{:03}", 1), "001");
t!(format!("{:<03}", 1), "001");
t!(format!("{:>03}", 1), "001");
t!(format!("{:^03}", 1), "001");
t!(format!("{:+03}", 1), "+01");
t!(format!("{:<+03}", 1), "+01");
t!(format!("{:>+03}", 1), "+01");
t!(format!("{:^+03}", 1), "+01");
t!(format!("{:#05x}", 1), "0x001");
t!(format!("{:<#05x}", 1), "0x001");
t!(format!("{:>#05x}", 1), "0x001");
t!(format!("{:^#05x}", 1), "0x001");
t!(format!("{:05}", 1.2), "001.2");
t!(format!("{:<05}", 1.2), "001.2");
t!(format!("{:>05}", 1.2), "001.2");
t!(format!("{:^05}", 1.2), "001.2");
t!(format!("{:05}", -1.2), "-01.2");
t!(format!("{:<05}", -1.2), "-01.2");
t!(format!("{:>05}", -1.2), "-01.2");
t!(format!("{:^05}", -1.2), "-01.2");
t!(format!("{:+05}", 1.2), "+01.2");
t!(format!("{:<+05}", 1.2), "+01.2");
t!(format!("{:>+05}", 1.2), "+01.2");
t!(format!("{:^+05}", 1.2), "+01.2");
// Ergonomic format_args!
t!(format!("{0:x} {0:X}", 15), "f F");
t!(format!("{0:x} {0:X} {}", 15), "f F 15");
t!(format!("{:x}{0:X}{a:x}{:X}{1:x}{a:X}", 13, 14, a = 15), "dDfEeF");
t!(format!("{a:x} {a:X}", a = 15), "f F");
// And its edge cases
t!(
format!(
"{a:.0$} {b:.0$} {0:.0$}\n{a:.c$} {b:.c$} {c:.c$}",
4,
a = "abcdefg",
b = "hijklmn",
c = 3
),
"abcd hijk 4\nabc hij 3"
);
t!(format!("{a:.*} {0} {:.*}", 4, 3, "efgh", a = "abcdef"), "abcd 4 efg");
t!(format!("{:.a$} {a} {a:#x}", "aaaaaa", a = 2), "aa 2 0x2");
// Test that pointers don't get truncated.
{
let val = usize::MAX;
let exp = format!("{val:#x}");
t!(format!("{:p}", val as *const isize), exp);
}
// Escaping
t!(format!("{{"), "{");
t!(format!("}}"), "}");
// make sure that format! doesn't move out of local variables
let a = Box::new(3);
format!("{a}");
format!("{a}");
// make sure that format! doesn't cause spurious unused-unsafe warnings when
// it's inside of an outer unsafe block
unsafe {
let a: isize = ::std::mem::transmute(3_usize);
format!("{a}");
}
// test that trailing commas are acceptable
format!("{}", "test",);
format!("{foo}", foo = "test",);
}
// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
#[test]
fn test_write() {
let mut buf = String::new();
let _ = write!(&mut buf, "{}", 3);
{
let w = &mut buf;
let _ = write!(w, "{foo}", foo = 4);
let _ = write!(w, "{}", "hello");
let _ = writeln!(w, "{}", "line");
let _ = writeln!(w, "{foo}", foo = "bar");
let _ = w.write_char('☃');
let _ = w.write_str("str");
}
t!(buf, "34helloline\nbar\n☃str");
}
// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
#[test]
fn test_print() {
print!("hi");
print!("{:?}", vec![0u8]);
println!("hello");
println!("this is a {}", "test");
println!("{foo}", foo = "bar");
}
// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
#[test]
fn test_format_args() {
let mut buf = String::new();
{
let w = &mut buf;
let _ = write!(w, "{}", format_args!("{}", 1));
let _ = write!(w, "{}", format_args!("test"));
let _ = write!(w, "{}", format_args!("{test}", test = 3));
}
let s = buf;
t!(s, "1test3");
let s = fmt::format(format_args!("hello {}", "world"));
t!(s, "hello world");
let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
t!(s, "args were: hello world");
}
#[test]
fn test_order() {
// Make sure format!() arguments are always evaluated in a left-to-right
// ordering
fn foo() -> isize {
static mut FOO: isize = 0;
unsafe {
FOO += 1;
FOO
}
}
assert_eq!(
format!("{} {} {a} {b} {} {c}", foo(), foo(), foo(), a = foo(), b = foo(), c = foo()),
"1 2 4 5 3 6".to_string()
);
}
#[test]
fn test_once() {
// Make sure each argument are evaluated only once even though it may be
// formatted multiple times
fn foo() -> isize {
static mut FOO: isize = 0;
unsafe {
FOO += 1;
FOO
}
}
assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a = foo()), "1 1 1 2 2 2".to_string());
}
#[test]
fn test_refcell() {
let refcell = RefCell::new(5);
assert_eq!(format!("{refcell:?}"), "RefCell { value: 5 }");
let borrow = refcell.borrow_mut();
assert_eq!(format!("{refcell:?}"), "RefCell { value: <borrowed> }");
drop(borrow);
assert_eq!(format!("{refcell:?}"), "RefCell { value: 5 }");
}