From ac4369bea4efbfdec26b29bf3e28b13e8c2a985c Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Wed, 7 Oct 2026 16:43:34 -0700 Subject: [PATCH 1/2] Use indoc for multiline strings in tests Use indoc where it makes visible indentation and before / after comparisons easier to read. Use raw strings for embedded quotes. Not all places were modified. Kept compact strings and escapes where they were subjectively easier to visually inspect. Indoc is only added as a dev-dependency to avoid increasing the runtime dependencies. Assisted-by: Codex, with prior discussion with the maintainers via Zulip https://rust-lang.zulipchat.com/#narrow/channel/357797-t-rustfmt/topic/Characterization.20tests/with/630013200 Codex identified candidates and made the fixes. I directed the scope and reviewed readability tradeoffs rejecting several changes that didn't seem to be worth the churn. --- Cargo.lock | 16 ++++++ Cargo.toml | 1 + src/config/mod.rs | 6 ++- src/emitter/checkstyle.rs | 33 +++++++++--- src/emitter/diff.rs | 30 +++++++++-- src/emitter/json.rs | 105 +++++++++++++++++++++++--------------- src/rustfmt_diff.rs | 9 +++- src/test/mod.rs | 43 +++++++++++++--- 8 files changed, 182 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5126167ca22..f2d1b7d936c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,6 +376,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + [[package]] name = "insta" version = "1.48.0" @@ -585,6 +594,7 @@ dependencies = [ "dirs", "getopts", "ignore", + "indoc", "insta", "itertools", "regex", @@ -616,6 +626,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + [[package]] name = "same-file" version = "1.0.6" diff --git a/Cargo.toml b/Cargo.toml index bf1474284ad..90803560b95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" } semver = "1.0.21" [dev-dependencies] +indoc = "2" tempfile = "3.23.0" insta = { version = "1.48.0", features = ["filters"] } diff --git a/src/config/mod.rs b/src/config/mod.rs index 141933cd7cf..2a51861920d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -550,6 +550,7 @@ fn config_path(options: &dyn CliOptions) -> Result, Error> { #[cfg(test)] mod test { use super::*; + use indoc::formatdoc; use std::str; use crate::config::macro_names::{MacroName, MacroSelectors}; @@ -726,7 +727,10 @@ mod test { let toml = used_options.to_toml().unwrap(); assert_eq!( toml, - format!("merge_derives = {merge_derives}\nskip_children = {skip_children}\n",) + formatdoc! {" + merge_derives = {merge_derives} + skip_children = {skip_children} + "} ); } diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs index c320c16bd1d..e1d8b44ce14 100644 --- a/src/emitter/checkstyle.rs +++ b/src/emitter/checkstyle.rs @@ -68,6 +68,7 @@ where #[cfg(test)] mod tests { use super::*; + use indoc::indoc; use std::path::PathBuf; #[test] @@ -89,11 +90,27 @@ mod tests { #[test] fn emits_single_xml_tree_containing_all_files() { let bin_file = "src/bin.rs"; - let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"]; - let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"]; + let bin_original = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; + let bin_formatted = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; let lib_file = "src/lib.rs"; - let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"]; - let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"]; + let lib_original = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; + let lib_formatted = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; let mut writer = Vec::new(); let mut emitter = CheckstyleEmitter::default(); let _ = emitter.emit_header(&mut writer); @@ -102,8 +119,8 @@ mod tests { &mut writer, FormattedFile { filename: &FileName::Real(PathBuf::from(bin_file)), - original_text: &bin_original.join("\n"), - formatted_text: &bin_formatted.join("\n"), + original_text: bin_original, + formatted_text: bin_formatted, }, ) .unwrap(); @@ -112,8 +129,8 @@ mod tests { &mut writer, FormattedFile { filename: &FileName::Real(PathBuf::from(lib_file)), - original_text: &lib_original.join("\n"), - formatted_text: &lib_formatted.join("\n"), + original_text: lib_original, + formatted_text: lib_formatted, }, ) .unwrap(); diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs index 4e48c59ea29..5f10f71b84d 100644 --- a/src/emitter/diff.rs +++ b/src/emitter/diff.rs @@ -51,6 +51,7 @@ impl Emitter for DiffEmitter { #[cfg(test)] mod tests { use super::*; + use indoc::{formatdoc, indoc}; use std::path::PathBuf; #[test] @@ -75,11 +76,27 @@ mod tests { #[test] fn prints_file_names_when_config_is_enabled() { let bin_file = "src/bin.rs"; - let bin_original = "fn main() {\nprintln!(\"Hello, world!\");\n}"; - let bin_formatted = "fn main() {\n println!(\"Hello, world!\");\n}"; + let bin_original = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; + let bin_formatted = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; let lib_file = "src/lib.rs"; - let lib_original = "fn greet() {\nprintln!(\"Greetings!\");\n}"; - let lib_formatted = "fn greet() {\n println!(\"Greetings!\");\n}"; + let lib_original = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; + let lib_formatted = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; let mut writer = Vec::new(); let mut config = Config::default(); @@ -108,7 +125,10 @@ mod tests { assert_eq!( String::from_utf8(writer).unwrap(), - format!("{bin_file}\n{lib_file}\n"), + formatdoc! {" + {bin_file} + {lib_file} + "}, ) } diff --git a/src/emitter/json.rs b/src/emitter/json.rs index 8c84ff72d04..bc15b424bde 100644 --- a/src/emitter/json.rs +++ b/src/emitter/json.rs @@ -106,6 +106,7 @@ impl JsonEmitter { #[cfg(test)] mod tests { use super::*; + use indoc::indoc; use std::path::PathBuf; #[test] @@ -122,7 +123,12 @@ mod tests { expected_begin_line: 79, expected_end_line: 82, original: String::from("fn Foo() where T: Bar {\n"), - expected: String::from("fn Foo()\nwhere\n T: Bar,\n{\n"), + expected: String::from(indoc! {" + fn Foo() + where + T: Bar, + { + "}), }], }; let mismatch = Mismatch { @@ -213,32 +219,32 @@ mod tests { #[test] fn emits_array_with_files_with_diffs() { let file_name = "src/bin.rs"; - let original = [ - "fn main() {", - "println!(\"Hello, world!\");", - "}", - "", - "#[cfg(test)]", - "mod tests {", - "#[test]", - "fn it_works() {", - " assert_eq!(2 + 2, 4);", - "}", - "}", - ]; - let formatted = [ - "fn main() {", - " println!(\"Hello, world!\");", - "}", - "", - "#[cfg(test)]", - "mod tests {", - " #[test]", - " fn it_works() {", - " assert_eq!(2 + 2, 4);", - " }", - "}", - ]; + let original = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + + #[cfg(test)] + mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } + } + "#}; + let formatted = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + + #[cfg(test)] + mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } + } + "#}; let mut writer = Vec::new(); let mut emitter = JsonEmitter::default(); let _ = emitter.emit_header(&mut writer); @@ -247,8 +253,8 @@ mod tests { &mut writer, FormattedFile { filename: &FileName::Real(PathBuf::from(file_name)), - original_text: &original.join("\n"), - formatted_text: &formatted.join("\n"), + original_text: original, + formatted_text: formatted, }, ) .unwrap(); @@ -269,9 +275,12 @@ mod tests { original_end_line: 10, expected_begin_line: 7, expected_end_line: 10, - original: String::from( - "#[test]\nfn it_works() {\n assert_eq!(2 + 2, 4);\n}\n", - ), + original: String::from(indoc! {" + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } + "}), expected: String::from( " #[test]\n fn it_works() {\n assert_eq!(2 + 2, 4);\n }\n", ), @@ -286,11 +295,27 @@ mod tests { #[test] fn emits_valid_json_with_multiple_files() { let bin_file = "src/bin.rs"; - let bin_original = ["fn main() {", "println!(\"Hello, world!\");", "}"]; - let bin_formatted = ["fn main() {", " println!(\"Hello, world!\");", "}"]; + let bin_original = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; + let bin_formatted = indoc! {r#" + fn main() { + println!("Hello, world!"); + } + "#}; let lib_file = "src/lib.rs"; - let lib_original = ["fn greet() {", "println!(\"Greetings!\");", "}"]; - let lib_formatted = ["fn greet() {", " println!(\"Greetings!\");", "}"]; + let lib_original = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; + let lib_formatted = indoc! {r#" + fn greet() { + println!("Greetings!"); + } + "#}; let mut writer = Vec::new(); let mut emitter = JsonEmitter::default(); let _ = emitter.emit_header(&mut writer); @@ -299,8 +324,8 @@ mod tests { &mut writer, FormattedFile { filename: &FileName::Real(PathBuf::from(bin_file)), - original_text: &bin_original.join("\n"), - formatted_text: &bin_formatted.join("\n"), + original_text: bin_original, + formatted_text: bin_formatted, }, ) .unwrap(); @@ -309,8 +334,8 @@ mod tests { &mut writer, FormattedFile { filename: &FileName::Real(PathBuf::from(lib_file)), - original_text: &lib_original.join("\n"), - formatted_text: &lib_formatted.join("\n"), + original_text: lib_original, + formatted_text: lib_formatted, }, ) .unwrap(); diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 4624683fa05..1734f5c02d5 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -284,6 +284,7 @@ mod test { use super::DiffLine::*; use super::{Mismatch, make_diff}; use super::{ModifiedChunk, ModifiedLines}; + use indoc::indoc; #[test] fn diff_simple() { @@ -370,7 +371,13 @@ mod test { fn modified_lines_from_str() { use std::str::FromStr; - let src = "1 6 2\nfn some() {}\nfn main() {}\n25 3 1\n struct Test {}"; + let src = indoc! {" + 1 6 2 + fn some() {} + fn main() {} + 25 3 1 + struct Test {} + "}; let lines = ModifiedLines::from_str(src).unwrap(); assert_eq!( lines, diff --git a/src/test/mod.rs b/src/test/mod.rs index c1007511126..7c27b7b8f8b 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1,3 +1,4 @@ +use indoc::indoc; use std::collections::HashMap; use std::env; use std::fs; @@ -619,7 +620,14 @@ fn stdin_formatting_smoke_test() { } #[cfg(not(windows))] - assert_eq!(buf, ":\n\nfn main() {}\n".as_bytes()); + { + let expected = indoc! {" + : + + fn main() {} + "}; + assert_eq!(buf, expected.as_bytes()); + } #[cfg(windows)] assert_eq!(buf, ":\n\nfn main() {}\r\n".as_bytes()); } @@ -644,8 +652,19 @@ fn stdin_parser_panic_caught() { #[test] fn stdin_works_with_modified_lines() { init_log(); - let input = "\nfn\n some( )\n{\n}\nfn main () {}\n"; - let output = "1 6 2\nfn some() {}\nfn main() {}\n"; + let input = indoc! {" + + fn + some( ) + { + } + fn main () {} + "}; + let output = indoc! {" + 1 6 2 + fn some() {} + fn main() {} + "}; let input = Input::Text(input.to_owned()); let mut config = Config::default(); @@ -715,7 +734,10 @@ fn stdin_disable_all_formatting_test() { #[test] fn stdin_generated_files_issue_5172() { init_log(); - let input = Input::Text("//@generated\nfn main() {}".to_owned()); + let input = Input::Text(String::from(indoc! {" + //@generated + fn main() {} + "})); let mut config = Config::default(); config.set().emit_mode(EmitMode::Stdout); config.set().format_generated_files(false); @@ -729,7 +751,12 @@ fn stdin_generated_files_issue_5172() { // N.B. this should be changed once `format_generated_files` is supported with stdin assert_eq!( String::from_utf8(buf).unwrap(), - ":\n\n//@generated\nfn main() {}\n", + indoc! {" + : + + //@generated + fn main() {} + "}, ); } @@ -737,7 +764,11 @@ fn stdin_generated_files_issue_5172() { fn stdin_handles_mod_inner_ignore_attr() { // see https://github.com/rust-lang/rustfmt/issues/5368 init_log(); - let input = String::from("#![rustfmt::skip]\n\nfn main() { }"); + let input = String::from(indoc! {" + #![rustfmt::skip] + + fn main() { } + "}); let mut child = Command::new(rustfmt().to_str().unwrap()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) From 5c23798dbbb7e83d68e02cc3205c11cc9130c664 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Fri, 9 Oct 2026 12:57:26 -0700 Subject: [PATCH 2/2] Use panicdoc for multiline test diagnostics --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- tests/cargo-fmt/main.rs | 23 ++++++++++++----------- tests/rustfmt/main.rs | 21 +++++++++++---------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2d1b7d936c..95ff171b7ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,9 +378,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1" dependencies = [ "rustversion", ] diff --git a/Cargo.toml b/Cargo.toml index 90803560b95..9b27c543197 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" } semver = "1.0.21" [dev-dependencies] -indoc = "2" +indoc = "2.0.8" tempfile = "3.23.0" insta = { version = "1.48.0", features = ["filters"] } diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs index 63cc12521a8..f6da068aa95 100644 --- a/tests/cargo-fmt/main.rs +++ b/tests/cargo-fmt/main.rs @@ -1,5 +1,6 @@ // Integration tests for cargo-fmt. +use indoc::panicdoc; use std::env; use std::path::Path; use std::process::Command; @@ -43,17 +44,17 @@ macro_rules! assert_that { ($args:expr, $check:ident $check_args:tt) => { let (stdout, stderr) = cargo_fmt($args); if !stdout.$check$check_args { - panic!( - "Output not expected for cargo-fmt {:?}\n\ - expected: {}{}\n\ - actual stdout:\n{}\n\ - actual stderr:\n{}", - $args, - stringify!($check), - stringify!($check_args), - stdout, - stderr - ); + let args = $args; + let check = stringify!($check); + let check_args = stringify!($check_args); + panicdoc! {" + Output not expected for cargo-fmt {args:?} + expected: {check}{check_args} + actual stdout: + {stdout} + actual stderr: + {stderr}", + }; } }; } diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index e04fae7ad04..2220df2b617 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -1,5 +1,6 @@ //! Integration tests for rustfmt. +use indoc::panicdoc; use std::env; use std::fs::{File, remove_file}; use std::path::Path; @@ -45,16 +46,16 @@ macro_rules! assert_that { ($args:expr, $($check:ident $check_args:tt)&&+) => { let (stdout, stderr) = rustfmt($args); if $(!stdout.$check$check_args && !stderr.$check$check_args)||* { - panic!( - "Output not expected for rustfmt {:?}\n\ - expected: {}\n\ - actual stdout:\n{}\n\ - actual stderr:\n{}", - $args, - stringify!($( $check$check_args )&&*), - stdout, - stderr - ); + let args = $args; + let expected = stringify!($( $check$check_args )&&*); + panicdoc! {" + Output not expected for rustfmt {args:?} + expected: {expected} + actual stdout: + {stdout} + actual stderr: + {stderr}", + }; } }; }