Skip to content

Commit 9f92435

Browse files
committed
[nextest-runner] move status level code to another file
Not much code here at the moment, but a lot of tests that can live here.
1 parent 6f00c07 commit 9f92435

File tree

5 files changed

+435
-422
lines changed

5 files changed

+435
-422
lines changed

nextest-runner/src/reporter/displayer/imp.rs

Lines changed: 3 additions & 347 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@ use super::{
1212
},
1313
progress::{progress_bar_msg, progress_str, write_summary_str, ProgressBarState},
1414
unit_output::TestOutputDisplay,
15-
ChildOutputSpec, UnitOutputReporter,
15+
ChildOutputSpec, FinalStatusLevel, OutputStoreFinal, StatusLevel, StatusLevels,
16+
UnitOutputReporter,
1617
};
1718
use crate::{
1819
config::{CompiledDefaultFilter, ScriptId},
1920
errors::WriteEventError,
2021
helpers::{plural, DisplayScriptInstance, DisplayTestInstance},
2122
list::{TestInstance, TestInstanceId},
22-
reporter::{
23-
events::*,
24-
helpers::Styles,
25-
imp::{FinalStatusLevel, ReporterStderr, StatusLevel},
26-
},
23+
reporter::{events::*, helpers::Styles, imp::ReporterStderr},
2724
};
2825
use debug_ignore::DebugIgnore;
2926
use indent_write::io::IndentWriter;
@@ -1586,92 +1583,6 @@ impl<'a> TestReporterImpl<'a> {
15861583
}
15871584
}
15881585

