@@ -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} ;
1718use 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} ;
2825use debug_ignore:: DebugIgnore ;
2926use 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-
16751586fn 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.
0 commit comments