Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by Cargo
# will have compiled files and executables
/target/
**/target/

# These are backup files generated by rustfmt
**/*.rs.bk
3 changes: 2 additions & 1 deletion rebuild_expected_outputs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ do
if [[ "$f" == 'src/test_inputs/compile_fail.json' ]]; then continue; fi
if [[ "$f" == 'src/test_inputs/float_time.json' ]]; then continue; fi
if [[ "$f" == 'src/test_inputs/one_suite_no_tests.json' ]]; then continue; fi
cargo run < "$f" > "${f%.json}.out" || ( echo $f | grep "fail" )
if [[ "$f" == 'src/test_inputs/unknown_type.json' ]]; then continue; fi
cargo run < "$f" > "${f%.json}.out" || true
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from || ( echo $f | grep "fail" ) to || true changes the error handling behavior. The original version allowed only files with "fail" in their name to fail without causing the script to exit, while the new version suppresses all errors indiscriminately. This could mask legitimate failures when processing test inputs. Consider either reverting to the original pattern or documenting why all failures should now be ignored.

Suggested change
cargo run < "$f" > "${f%.json}.out" || true
cargo run < "$f" > "${f%.json}.out" || ( echo "$f" | grep "fail" )

Copilot uses AI. Check for mistakes.
done;

mv src/test_inputs/*.out src/expected_outputs/
Expand Down
8 changes: 8 additions & 0 deletions regenerate_test_inputs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
set -e
set -x

for f in test_input_generators/*;
do
echo
RUSTC_BOOTSTRAP=1 cargo test --manifest-path $f/Cargo.toml -- -Z unstable-options --format json --report-time > src/test_inputs/"${f##*/}".json || true
done;
40 changes: 40 additions & 0 deletions src/expected_outputs/doctests_edition2024.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite id="0" name="cargo test #0" package="testsuite/cargo test #0" tests="0" errors="0" failures="0" hostname="localhost" timestamp="2025-12-28T10:22:18.211031876Z" time="0" />
<testsuite id="1" name="cargo test #1" package="testsuite/cargo test #1" tests="0" errors="0" failures="0" hostname="localhost" timestamp="2025-12-28T10:22:18.211031876Z" time="0" />
<testsuite id="2" name="cargo test #2" package="testsuite/cargo test #2" tests="4" errors="0" failures="1" hostname="localhost" timestamp="2025-12-28T10:22:18.211031876Z" time="0.119109648">
<testcase name="src/lib.rs - foo (line 15)" time="0">
<skipped />
</testcase>
<testcase name="src/lib.rs - foo (line 2)" time="0.001401198" classname="" />
<testcase name="src/lib.rs - foo (line 7)" time="0.058641184" classname="">
<failure type="cargo test" message="failed ::src/lib.rs - foo (line 7)"><![CDATA[Test executable failed (exit status: 101).

stderr:

thread 'main' (3272617) panicked at /tmp/rustdoctestzqkU8w/doctest_bundle_2024.rs:24:1:
assertion `left == right` failed
left: 1
right: 2
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/std/src/panicking.rs:698:5
1: core::panicking::panic_fmt
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:444:17
3: core::panicking::assert_failed
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:399:5
4: doctest_bundle_2024::__doctest_3::main
5: doctest_bundle_2024::__doctest_3::__main_fn
6: doctest_runner_2024::__doctest_3::TEST::{{closure}}
7: core::ops::function::FnOnce::call_once
8: doctest_runner_2024::main
9: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

]]></failure>
</testcase>
<testcase name="src/lib.rs - foo (line 11)" time="0.059067266" classname="" />
</testsuite>
</testsuites>
24 changes: 23 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ enum Event {
duration: Option<f64>,
exec_time: Option<ExecTime>,
},
#[serde(rename = "report")]
DoctestsReport {
total_time: f64,
compilation_time: f64,
}
}

impl Event {
Expand Down Expand Up @@ -120,7 +125,8 @@ impl Event {
};

Duration::nanoseconds(duration_ns)
}
},
Event::DoctestsReport { .. } => panic!(),
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The panic!() call here could be problematic if get_duration() is ever called on a DoctestsReport event. While this may never happen in the current code flow (since report events are ignored in parsing), it would be more robust to either return a default Duration (like Duration::nanoseconds(0)) or add a comment explaining why this panic is safe. Consider using unreachable!("DoctestsReport events do not have duration") to make the intent clearer.

