@@ -333,9 +333,12 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
333
333
. map ( make_owned_test)
334
334
. next ( )
335
335
. 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) ) ;
339
342
}
340
343
341
344
let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
@@ -1088,31 +1091,16 @@ impl Write for Sink {
1088
1091
}
1089
1092
}
1090
1093
1091
- #[ derive( Clone ) ]
1094
+ #[ derive( Clone , Copy ) ]
1092
1095
pub enum RunStrategy {
1093
1096
/// Runs the test in the current process, and sends the result back over the
1094
1097
/// supplied channel.
1095
- InProcess ( Sender < MonitorMsg > ) ,
1098
+ InProcess ,
1096
1099
1097
1100
/// Spawns a subprocess to run the test, and sends the result back over the
1098
1101
/// supplied channel. Requires argv[0] to exist and point to the binary
1099
1102
/// 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 ,
1116
1104
}
1117
1105
1118
1106
pub fn run_tests < F > ( opts : & TestOpts , tests : Vec < TestDescAndFn > , mut callback : F ) -> io:: Result < ( ) >
@@ -1163,9 +1151,9 @@ where
1163
1151
1164
1152
let ( tx, rx) = channel :: < MonitorMsg > ( ) ;
1165
1153
let run_strategy = if opts. options . panic_abort {
1166
- RunStrategy :: SpawnPrimary ( tx )
1154
+ RunStrategy :: SpawnPrimary
1167
1155
} else {
1168
- RunStrategy :: InProcess ( tx )
1156
+ RunStrategy :: InProcess
1169
1157
} ;
1170
1158
1171
1159
let mut running_tests: TestMap = HashMap :: default ( ) ;
@@ -1203,7 +1191,7 @@ where
1203
1191
while !remaining. is_empty ( ) {
1204
1192
let test = remaining. pop ( ) . unwrap ( ) ;
1205
1193
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 ) ;
1207
1195
let ( test, result, stdout) = rx. recv ( ) . unwrap ( ) ;
1208
1196
callback ( TeResult ( test, result, stdout) ) ?;
1209
1197
}
@@ -1214,7 +1202,7 @@ where
1214
1202
let timeout = Instant :: now ( ) + Duration :: from_secs ( TEST_WARN_TIMEOUT_S ) ;
1215
1203
running_tests. insert ( test. desc . clone ( ) , timeout) ;
1216
1204
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 ) ;
1218
1206
pending += 1 ;
1219
1207
}
1220
1208
@@ -1246,7 +1234,7 @@ where
1246
1234
// All benchmarks run at the end, in serial.
1247
1235
for b in filtered_benchs {
1248
1236
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 ) ;
1250
1238
let ( test, result, stdout) = rx. recv ( ) . unwrap ( ) ;
1251
1239
callback ( TeResult ( test, result, stdout) ) ?;
1252
1240
}
@@ -1474,129 +1462,34 @@ pub fn run_test(
1474
1462
force_ignore : bool ,
1475
1463
test : TestDescAndFn ,
1476
1464
strategy : RunStrategy ,
1465
+ monitor_ch : Sender < MonitorMsg > ,
1477
1466
concurrency : Concurrent ,
1478
1467
) {
1479
1468
let TestDescAndFn { desc, testfn } = test;
1480
1469
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 ( ) ;
1488
1476
return ;
1489
1477
}
1490
1478
1491
1479
fn run_test_inner (
1492
1480
desc : TestDesc ,
1493
1481
nocapture : bool ,
1494
1482
strategy : RunStrategy ,
1483
+ monitor_ch : Sender < MonitorMsg > ,
1495
1484
testfn : Box < dyn FnOnce ( ) + Send > ,
1496
1485
concurrency : Concurrent ,
1497
1486
) {
1498
- // Buffer for capturing standard I/O
1499
- let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1500
-
1501
1487
let name = desc. name . clone ( ) ;
1488
+
1502
1489
let runtest = move || {
1503
- // TODO split into functions
1504
1490
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) ,
1600
1493
}
1601
1494
} ;
1602
1495
@@ -1615,27 +1508,27 @@ pub fn run_test(
1615
1508
match testfn {
1616
1509
DynBenchFn ( bencher) => {
1617
1510
// 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| {
1619
1512
bencher. run ( harness)
1620
1513
} ) ;
1621
1514
}
1622
1515
StaticBenchFn ( benchfn) => {
1623
1516
// 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| {
1625
1518
( benchfn. clone ( ) ) ( harness)
1626
1519
} ) ;
1627
1520
}
1628
1521
DynTestFn ( f) => {
1629
1522
match strategy {
1630
- RunStrategy :: InProcess ( _ ) => ( ) ,
1523
+ RunStrategy :: InProcess => ( ) ,
1631
1524
_ => panic ! ( "Cannot run dynamic test fn out-of-process" ) ,
1632
1525
} ;
1633
1526
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) ;
1635
1528
}
1636
1529
StaticTestFn ( f) => {
1637
1530
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) ;
1639
1532
}
1640
1533
}
1641
1534
}
@@ -1673,6 +1566,104 @@ fn calc_result<'a>(desc: &TestDesc,
1673
1566
}
1674
1567
}
1675
1568
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
+
1676
1667
#[ derive( Clone , PartialEq ) ]
1677
1668
pub struct MetricMap ( BTreeMap < String , Metric > ) ;
1678
1669
@@ -1822,15 +1813,15 @@ where
1822
1813
1823
1814
pub mod bench {
1824
1815
use super :: {
1825
- BenchMode , BenchSamples , Bencher , MonitorMsg , Sender , Sink , TestDesc , TestOpts , TestResult
1816
+ BenchMode , BenchSamples , Bencher , MonitorMsg , Sender , Sink , TestDesc , TestResult
1826
1817
} ;
1827
1818
use crate :: stats;
1828
1819
use std:: cmp;
1829
1820
use std:: io;
1830
1821
use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
1831
1822
use std:: sync:: { Arc , Mutex } ;
1832
1823
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 )
1834
1825
where
1835
1826
F : FnMut ( & mut Bencher ) ,
1836
1827
{
@@ -1841,7 +1832,7 @@ pub mod bench {
1841
1832
} ;
1842
1833
1843
1834
let data = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1844
- let oldio = if !opts . nocapture {
1835
+ let oldio = if !nocapture {
1845
1836
Some ( (
1846
1837
io:: set_print ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
1847
1838
io:: set_panic ( Some ( Box :: new ( Sink ( data. clone ( ) ) ) ) ) ,
0 commit comments