Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more prep work #1918

Merged
merged 4 commits into from
Nov 29, 2024
Merged
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
8 changes: 7 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ home = "0.5.9"
http = "1.1.0"
humantime-serde = "1.1.1"
indenter = "0.3.3"
indent_write = "2.2.0"
indexmap = "2.6.0"
indicatif = "0.17.9"
indoc = "2.0.5"
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/tests/integration/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,11 @@ impl CheckResult {
vec![
(
"stdout",
Regex::new(&format!("--- STDOUT: +{name} ---")).unwrap(),
Regex::new(&format!("---- STDOUT: +{name}")).unwrap(),
),
(
"stderr",
Regex::new(&format!("--- STDERR: +{name} ---")).unwrap(),
Regex::new(&format!("---- STDERR: +{name}")).unwrap(),
),
]
}
Expand Down
2 changes: 1 addition & 1 deletion nextest-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ guppy.workspace = true
# added a config.toml there
home.workspace = true
humantime-serde.workspace = true
indenter.workspace = true
indent_write.workspace = true
indexmap = { workspace = true, features = ["serde"] }
indicatif.workspace = true
is_ci.workspace = true
Expand Down
17 changes: 10 additions & 7 deletions nextest-runner/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
};
use camino::{FromPathBufError, Utf8Path, Utf8PathBuf};
use config::ConfigError;
use indent_write::fmt::IndentWriter;
use itertools::{Either, Itertools};
use nextest_filtering::errors::FiltersetParseErrors;
use nextest_metadata::RustBinaryId;
Expand All @@ -24,6 +25,7 @@ use std::{
env::JoinPathsError,
fmt::{self, Write as _},
process::ExitStatus,
sync::Arc,
};
use target_spec_miette::IntoMietteDiagnostic;
use thiserror::Error;
Expand Down Expand Up @@ -345,7 +347,7 @@ pub(crate) enum SetupScriptError {
pub struct ErrorList<T>(pub Vec<T>);

impl<T: std::error::Error> fmt::Display for ErrorList<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, mut f: &mut fmt::Formatter) -> fmt::Result {
// If a single error occurred, pretend that this is just that.
if self.0.len() == 1 {
return write!(f, "{}", self.0[0]);
Expand All @@ -357,12 +359,13 @@ impl<T: std::error::Error> fmt::Display for ErrorList<T> {
writeln!(f, "- {}", error)?;
// Also display the chain of causes here, since we can't return a single error in the
// causes section below.
let mut indent = indenter::indented(f).with_str(" ");
let mut indent = IndentWriter::new(" ", f);
let mut cause = error.source();
while let Some(cause_error) = cause {
writeln!(indent, "Caused by: {}", cause_error)?;
cause = cause_error.source();
}
f = indent.into_inner();
}
Ok(())
}
Expand All @@ -381,24 +384,24 @@ impl<T: std::error::Error> std::error::Error for ErrorList<T> {
}

/// An error was returned during the process of managing a child process.
#[derive(Debug, Error)]
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum ChildError {
/// An error occurred while reading standard output.
#[error("error reading standard output")]
ReadStdout(#[source] std::io::Error),
ReadStdout(#[source] Arc<std::io::Error>),

/// An error occurred while reading standard error.
#[error("error reading standard error")]
ReadStderr(#[source] std::io::Error),
ReadStderr(#[source] Arc<std::io::Error>),

/// An error occurred while reading a combined stream.
#[error("error reading combined stream")]
ReadCombined(#[source] std::io::Error),
ReadCombined(#[source] Arc<std::io::Error>),

/// An error occurred while waiting for the child process to exit.
#[error("error waiting for child process to exit")]
Wait(#[source] std::io::Error),
Wait(#[source] Arc<std::io::Error>),
}

/// An unknown test group was specified in the config.
Expand Down
74 changes: 68 additions & 6 deletions nextest-runner/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// Copyright (c) The nextest Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{list::Styles, runner::AbortStatus, write_str::WriteStr};
use crate::{
config::ScriptId,
list::{Styles, TestInstanceId},
runner::AbortStatus,
write_str::WriteStr,
};
use camino::{Utf8Path, Utf8PathBuf};
use owo_colors::OwoColorize;
use owo_colors::{OwoColorize, Style};
use std::{fmt, io, path::PathBuf, process::ExitStatus, time::Duration};

pub(crate) mod plural {
Expand Down Expand Up @@ -84,6 +89,63 @@ pub(crate) mod plural {
}
}

pub(crate) struct DisplayTestInstance<'a> {
instance: TestInstanceId<'a>,
styles: &'a Styles,
}

impl<'a> DisplayTestInstance<'a> {
pub(crate) fn new(instance: TestInstanceId<'a>, styles: &'a Styles) -> Self {
Self { instance, styles }
}
}

impl fmt::Display for DisplayTestInstance<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} ",
self.instance.binary_id.style(self.styles.binary_id),
)?;
fmt_write_test_name(self.instance.test_name, self.styles, f)
}
}

pub(crate) struct DisplayScriptInstance {
script_id: ScriptId,
full_command: String,
script_id_style: Style,
}

impl DisplayScriptInstance {
pub(crate) fn new(
script_id: ScriptId,
command: &str,
args: &[String],
script_id_style: Style,
) -> Self {
let full_command =
shell_words::join(std::iter::once(command).chain(args.iter().map(|arg| arg.as_ref())));

Self {
script_id,
full_command,
script_id_style,
}
}
}

impl fmt::Display for DisplayScriptInstance {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}: {}",
self.script_id.style(self.script_id_style),
self.full_command,
)
}
}

/// Write out a test name.
pub(crate) fn write_test_name(
name: &str,
Expand All @@ -106,12 +168,12 @@ pub(crate) fn write_test_name(
Ok(())
}

/// Write out a test name, `std::io::Write` version.
pub(crate) fn io_write_test_name(
/// Write out a test name, `std::fmt::Write` version.
pub(crate) fn fmt_write_test_name(
name: &str,
style: &Styles,
writer: &mut dyn io::Write,
) -> io::Result<()> {
writer: &mut dyn fmt::Write,
) -> fmt::Result {
// Look for the part of the test after the last ::, if any.
let mut splits = name.rsplitn(2, "::");
let trailing = splits.next().expect("test should have at least 1 element");
Expand Down
10 changes: 10 additions & 0 deletions nextest-runner/src/indenter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
//!
//! This module is adapted from [indenter](https://github.com/eyre-rs/indenter) and is used under the
//! terms of the MIT or Apache-2.0 licenses.
//!
//! # Notes
//!
//! We previously used to use `indenter` to indent multi-line `fmt::Display`
//! instances. However, at some point we needed to also indent
//! `std::io::Write`s, not just `fmt::Write`. `indenter` 0.3.3 doesn't support
//! `std::io::Write`, so we switched to `indent_write`.
//!
//! This file still has the `indenter` API. So we have both APIs floating around
//! for a bit... oh well. Still in two minds about which one's better here.

use crate::write_str::WriteStr;
use std::io;
Expand Down
Loading
Loading