1589-
pub(crate) struct StatusLevels {
1590-
pub(crate) status_level: StatusLevel,
1591-
pub(crate) final_status_level: FinalStatusLevel,
1592-
}
1593-
1594-
impl StatusLevels {
1595-
fn compute_output_on_test_finished(
1596-
&self,
1597-
display: TestOutputDisplay,
1598-
cancel_status: Option<CancelReason>,
1599-
test_status_level: StatusLevel,
1600-
test_final_status_level: FinalStatusLevel,
1601-
) -> OutputOnTestFinished {
1602-
let write_status_line = self.status_level >= test_status_level;
1603-
1604-
let is_immediate = display.is_immediate();
1605-
// We store entries in the final output map if either the final status level is high enough or
1606-
// if `display` says we show the output at the end.
1607-
let is_final = display.is_final() || self.final_status_level >= test_final_status_level;
1608-
1609-
// This table is tested below. The basic invariant is that we generally follow what
1610-
// is_immediate and is_final suggests, except:
1611-
//
1612-
// - if the run is cancelled due to a non-interrupt signal, we display test output at most
1613-
// once.
1614-
// - if the run is cancelled due to an interrupt, we hide the output because dumping a bunch
1615-
// of output at the end is likely to not be helpful (though in the future we may want to
1616-
// at least dump outputs into files and write their names out, or whenever nextest gains
1617-
// the ability to replay test runs to be able to display it then.)
1618-
//
1619-
// is_immediate is_final cancel_status | show_immediate store_final
1620-
//
1621-
// false false <= Signal | false false
1622-
// false true <= Signal | false true [1]
1623-
// true false <= Signal | true false [1]
1624-
// true true < Signal | true true
1625-
// true true Signal | true false [2]
1626-
// * * Interrupt | false false
1627-
//
1628-
// [1] In non-interrupt cases, we want to display output if specified once.
1629-
//
1630-
// [2] If there's a signal, we shouldn't display output twice at the end since it's
1631-
// redundant -- instead, just show the output as part of the immediate display.
1632-
let show_immediate = is_immediate && cancel_status <= Some(CancelReason::Signal);
1633-
1634-
let store_final = if is_final && cancel_status < Some(CancelReason::Signal)
1635-
|| !is_immediate && is_final && cancel_status == Some(CancelReason::Signal)
1636-
{
1637-
OutputStoreFinal::Yes {
1638-
display_output: display.is_final(),
1639-
}
1640-
} else if is_immediate && is_final && cancel_status == Some(CancelReason::Signal) {
1641-
// In this special case, we already display the output once as the test is being
1642-
// cancelled, so don't display it again at the end since that's redundant.
1643-
OutputStoreFinal::Yes {
1644-
display_output: false,
1645-
}
1646-
} else {
1647-
OutputStoreFinal::No
1648-
};
1649-
1650-
OutputOnTestFinished {
1651-
write_status_line,
1652-
show_immediate,
1653-
store_final,
1654-
}
1655-
}
1656-
}
1657-
1658-
#[derive(Debug, PartialEq, Eq)]
1659-
struct OutputOnTestFinished {
1660-
write_status_line: bool,
1661-
show_immediate: bool,
1662-
store_final: OutputStoreFinal,
1663-
}
1664-
1665-
#[derive(Debug, PartialEq, Eq)]
1666-
enum OutputStoreFinal {
1667-
/// Do not store the output.
1668-
No,
1669-
1670-
/// Store the output. display_output controls whether stdout and stderr should actually be
1671-
/// displayed at the end.
1672-
Yes { display_output: bool },
1673-
}
1674-
16751586
fn status_str(result: ExecutionResult) -> Cow<'static, str> {
16761587
// Max 12 characters here.
16771588
match result {
@@ -1818,7 +1729,6 @@ mod tests {
18181729
use nextest_metadata::RustBinaryId;
18191730
use smol_str::SmolStr;
18201731
use std::sync::Arc;
1821-
use test_strategy::proptest;
18221732

18231733
/// Creates a test reporter with default settings and calls the given function with it.
18241734
///
@@ -1845,260 +1755,6 @@ mod tests {
18451755
f(reporter);
18461756
}
18471757

1848-
// ---
1849-
// The proptests here are probabilistically exhaustive, and it's just easier to express them
1850-
// as property-based tests. We could also potentially use a model checker like Kani here.
1851-
// ---
1852-
1853-
#[proptest(cases = 64)]
1854-
fn on_test_finished_dont_write_status_line(
1855-
display: TestOutputDisplay,
1856-
cancel_status: Option<CancelReason>,
1857-
#[filter(StatusLevel::Pass < #test_status_level)] test_status_level: StatusLevel,
1858-
test_final_status_level: FinalStatusLevel,
1859-
) {
1860-
let status_levels = StatusLevels {
1861-
status_level: StatusLevel::Pass,
1862-
final_status_level: FinalStatusLevel::Fail,
1863-
};
1864-
1865-
let actual = status_levels.compute_output_on_test_finished(
1866-
display,
1867-
cancel_status,
1868-
test_status_level,
1869-
test_final_status_level,
1870-
);
1871-
1872-
assert!(!actual.write_status_line);
1873-
}
1874-
1875-
#[proptest(cases = 64)]
1876-
fn on_test_finished_write_status_line(
1877-
display: TestOutputDisplay,
1878-
cancel_status: Option<CancelReason>,
1879-
#[filter(StatusLevel::Pass >= #test_status_level)] test_status_level: StatusLevel,
1880-
test_final_status_level: FinalStatusLevel,
1881-
) {
1882-
let status_levels = StatusLevels {
1883-
status_level: StatusLevel::Pass,
1884-
final_status_level: FinalStatusLevel::Fail,
1885-
};
1886-
1887-
let actual = status_levels.compute_output_on_test_finished(
1888-
display,
1889-
cancel_status,
1890-
test_status_level,
1891-
test_final_status_level,
1892-
);
1893-
assert!(actual.write_status_line);
1894-
}
1895-
1896-
#[proptest(cases = 64)]
1897-
fn on_test_finished_with_interrupt(
1898-
// We always hide output on interrupt.
1899-
display: TestOutputDisplay,
1900-
// cancel_status is fixed to Interrupt.
1901-
1902-
// In this case, the status levels are not relevant for is_immediate and is_final.
1903-
test_status_level: StatusLevel,
1904-
test_final_status_level: FinalStatusLevel,
1905-
) {
1906-
let status_levels = StatusLevels {
1907-
status_level: StatusLevel::Pass,
1908-
final_status_level: FinalStatusLevel::Fail,
1909-
};
1910-
1911-
let actual = status_levels.compute_output_on_test_finished(
1912-
display,
1913-
Some(CancelReason::Interrupt),
1914-
test_status_level,
1915-
test_final_status_level,
1916-
);
1917-
assert!(!actual.show_immediate);
1918-
assert_eq!(actual.store_final, OutputStoreFinal::No);
1919-
}
1920-
1921-
#[proptest(cases = 64)]
1922-
fn on_test_finished_dont_show_immediate(
1923-
#[filter(!#display.is_immediate())] display: TestOutputDisplay,
1924-
cancel_status: Option<CancelReason>,
1925-
// The status levels are not relevant for show_immediate.
1926-
test_status_level: StatusLevel,
1927-
test_final_status_level: FinalStatusLevel,
1928-
) {
1929-
let status_levels = StatusLevels {
1930-
status_level: StatusLevel::Pass,
1931-
final_status_level: FinalStatusLevel::Fail,
1932-
};
1933-
1934-
let actual = status_levels.compute_output_on_test_finished(
1935-
display,
1936-
cancel_status,
1937-
test_status_level,
1938-
test_final_status_level,
1939-
);
1940-
assert!(!actual.show_immediate);
1941-
}
1942-
1943-
#[proptest(cases = 64)]
1944-
fn on_test_finished_show_immediate(
1945-
#[filter(#display.is_immediate())] display: TestOutputDisplay,
1946-
#[filter(#cancel_status <= Some(CancelReason::Signal))] cancel_status: Option<CancelReason>,
1947-
// The status levels are not relevant for show_immediate.
1948-
test_status_level: StatusLevel,
1949-
test_final_status_level: FinalStatusLevel,
1950-
) {
1951-
let status_levels = StatusLevels {
1952-
status_level: StatusLevel::Pass,
1953-
final_status_level: FinalStatusLevel::Fail,
1954-
};
1955-
1956-
let actual = status_levels.compute_output_on_test_finished(
1957-
display,
1958-
cancel_status,
1959-
test_status_level,
1960-
test_final_status_level,
1961-
);
1962-
assert!(actual.show_immediate);
1963-
}
1964-
1965-
// Where we don't store final output: if display.is_final() is false, and if the test final
1966-
// status level is too high.
1967-
#[proptest(cases = 64)]
1968-
fn on_test_finished_dont_store_final(
1969-
#[filter(!#display.is_final())] display: TestOutputDisplay,
1970-
cancel_status: Option<CancelReason>,
1971-
// The status level is not relevant for store_final.
1972-
test_status_level: StatusLevel,
1973-
// But the final status level is.
1974-
#[filter(FinalStatusLevel::Fail < #test_final_status_level)]
1975-
test_final_status_level: FinalStatusLevel,
1976-
) {
1977-
let status_levels = StatusLevels {
1978-
status_level: StatusLevel::Pass,
1979-
final_status_level: FinalStatusLevel::Fail,
1980-
};
1981-
1982-
let actual = status_levels.compute_output_on_test_finished(
1983-
display,
1984-
cancel_status,
1985-
test_status_level,
1986-
test_final_status_level,
1987-
);
1988-
assert_eq!(actual.store_final, OutputStoreFinal::No);
1989-
}
1990-
1991-
// Case 1 where we store final output: if display is exactly TestOutputDisplay::Final, and if
1992-
// the cancel status is not Interrupt.
1993-
#[proptest(cases = 64)]
1994-
fn on_test_finished_store_final_1(
1995-
#[filter(#cancel_status <= Some(CancelReason::Signal))] cancel_status: Option<CancelReason>,
1996-
// In this case, it isn't relevant what test_status_level and test_final_status_level are.
1997-
test_status_level: StatusLevel,
1998-
test_final_status_level: FinalStatusLevel,
1999-
) {
2000-
let status_levels = StatusLevels {
2001-
status_level: StatusLevel::Pass,
2002-
final_status_level: FinalStatusLevel::Fail,
2003-
};
2004-
2005-
let actual = status_levels.compute_output_on_test_finished(
2006-
TestOutputDisplay::Final,
2007-
cancel_status,
2008-
test_status_level,
2009-
test_final_status_level,
2010-
);
2011-
assert_eq!(
2012-
actual.store_final,
2013-
OutputStoreFinal::Yes {
2014-
display_output: true
2015-
}
2016-
);
2017-
}
2018-
2019-
// Case 2 where we store final output: if display is TestOutputDisplay::ImmediateFinal and the
2020-
// cancel status is not Signal or Interrupt
2021-
#[proptest(cases = 64)]
2022-
fn on_test_finished_store_final_2(
2023-
#[filter(#cancel_status < Some(CancelReason::Signal))] cancel_status: Option<CancelReason>,
2024-
test_status_level: StatusLevel,
2025-
test_final_status_level: FinalStatusLevel,
2026-
) {
2027-
let status_levels = StatusLevels {
2028-
status_level: StatusLevel::Pass,
2029-
final_status_level: FinalStatusLevel::Fail,
2030-
};
2031-
2032-
let actual = status_levels.compute_output_on_test_finished(
2033-
TestOutputDisplay::ImmediateFinal,
2034-
cancel_status,
2035-
test_status_level,
2036-
test_final_status_level,
2037-
);
2038-
assert_eq!(
2039-
actual.store_final,
2040-
OutputStoreFinal::Yes {
2041-
display_output: true
2042-
}
2043-
);
2044-
}
2045-
2046-
// Case 3 where we store final output: if display is TestOutputDisplay::ImmediateFinal and the
2047-
// cancel status is exactly Signal. In this special case, we don't display the output.
2048-
#[proptest(cases = 64)]
2049-
fn on_test_finished_store_final_3(
2050-
test_status_level: StatusLevel,
2051-
test_final_status_level: FinalStatusLevel,
2052-
) {
2053-
let status_levels = StatusLevels {
2054-
status_level: StatusLevel::Pass,
2055-
final_status_level: FinalStatusLevel::Fail,
2056-
};
2057-
2058-
let actual = status_levels.compute_output_on_test_finished(
2059-
TestOutputDisplay::ImmediateFinal,
2060-
Some(CancelReason::Signal),
2061-
test_status_level,
2062-
test_final_status_level,
2063-
);
2064-
assert_eq!(
2065-
actual.store_final,
2066-
OutputStoreFinal::Yes {
2067-
display_output: false,
2068-
}
2069-
);
2070-
}
2071-
2072-
// Case 4: if display.is_final() is *false* but the test_final_status_level is low enough.
2073-
#[proptest(cases = 64)]
2074-
fn on_test_finished_store_final_4(
2075-
#[filter(!#display.is_final())] display: TestOutputDisplay,
2076-
#[filter(#cancel_status <= Some(CancelReason::Signal))] cancel_status: Option<CancelReason>,
2077-
// The status level is not relevant for store_final.
2078-
test_status_level: StatusLevel,
2079-
// But the final status level is.
2080-
#[filter(FinalStatusLevel::Fail >= #test_final_status_level)]
2081-
test_final_status_level: FinalStatusLevel,
2082-
) {
2083-
let status_levels = StatusLevels {
2084-
status_level: StatusLevel::Pass,
2085-
final_status_level: FinalStatusLevel::Fail,
2086-
};
2087-
2088-
let actual = status_levels.compute_output_on_test_finished(
2089-
display,
2090-
cancel_status,
2091-
test_status_level,
2092-
test_final_status_level,
2093-
);
2094-
assert_eq!(
2095-
actual.store_final,
2096-
OutputStoreFinal::Yes {
2097-
display_output: false,
2098-
}
2099-
);
2100-
}
2101-
21021758
// ---
21031759

21041760
/// Send an information response to the reporter and return the output.

nextest-runner/src/reporter/displayer/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
mod formatters;
77
mod imp;
88
mod progress;
9+
mod status_level;
910
mod unit_output;
1011

1112
pub(crate) use imp::*;
13+
pub use status_level::*;
1214
pub use unit_output::*;

0 commit comments

Comments
 (0)