diff --git a/nextest-runner/src/list/test_list.rs b/nextest-runner/src/list/test_list.rs index f250b08a896..31678a8becb 100644 --- a/nextest-runner/src/list/test_list.rs +++ b/nextest-runner/src/list/test_list.rs @@ -1133,32 +1133,14 @@ impl<'a> TestInstance<'a> { /// Creates the command for this test instance. pub(crate) fn make_command( &self, - ctx: &TestExecuteContext<'_>, + ctx: &'a TestExecuteContext<'a>, test_list: &TestList<'_>, wrapper_script: Option<&'a WrapperScriptConfig>, - extra_args: &[String], + extra_args: &'a [String], interceptor: &Interceptor, ) -> TestCommand { // TODO: non-rust tests - - let platform_runner = ctx - .target_runner - .for_build_platform(self.suite_info.build_platform); - - let mut cli = TestCommandCli::default(); - cli.apply_wrappers( - wrapper_script, - platform_runner, - test_list.workspace_root(), - &test_list.rust_build_meta().target_directory, - ); - cli.push(self.suite_info.binary_path.as_str()); - - cli.extend(["--exact", self.name, "--nocapture"]); - if self.test_info.ignored { - cli.push("--ignored"); - } - cli.extend(extra_args.iter().map(String::as_str)); + let cli = self.compute_cli(ctx, test_list, wrapper_script, extra_args); let lctx = LocalExecuteContext { phase: TestCommandPhase::Run, @@ -1182,6 +1164,46 @@ impl<'a> TestInstance<'a> { interceptor, ) } + + pub(crate) fn command_line( + &self, + ctx: &'a TestExecuteContext<'a>, + test_list: &TestList<'_>, + wrapper_script: Option<&'a WrapperScriptConfig>, + extra_args: &'a [String], + ) -> Vec { + self.compute_cli(ctx, test_list, wrapper_script, extra_args) + .to_owned_cli() + } + + fn compute_cli( + &self, + ctx: &'a TestExecuteContext<'a>, + test_list: &TestList<'_>, + wrapper_script: Option<&'a WrapperScriptConfig>, + extra_args: &'a [String], + ) -> TestCommandCli<'a> { + let platform_runner = ctx + .target_runner + .for_build_platform(self.suite_info.build_platform); + + let mut cli = TestCommandCli::default(); + cli.apply_wrappers( + wrapper_script, + platform_runner, + test_list.workspace_root(), + &test_list.rust_build_meta().target_directory, + ); + cli.push(self.suite_info.binary_path.as_str()); + + cli.extend(["--exact", self.name, "--nocapture"]); + if self.test_info.ignored { + cli.push("--ignored"); + } + cli.extend(extra_args.iter().map(String::as_str)); + + cli + } } #[derive(Clone, Debug, Default)] diff --git a/nextest-runner/src/reporter/displayer/imp.rs b/nextest-runner/src/reporter/displayer/imp.rs index fc84ed316e1..826182dd68c 100644 --- a/nextest-runner/src/reporter/displayer/imp.rs +++ b/nextest-runner/src/reporter/displayer/imp.rs @@ -54,6 +54,7 @@ pub(crate) struct DisplayReporterBuilder { pub(crate) failure_output: Option, pub(crate) should_colorize: bool, pub(crate) no_capture: bool, + pub(crate) verbose: bool, pub(crate) show_progress: ShowProgress, pub(crate) no_output_indent: bool, pub(crate) max_progress_running: MaxProgressRunning, @@ -141,6 +142,7 @@ impl DisplayReporterBuilder { final_status_level: self.status_levels.final_status_level, }, no_capture: self.no_capture, + verbose: self.verbose, no_output_indent: self.no_output_indent, counter_width, styles, @@ -377,6 +379,7 @@ struct DisplayReporterImpl<'a> { default_filter: CompiledDefaultFilter, status_levels: StatusLevels, no_capture: bool, + verbose: bool, no_output_indent: bool, // None if no counter is displayed. If a counter is displayed, this is the // width of the total number of tests to run. @@ -601,6 +604,7 @@ impl<'a> DisplayReporterImpl<'a> { stress_index, test_instance, current_stats, + command_line, .. } => { // In no-capture mode, print out a test start event. @@ -623,6 +627,15 @@ impl<'a> DisplayReporterImpl<'a> { ), )?; } + + if self.verbose { + writeln!( + writer, + "{:>12} {}", + "COMMAND".style(self.styles.count), + shell_words::join(command_line), + )?; + } } TestEventKind::TestSlow { stress_index, @@ -2390,10 +2403,12 @@ mod tests { failure_output: Some(TestOutputDisplay::Immediate), should_colorize: false, no_capture: true, + verbose: false, show_progress: ShowProgress::Counter, no_output_indent: false, max_progress_running: MaxProgressRunning::default(), }; + let output = ReporterStderr::Buffer(out); let reporter = builder.build(&configs, output); f(reporter); diff --git a/nextest-runner/src/reporter/events.rs b/nextest-runner/src/reporter/events.rs index 50e2b285b4c..d1dcabed4a7 100644 --- a/nextest-runner/src/reporter/events.rs +++ b/nextest-runner/src/reporter/events.rs @@ -168,6 +168,9 @@ pub enum TestEventKind<'a> { /// The number of tests currently running, including this one. running: usize, + + /// The command line that will be used to run this test. + command_line: Vec, }, /// A test was slower than a configured soft timeout. diff --git a/nextest-runner/src/reporter/imp.rs b/nextest-runner/src/reporter/imp.rs index 8bf7e6cafbf..67c1c3a9790 100644 --- a/nextest-runner/src/reporter/imp.rs +++ b/nextest-runner/src/reporter/imp.rs @@ -148,6 +148,7 @@ impl ReporterBuilder { failure_output: self.failure_output, should_colorize: self.should_colorize, no_capture: self.no_capture, + verbose: self.verbose, show_progress: self.show_progress, no_output_indent: self.no_output_indent, max_progress_running: self.max_progress_running, diff --git a/nextest-runner/src/runner/dispatcher.rs b/nextest-runner/src/runner/dispatcher.rs index e6fd0b86ea9..d7827027a1f 100644 --- a/nextest-runner/src/runner/dispatcher.rs +++ b/nextest-runner/src/runner/dispatcher.rs @@ -656,6 +656,7 @@ where InternalEvent::Executor(ExecutorEvent::Started { stress_index, test_instance, + command_line, req_rx_tx, }) => { if self.run_stats.cancel_reason.is_some() { @@ -678,6 +679,7 @@ where test_instance, current_stats: self.run_stats, running: self.running_tests.len(), + command_line, }) } InternalEvent::Executor(ExecutorEvent::Slow { diff --git a/nextest-runner/src/runner/executor.rs b/nextest-runner/src/runner/executor.rs index 66e3bcf6aab..48bb2de8c73 100644 --- a/nextest-runner/src/runner/executor.rs +++ b/nextest-runner/src/runner/executor.rs @@ -94,6 +94,14 @@ impl<'a> ExecutorContext<'a> { } } + fn test_execute_context(&self) -> TestExecuteContext<'_> { + TestExecuteContext { + profile_name: self.profile.name(), + double_spawn: &self.double_spawn, + target_runner: &self.target_runner, + } + } + /// Run scripts, returning data about each successfully executed script. pub(super) async fn run_setup_scripts( &self, @@ -210,11 +218,20 @@ impl<'a> ExecutorContext<'a> { let (req_rx_tx, req_rx_rx) = oneshot::channel(); + let ctx = self.test_execute_context(); + let command_line = test.instance.command_line( + &ctx, + self.test_list, + settings.run_wrapper(), + settings.run_extra_args(), + ); + // Wait for the Started event to be processed by the // execution future. _ = resp_tx.send(ExecutorEvent::Started { stress_index, test_instance: test.instance, + command_line, req_rx_tx, }); let mut req_rx = match req_rx_rx.await { @@ -664,11 +681,7 @@ impl<'a> ExecutorContext<'a> { resp_tx: &UnboundedSender>, req_rx: &mut UnboundedReceiver>, ) -> Result, ChildStartError> { - let ctx = TestExecuteContext { - profile_name: self.profile.name(), - double_spawn: &self.double_spawn, - target_runner: &self.target_runner, - }; + let ctx = self.test_execute_context(); let mut cmd = test.test_instance.make_command( &ctx, self.test_list, diff --git a/nextest-runner/src/runner/internal_events.rs b/nextest-runner/src/runner/internal_events.rs index 18c18739894..3d2984e64f7 100644 --- a/nextest-runner/src/runner/internal_events.rs +++ b/nextest-runner/src/runner/internal_events.rs @@ -69,6 +69,7 @@ pub(super) enum ExecutorEvent<'a> { Started { stress_index: Option, test_instance: TestInstance<'a>, + command_line: Vec, // The channel over which to return the unit request. // // The callback context is solely responsible for coordinating the