Auto merge of #149437 - ilammy:patch-1, r=Mark-Simulacrum

Fix trailing newline in JUnit formatter

`write_message()` expects messages to contain no newlines.

Fixes https://github.com/rust-lang/rust/issues/149436
This commit is contained in:
bors 2025-12-21 10:37:51 +00:00
commit d3f16d2f35
7 changed files with 96 additions and 9 deletions

View file

@ -189,8 +189,10 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
compilation_time: f64,
) -> io::Result<()> {
self.write_message(&format!(
"<report total_time=\"{total_time}\" compilation_time=\"{compilation_time}\"></report>\n",
))
"<report total_time=\"{total_time}\" compilation_time=\"{compilation_time}\"></report>",
))?;
self.out.write_all(b"\n")?;
Ok(())
}
}

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="3" skipped="0" ><testcase classname="doctest.rs" name="add (line 1)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 5)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 9)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="2" skipped="0" ><testcase classname="doctest.rs" name="add (line 1)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 5)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="1" skipped="0" ><testcase classname="doctest.rs" name="add (line 9)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
<report total_time="$TIME" compilation_time="$TIME"></report>

View file

@ -0,0 +1,14 @@
/// ```
/// assert_eq!(doctest::add(2, 2), 4);
/// ```
///
/// ```should_panic
/// assert_eq!(doctest::add(2, 2), 5);
/// ```
///
/// ```compile_fail
/// assert_eq!(doctest::add(2, 2), "banana");
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}

View file

@ -0,0 +1,45 @@
// Check rustdoc's test JUnit (XML) output against snapshots.
//@ ignore-cross-compile (running doctests)
//@ ignore-stage1 (rustdoc depends on a fix in libtest)
//@ needs-unwind (test file contains `should_panic` test)
use std::path::Path;
use run_make_support::{cwd, diff, python_command, rustc, rustdoc};
fn main() {
let rlib = cwd().join("libdoctest.rlib");
rustc().input("doctest.rs").crate_type("rlib").output(&rlib).run();
run_doctests(&rlib, "2021", "doctest-2021.xml");
run_doctests(&rlib, "2024", "doctest-2024.xml");
}
#[track_caller]
fn run_doctests(rlib: &Path, edition: &str, expected_xml: &str) {
let rustdoc_out = rustdoc()
.input("doctest.rs")
.args(&[
"--test",
"--test-args=-Zunstable-options",
"--test-args=--test-threads=1",
"--test-args=--format=junit",
])
.edition(edition)
.env("RUST_BACKTRACE", "0")
.extern_("doctest", rlib.display().to_string())
.run();
let rustdoc_stdout = &rustdoc_out.stdout_utf8();
// FIXME: merged output of compile_fail tests is broken
if edition != "2024" {
python_command().arg("validate_junit.py").stdin_buf(rustdoc_stdout).run();
}
diff()
.expected_file(expected_xml)
.actual_text("output", rustdoc_stdout)
.normalize(r#"\b(time|total_time|compilation_time)="[0-9.]+""#, r#"$1="$$TIME""#)
.run();
}

View file

@ -0,0 +1,22 @@
#!/usr/bin/env python
# Trivial Python script that reads lines from stdin, and checks that each line
# is a well-formed XML document.
#
# This takes advantage of the fact that Python has a built-in XML parser,
# whereas doing the same check in Rust would require us to pull in an XML
# crate just for this relatively-minor test.
#
# If you're trying to remove Python scripts from the test suite, think twice
# before removing this one. You could do so, but it's probably not worth it.
import sys
import xml.etree.ElementTree as ET
# Read the entire output and try to decode it as XML.
junit = sys.stdin.read()
try:
ET.fromstring(junit)
except ET.ParseError:
print("Invalid xml: %r" % junit)
raise

View file

@ -13,10 +13,10 @@
import sys
import xml.etree.ElementTree as ET
# Try to decode line in order to ensure it is a valid XML document
for line in sys.stdin:
try:
ET.fromstring(line)
except ET.ParseError:
print("Invalid xml: %r" % line)
raise
# Read the entire output and try to decode it as XML.
junit = sys.stdin.read()
try:
ET.fromstring(junit)
except ET.ParseError:
print("Invalid xml: %r" % junit)
raise