Suggested change
Event::DoctestsReport { .. } => panic!(),
Event::DoctestsReport { .. } => unreachable!("DoctestsReport events do not have duration"),

Copilot uses AI. Check for mistakes.
}
}
}
Expand Down Expand Up @@ -273,6 +279,12 @@ fn parse<T: BufRead>(
}

current_suite_maybe = Some(current_suite);
},
Event::DoctestsReport { .. } => {
// This is an informative event that's emitted after a doctests binary is done executing.
// Aside from a bespoke way of compiling into a single binary, doctests are not special
// and produce all the same events as the regular tests. We thus should have all the required
// information already and can ignore this event.
}
}
}
Expand Down Expand Up @@ -545,4 +557,14 @@ mod tests {

assert!(determine_exit_code(&report).is_ok());
}

#[test]
fn doctests_edition2024() {
let report = parse_bytes(
include_bytes!("test_inputs/doctests_edition2024.json"),
SYSTEM_OUT_MAX_LEN,
)
.expect("Could not parse test input");
assert_output(&report, include_bytes!("expected_outputs/doctests_edition2024.out"));
}
}
15 changes: 15 additions & 0 deletions src/test_inputs/doctests_edition2024.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{ "type": "suite", "event": "started", "test_count": 0 }
{ "type": "suite", "event": "ok", "passed": 0, "failed": 0, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.000110368 }
{ "type": "suite", "event": "started", "test_count": 0 }
{ "type": "suite", "event": "ok", "passed": 0, "failed": 0, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.000061506 }
{ "type": "suite", "event": "started", "test_count": 4 }
{ "type": "test", "event": "started", "name": "src/lib.rs - foo (line 11)" }
{ "type": "test", "event": "started", "name": "src/lib.rs - foo (line 15)" }
{ "type": "test", "event": "started", "name": "src/lib.rs - foo (line 2)" }
{ "type": "test", "event": "started", "name": "src/lib.rs - foo (line 7)" }
{ "type": "test", "name": "src/lib.rs - foo (line 15)", "event": "ignored" }
{ "type": "test", "name": "src/lib.rs - foo (line 2)", "event": "ok", "exec_time": 0.001401198 }
{ "type": "test", "name": "src/lib.rs - foo (line 7)", "event": "failed", "exec_time": 0.058641184, "stdout": "Test executable failed (exit status: 101).\n\nstderr:\n\nthread 'main' (3272617) panicked at /tmp/rustdoctestzqkU8w/doctest_bundle_2024.rs:24:1:\nassertion `left == right` failed\n left: 1\n right: 2\nstack backtrace:\n 0: __rustc::rust_begin_unwind\n at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/std/src/panicking.rs:698:5\n 1: core::panicking::panic_fmt\n at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:80:14\n 2: core::panicking::assert_failed_inner\n at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:444:17\n 3: core::panicking::assert_failed\n at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:399:5\n 4: doctest_bundle_2024::__doctest_3::main\n 5: doctest_bundle_2024::__doctest_3::__main_fn\n 6: doctest_runner_2024::__doctest_3::TEST::{{closure}}\n 7: core::ops::function::FnOnce::call_once\n 8: doctest_runner_2024::main\n 9: core::ops::function::FnOnce::call_once\nnote: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n\n" }
{ "type": "test", "name": "src/lib.rs - foo (line 11)", "event": "ok", "exec_time": 0.059067266 }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": 0.059319241 }
{ "type": "report", "total_time": 0.225519393, "compilation_time": 0.162774902 }
7 changes: 7 additions & 0 deletions test_input_generators/doctests_edition2024/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions test_input_generators/doctests_edition2024/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "doctests_edition2024"
version = "0.1.0"

# Since Rust edition 2024, rustdoc combines doctests into a single binary:
# https://doc.rust-lang.org/edition-guide/rust-2024/rustdoc-doctests.html
#
# When it does so, it also produces `{ "type": "report" ... }` events after
# the doctests are run. We are using edition 2024 here to generate test input
# that contains such events.
edition = "2024"

[dependencies]
18 changes: 18 additions & 0 deletions test_input_generators/doctests_edition2024/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// Pass:
/// ```
/// assert_eq!(1, 1)
/// ```
///
/// Fail:
/// ```
/// assert_eq!(1, 2)
/// ```
///
/// ```should_panic
/// assert_eq!(2, 1)
/// ```
///
/// ```ignore
/// assert_eq!(2, 1)
/// ```
pub fn foo() {}
1 change: 1 addition & 0 deletions test_input_generators/doctests_edition2024/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
Loading