@@ -333,9 +333,12 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
333333 . map ( make_owned_test)
334334 . next ( )
335335 . expect ( "couldn't find a test with the provided name" ) ;
336- let opts = parse_opts ( & [ ] ) . unwrap ( ) . unwrap ( ) ;
337- run_test ( & opts, false , test, RunStrategy :: SpawnedSecondary , Concurrent :: No ) ;
338- unreachable ! ( ) ;
336+ let TestDescAndFn { desc, testfn } = test;
337+ let testfn = match testfn {
338+ StaticTestFn ( f) => f,
339+ _ => panic ! ( "only static tests are supported" ) ,
340+ } ;
341+ run_test_in_spawned_subprocess ( desc, Box :: new ( testfn) ) ;
339342 }
340343
341344 let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
@@ -1088,31 +1091,16 @@ impl Write for Sink {
10881091 }
10891092}
10901093
1091- #[ derive( Clone ) ]
1094+ #[ derive( Clone , Copy ) ]
10921095pub enum RunStrategy {
10931096 /// Runs the test in the current process, and sends the result back over the
10941097 /// supplied channel.
1095- InProcess ( Sender < MonitorMsg > ) ,
1098+ InProcess ,
10961099
10971100 /// Spawns a subprocess to run the test, and sends the result back over the
10981101 /// supplied channel. Requires argv[0] to exist and point to the binary
10991102 /// that's currently running.
1100- SpawnPrimary ( Sender < MonitorMsg > ) ,
1101-
1102- /// Runs the test in the current process, then exits the process.
1103- /// Prints to stdout the custom result format that the parent process
1104- /// expects in SpawnPrimary mode.
1105- SpawnedSecondary ,
1106- }
1107-
1108- impl RunStrategy {
1109- fn monitor_ch ( self ) -> Option < Sender < MonitorMsg > > {
1110- match self {
1111- RunStrategy :: InProcess ( ch) => Some ( ch) ,
1112- RunStrategy :: SpawnPrimary ( ch) => Some ( ch) ,
1113- RunStrategy :: SpawnedSecondary => None ,
1114- }
1115- }
1103+ SpawnPrimary ,
11161104}
11171105
11181106pub fn run_tests < F > ( opts : & TestOpts , tests : Vec < TestDescAndFn > , mut callback : F ) -> io:: Result < ( ) >
@@ -1163,9 +1151,9 @@ where
11631151
11641152 let ( tx, rx) = channel :: < MonitorMsg > ( ) ;
11651153 let run_strategy = if opts. options . panic_abort {
1166- RunStrategy :: SpawnPrimary ( tx )
1154+ RunStrategy :: SpawnPrimary
11671155 } else {
1168- RunStrategy :: InProcess ( tx )
1156+ RunStrategy :: InProcess
11691157 } ;
11701158
11711159 let mut running_tests: TestMap = HashMap :: default ( ) ;
@@ -1203,7 +1191,7 @@ where
12031191 while !remaining. is_empty ( ) {
12041192 let test = remaining. pop ( ) . unwrap ( ) ;
12051193 callback ( TeWait ( test. desc . clone ( ) ) ) ?;
1206- run_test ( opts, !opts. run_tests , test, run_strategy. clone ( ) , Concurrent :: No ) ;
1194+ run_test ( opts, !opts. run_tests , test, run_strategy, tx . clone ( ) , Concurrent :: No ) ;
12071195 let ( test, result, stdout) = rx. recv ( ) . unwrap ( ) ;
12081196 callback ( TeResult ( test, result, stdout) ) ?;
12091197 }
@@ -1214,7 +1202,7 @@ where
12141202 let timeout = Instant :: now ( ) + Duration :: from_secs ( TEST_WARN_TIMEOUT_S ) ;
12151203 running_tests. insert ( test. desc . clone ( ) , timeout) ;
12161204 callback ( TeWait ( test. desc . clone ( ) ) ) ?; //here no pad
1217- run_test ( opts, !opts. run_tests , test, run_strategy. clone ( ) , Concurrent :: Yes ) ;
1205+ run_test ( opts, !opts. run_tests , test, run_strategy, tx . clone ( ) , Concurrent :: Yes ) ;
12181206 pending += 1 ;
12191207 }
12201208
@@ -1246,7 +1234,7 @@ where
12461234 // All benchmarks run at the end, in serial.
12471235 for b in filtered_benchs {
12481236 callback ( TeWait ( b. desc . clone ( ) ) ) ?;
1249- run_test ( opts, false , b, run_strategy. clone ( ) , Concurrent :: No ) ;
1237+ run_test ( opts, false , b, run_strategy, tx . clone ( ) , Concurrent :: No ) ;
12501238 let ( test, result, stdout) = rx. recv ( ) . unwrap ( ) ;
12511239 callback ( TeResult ( test, result, stdout) ) ?;
12521240 }
@@ -1474,129 +1462,34 @@ pub fn run_test(
14741462 force_ignore : bool ,
14751463 test : TestDescAndFn ,
14761464 strategy : RunStrategy ,
1465+ monitor_ch : Sender < MonitorMsg > ,
14771466 concurrency : Concurrent ,
14781467) {
14791468 let TestDescAndFn { desc, testfn } = test;
14801469
1481- if force_ignore || desc. ignore {
1482- match strategy {
1483- RunStrategy :: InProcess ( tx) | RunStrategy :: SpawnPrimary ( tx) => {
1484- tx. send ( ( desc, TrIgnored , Vec :: new ( ) ) ) . unwrap ( ) ;
1485- }
1486- RunStrategy :: SpawnedSecondary => panic ! ( ) ,
1487- }
1470+ let ignore_because_no_process_support = cfg ! ( target_arch = "wasm32" )
1471+ && !cfg ! ( target_os = "emscripten" )
1472+ && desc. should_panic != ShouldPanic :: No ;
1473+
1474+ if force_ignore || desc. ignore || ignore_because_no_process_support {
1475+ monitor_ch. send ( ( desc, TrIgnored , Vec :: new ( ) ) ) . unwrap ( ) ;
14881476 return ;
14891477 }
14901478
14911479 fn run_test_inner (
14921480 desc : TestDesc ,
14931481 nocapture : bool ,
14941482 strategy : RunStrategy ,
1483+ monitor_ch : Sender < MonitorMsg > ,
14951484 testfn : Box < dyn FnOnce ( ) + Send > ,
14961485 concurrency : Concurrent ,
14971486 ) {
1498- // Buffer for capturing standard I/O
1499- let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1500-
15011487 let name = desc. name . clone ( ) ;
1488+
15021489 let runtest = move || {
1503- // TODO split into functions
15041490 match strategy {
1505- RunStrategy :: InProcess ( monitor_ch) => {
1506- let oldio = if !nocapture {
1507- Some ( (
1508- io:: set_print ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
1509- io:: set_panic ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
1510- ) )
1511- } else {
1512- None
1513- } ;
1514-
1515- let result = catch_unwind ( AssertUnwindSafe ( testfn) ) ;
1516-
1517- if let Some ( ( printio, panicio) ) = oldio {
1518- io:: set_print ( printio) ;
1519- io:: set_panic ( panicio) ;
1520- }
1521-
1522- let test_result = match result {
1523- Ok ( ( ) ) => calc_result ( & desc, Ok ( ( ) ) ) ,
1524- Err ( e) => calc_result ( & desc, Err ( e. as_ref ( ) ) ) ,
1525- } ;
1526- let stdout = data. lock ( ) . unwrap ( ) . to_vec ( ) ;
1527- monitor_ch. send ( ( desc. clone ( ) , test_result, stdout) ) . unwrap ( ) ;
1528- }
1529-
1530- RunStrategy :: SpawnPrimary ( monitor_ch) => {
1531- let ( result, test_output) = ( || {
1532- let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
1533- let current_exe = & args[ 0 ] ;
1534- let output = match Command :: new ( current_exe)
1535- . env ( SECONDARY_TEST_INVOKER_VAR , desc. name . as_slice ( ) )
1536- . output ( ) {
1537- Ok ( out) => out,
1538- Err ( e) => {
1539- let err = format ! ( "Failed to spawn {} as child for test: {:?}" ,
1540- args[ 0 ] , e) ;
1541- return ( TrFailed , err. into_bytes ( ) ) ;
1542- }
1543- } ;
1544-
1545- let std:: process:: Output { stdout, stderr, status } = output;
1546- let mut test_output = stdout;
1547- test_output. extend_from_slice ( & stderr) ;
1548-
1549- let result = match ( move || {
1550- let exit_code = status. code ( ) . ok_or ( "child process was terminated" ) ?;
1551- TestResult :: try_from ( exit_code) . map_err ( |_| {
1552- format ! ( "child process returned unexpected exit code {}" , exit_code)
1553- } )
1554- } ) ( ) {
1555- Ok ( r) => r,
1556- Err ( e) => {
1557- write ! ( & mut test_output, "Unexpected error: {}" , e) . unwrap ( ) ;
1558- TrFailed
1559- }
1560- } ;
1561-
1562- ( result, test_output)
1563- } ) ( ) ;
1564-
1565- monitor_ch. send ( ( desc. clone ( ) , result, test_output) ) . unwrap ( ) ;
1566- }
1567-
1568- RunStrategy :: SpawnedSecondary => {
1569- let record_lock = Mutex :: new ( ( ) ) ;
1570- let builtin_panic_hook = panic:: take_hook ( ) ;
1571- let record_result = Arc :: new ( move |panic_info : Option < & ' _ PanicInfo < ' _ > > | {
1572- let _lock = record_lock. lock ( ) . unwrap ( ) ;
1573-
1574- let test_result = match panic_info {
1575- Some ( info) => calc_result ( & desc, Err ( info. payload ( ) ) ) ,
1576- None => calc_result ( & desc, Ok ( ( ) ) ) ,
1577- } ;
1578-
1579- // We don't support serializing TrFailedMsg, so just
1580- // print the message out to stderr.
1581- let test_result = match test_result {
1582- TrFailedMsg ( msg) => {
1583- eprintln ! ( "{}" , msg) ;
1584- TrFailed
1585- }
1586- _ => test_result,
1587- } ;
1588-
1589- if let Some ( info) = panic_info {
1590- builtin_panic_hook ( info) ;
1591- }
1592- process:: exit ( test_result. try_into ( ) . unwrap ( ) ) ;
1593- } ) ;
1594- let record_result2 = record_result. clone ( ) ;
1595- panic:: set_hook ( Box :: new ( move |info| record_result2 ( Some ( & info) ) ) ) ;
1596- testfn ( ) ;
1597- record_result ( None ) ;
1598- unreachable ! ( "panic=abort callback should have exited the process" ) ;
1599- }
1491+ RunStrategy :: InProcess => run_test_in_process ( desc, nocapture, testfn, monitor_ch) ,
1492+ RunStrategy :: SpawnPrimary => spawn_test_subprocess ( desc, monitor_ch) ,
16001493 }
16011494 } ;
16021495
@@ -1615,27 +1508,27 @@ pub fn run_test(
16151508 match testfn {
16161509 DynBenchFn ( bencher) => {
16171510 // Benchmarks aren't expected to panic, so we run them all in-process.
1618- crate :: bench:: benchmark ( opts , desc , strategy . monitor_ch ( ) . unwrap ( ) , |harness| {
1511+ crate :: bench:: benchmark ( desc , monitor_ch , opts . nocapture , |harness| {
16191512 bencher. run ( harness)
16201513 } ) ;
16211514 }
16221515 StaticBenchFn ( benchfn) => {
16231516 // Benchmarks aren't expected to panic, so we run them all in-process.
1624- crate :: bench:: benchmark ( opts , desc , strategy . monitor_ch ( ) . unwrap ( ) , |harness| {
1517+ crate :: bench:: benchmark ( desc , monitor_ch , opts . nocapture , |harness| {
16251518 ( benchfn. clone ( ) ) ( harness)
16261519 } ) ;
16271520 }
16281521 DynTestFn ( f) => {
16291522 match strategy {
1630- RunStrategy :: InProcess ( _ ) => ( ) ,
1523+ RunStrategy :: InProcess => ( ) ,
16311524 _ => panic ! ( "Cannot run dynamic test fn out-of-process" ) ,
16321525 } ;
16331526 let cb = move || __rust_begin_short_backtrace ( f) ;
1634- run_test_inner ( desc, opts. nocapture , strategy, Box :: new ( cb) , concurrency) ;
1527+ run_test_inner ( desc, opts. nocapture , strategy, monitor_ch , Box :: new ( cb) , concurrency) ;
16351528 }
16361529 StaticTestFn ( f) => {
16371530 let cb = move || __rust_begin_short_backtrace ( f) ;
1638- run_test_inner ( desc, opts. nocapture , strategy, Box :: new ( cb) , concurrency) ;
1531+ run_test_inner ( desc, opts. nocapture , strategy, monitor_ch , Box :: new ( cb) , concurrency) ;
16391532 }
16401533 }
16411534}
@@ -1673,6 +1566,104 @@ fn calc_result<'a>(desc: &TestDesc,
16731566 }
16741567}
16751568
1569+ fn run_test_in_process ( desc : TestDesc ,
1570+ nocapture : bool ,
1571+ testfn : Box < dyn FnOnce ( ) + Send > ,
1572+ monitor_ch : Sender < MonitorMsg > ) {
1573+ // Buffer for capturing standard I/O
1574+ let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1575+
1576+ let oldio = if !nocapture {
1577+ Some ( (
1578+ io:: set_print ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
1579+ io:: set_panic ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
1580+ ) )
1581+ } else {
1582+ None
1583+ } ;
1584+
1585+ let result = catch_unwind ( AssertUnwindSafe ( testfn) ) ;
1586+
1587+ if let Some ( ( printio, panicio) ) = oldio {
1588+ io:: set_print ( printio) ;
1589+ io:: set_panic ( panicio) ;
1590+ }
1591+
1592+ let test_result = match result {
1593+ Ok ( ( ) ) => calc_result ( & desc, Ok ( ( ) ) ) ,
1594+ Err ( e) => calc_result ( & desc, Err ( e. as_ref ( ) ) ) ,
1595+ } ;
1596+ let stdout = data. lock ( ) . unwrap ( ) . to_vec ( ) ;
1597+ monitor_ch. send ( ( desc. clone ( ) , test_result, stdout) ) . unwrap ( ) ;
1598+ }
1599+
1600+ fn spawn_test_subprocess ( desc : TestDesc , monitor_ch : Sender < MonitorMsg > ) {
1601+ let ( result, test_output) = ( || {
1602+ let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
1603+ let current_exe = & args[ 0 ] ;
1604+ let output = match Command :: new ( current_exe)
1605+ . env ( SECONDARY_TEST_INVOKER_VAR , desc. name . as_slice ( ) )
1606+ . output ( ) {
1607+ Ok ( out) => out,
1608+ Err ( e) => {
1609+ let err = format ! ( "Failed to spawn {} as child for test: {:?}" , args[ 0 ] , e) ;
1610+ return ( TrFailed , err. into_bytes ( ) ) ;
1611+ }
1612+ } ;
1613+
1614+ let std:: process:: Output { stdout, stderr, status } = output;
1615+ let mut test_output = stdout;
1616+ test_output. extend_from_slice ( & stderr) ;
1617+
1618+ let result = match ( move || {
1619+ let exit_code = status. code ( ) . ok_or ( "child process was terminated" ) ?;
1620+ TestResult :: try_from ( exit_code) . map_err ( |_| {
1621+ format ! ( "child process returned unexpected exit code {}" , exit_code)
1622+ } )
1623+ } ) ( ) {
1624+ Ok ( r) => r,
1625+ Err ( e) => {
1626+ write ! ( & mut test_output, "Unexpected error: {}" , e) . unwrap ( ) ;
1627+ TrFailed
1628+ }
1629+ } ;
1630+
1631+ ( result, test_output)
1632+ } ) ( ) ;
1633+
1634+ monitor_ch. send ( ( desc. clone ( ) , result, test_output) ) . unwrap ( ) ;
1635+ }
1636+
1637+ fn run_test_in_spawned_subprocess ( desc : TestDesc , testfn : Box < dyn FnOnce ( ) + Send > ) -> ! {
1638+ let builtin_panic_hook = panic:: take_hook ( ) ;
1639+ let record_result = Arc :: new ( move |panic_info : Option < & ' _ PanicInfo < ' _ > > | {
1640+ let test_result = match panic_info {
1641+ Some ( info) => calc_result ( & desc, Err ( info. payload ( ) ) ) ,
1642+ None => calc_result ( & desc, Ok ( ( ) ) ) ,
1643+ } ;
1644+
1645+ // We don't support serializing TrFailedMsg, so just
1646+ // print the message out to stderr.
1647+ let test_result = match test_result {
1648+ TrFailedMsg ( msg) => {
1649+ eprintln ! ( "{}" , msg) ;
1650+ TrFailed
1651+ }
1652+ _ => test_result,
1653+ } ;
1654+
1655+ if let Some ( info) = panic_info {
1656+ builtin_panic_hook ( info) ;
1657+ }
1658+ process:: exit ( test_result. try_into ( ) . unwrap ( ) ) ;
1659+ } ) ;
1660+ let record_result2 = record_result. clone ( ) ;
1661+ panic:: set_hook ( Box :: new ( move |info| record_result2 ( Some ( & info) ) ) ) ;
1662+ testfn ( ) ;
1663+ record_result ( None ) ;
1664+ unreachable ! ( "panic=abort callback should have exited the process" )
1665+ }
1666+
16761667#[ derive( Clone , PartialEq ) ]
16771668pub struct MetricMap ( BTreeMap < String , Metric > ) ;
16781669
@@ -1822,15 +1813,15 @@ where
18221813
18231814pub mod bench {
18241815 use super :: {
1825- BenchMode , BenchSamples , Bencher , MonitorMsg , Sender , Sink , TestDesc , TestOpts , TestResult
1816+ BenchMode , BenchSamples , Bencher , MonitorMsg , Sender , Sink , TestDesc , TestResult
18261817 } ;
18271818 use crate :: stats;
18281819 use std:: cmp;
18291820 use std:: io;
18301821 use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
18311822 use std:: sync:: { Arc , Mutex } ;
18321823
1833- pub fn benchmark < F > ( opts : & TestOpts , desc : TestDesc , monitor_ch : Sender < MonitorMsg > , f : F )
1824+ pub fn benchmark < F > ( desc : TestDesc , monitor_ch : Sender < MonitorMsg > , nocapture : bool , f : F )
18341825 where
18351826 F : FnMut ( & mut Bencher ) ,
18361827 {
@@ -1841,7 +1832,7 @@ pub mod bench {
18411832 } ;
18421833
18431834 let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1844- let oldio = if !opts . nocapture {
1835+ let oldio = if !nocapture {
18451836 Some ( (
18461837 io:: set_print ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
18471838 io:: set_panic ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
0 commit comments