about summary refs log tree commit diff
path: root/src/libtest
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-09-11 17:13:34 -0700
committerTyler Mandry <tmandry@gmail.com>2019-09-28 13:52:18 -0700
commit8ae1ec60cc16e5d2a3d522a2e3fdddd27e5fb4c9 (patch)
treea2764361c43fe99fb568cd8c671d77883a1c7819 /src/libtest
parent76b12bd8fdd8c512cf9685a8ec51e76643f2f86f (diff)
downloadrust-8ae1ec60cc16e5d2a3d522a2e3fdddd27e5fb4c9.tar.gz
rust-8ae1ec60cc16e5d2a3d522a2e3fdddd27e5fb4c9.zip
Spawn one subprocess per unit test when panic=abort
Diffstat (limited to 'src/libtest')
-rw-r--r--src/libtest/formatters/mod.rs9
-rw-r--r--src/libtest/lib.rs364
-rw-r--r--src/libtest/tests.rs16
3 files changed, 291 insertions, 98 deletions
diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs
index e97cda76d23..dd202fb3ab6 100644
--- a/src/libtest/formatters/mod.rs
+++ b/src/libtest/formatters/mod.rs
@@ -22,3 +22,12 @@ pub(crate) trait OutputFormatter {
     ) -> io::Result<()>;
     fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool>;
 }
+
+pub(crate) fn write_stderr_delimiter(test_output: &mut Vec<u8>, test_name: &TestName) {
+    match test_output.last() {
+        Some(b'\n') => (),
+        Some(_) => test_output.push(b'\n'),
+        None => (),
+    }
+    write!(test_output, "---- {} stderr ----\n", test_name).unwrap();
+}
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index bcda5384204..f04d289c4ef 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -21,7 +21,8 @@
 #![unstable(feature = "test", issue = "50297")]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(asm)]
-#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc, rustc_private))]
+#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
+#![feature(rustc_private)]
 #![feature(nll)]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
@@ -34,16 +35,6 @@ use getopts;
 extern crate libc;
 use term;
 
-// FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
-//                on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc
-//                so we don't link libtest against libunwind (for the time being)
-//                even though it means that libtest won't be fully functional on
-//                these platforms.
-//
-// See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
-#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))]
-extern crate panic_unwind;
-
 pub use self::ColorConfig::*;
 use self::NamePadding::*;
 use self::OutputLocation::*;
@@ -61,10 +52,10 @@ use std::fmt;
 use std::fs::File;
 use std::io;
 use std::io::prelude::*;
-use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo};
 use std::path::PathBuf;
 use std::process;
-use std::process::Termination;
+use std::process::{ExitStatus, Command, Termination};
 use std::sync::mpsc::{channel, Sender};
 use std::sync::{Arc, Mutex};
 use std::thread;
@@ -76,13 +67,21 @@ mod tests;
 const TEST_WARN_TIMEOUT_S: u64 = 60;
 const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
 
+const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE";
+
+// Return codes for secondary process.
+// Start somewhere other than 0 so we know the return code means what we think
+// it means.
+const TR_OK: i32 = 50;
+const TR_FAILED: i32 = 51;
+
 // to be used by rustc to compile tests in libtest
 pub mod test {
     pub use crate::{
         assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
-        Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
-        StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts,
-        TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
+        Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, RunStrategy,
+        ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName,
+        TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
     };
 }
 
@@ -257,12 +256,14 @@ impl Metric {
 #[derive(Copy, Clone, Debug)]
 pub struct Options {
     display_output: bool,
+    panic_abort: bool,
 }
 
 impl Options {
     pub fn new() -> Options {
         Options {
             display_output: false,
+            panic_abort: false,
         }
     }
 
@@ -270,6 +271,11 @@ impl Options {
         self.display_output = display_output;
         self
     }
+
+    pub fn panic_abort(mut self, panic_abort: bool) -> Options {
+        self.panic_abort = panic_abort;
+        self
+    }
 }
 
 // The default console test runner. It accepts the command line
@@ -303,32 +309,66 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
     }
 }
 
-// A variant optimized for invocation with a static test vector.
-// This will panic (intentionally) when fed any dynamic tests, because
-// it is copying the static values out into a dynamic vector and cannot
-// copy dynamic values. It is doing this because from this point on
-// a Vec<TestDescAndFn> is used in order to effect ownership-transfer
-// semantics into parallel test runners, which in turn requires a Vec<>
-// rather than a &[].
+/// A variant optimized for invocation with a static test vector.
+/// This will panic (intentionally) when fed any dynamic tests.
+///
+/// This is the entry point for the main function generated by `rustc --test`
+/// when panic=unwind.
 pub fn test_main_static(tests: &[&TestDescAndFn]) {
     let args = env::args().collect::<Vec<_>>();
-    let owned_tests = tests
-        .iter()
-        .map(|t| match t.testfn {
-            StaticTestFn(f) => TestDescAndFn {
-                testfn: StaticTestFn(f),
-                desc: t.desc.clone(),
-            },
-            StaticBenchFn(f) => TestDescAndFn {
-                testfn: StaticBenchFn(f),
-                desc: t.desc.clone(),
-            },
-            _ => panic!("non-static tests passed to test::test_main_static"),
-        })
-        .collect();
+    let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
     test_main(&args, owned_tests, None)
 }
 
+/// A variant optimized for invocation with a static test vector.
+/// This will panic (intentionally) when fed any dynamic tests.
+///
+/// Runs tests in panic=abort mode, which involves spawning subprocesses for
+/// tests.
+///
+/// This is the entry point for the main function generated by `rustc --test`
+/// when panic=abort.
+pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
+    // If we're being run in SpawnedSecondary mode, run the test here. run_test
+    // will then exit the process.
+    if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
+        let test = tests
+            .iter()
+            .filter(|test| test.desc.name.as_slice() == name)
+            .map(make_owned_test)
+            .next()
+            .expect("couldn't find a test with the provided name");
+        let TestDescAndFn { desc, testfn } = test;
+        let testfn = match testfn {
+            StaticTestFn(f) => f,
+            _ => panic!("only static tests are supported"),
+        };
+        run_test_in_spawned_subprocess(desc, Box::new(testfn));
+    }
+
+    let args = env::args().collect::<Vec<_>>();
+    let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
+    test_main(&args, owned_tests, Some(Options::new().panic_abort(true)))
+}
+
+/// Clones static values for putting into a dynamic vector, which test_main()
+/// needs to hand out ownership of tests to parallel test runners.
+///
+/// This will panic when fed any dynamic tests, because they cannot be cloned.
+fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
+    match test.testfn {
+        StaticTestFn(f) => TestDescAndFn {
+            testfn: StaticTestFn(f),
+            desc: test.desc.clone(),
+        },
+        StaticBenchFn(f) => TestDescAndFn {
+            testfn: StaticBenchFn(f),
+            desc: test.desc.clone(),
+        },
+        _ => panic!("non-static tests passed to test::test_main_static"),
+    }
+}
+
 /// Invoked when unit tests terminate. Should panic if the unit
 /// Tests is considered a failure. By default, invokes `report()`
 /// and checks for a `0` result.
@@ -1062,6 +1102,18 @@ impl Write for Sink {
     }
 }
 
+#[derive(Clone, Copy)]
+pub enum RunStrategy {
+    /// Runs the test in the current process, and sends the result back over the
+    /// supplied channel.
+    InProcess,
+
+    /// Spawns a subprocess to run the test, and sends the result back over the
+    /// supplied channel. Requires argv[0] to exist and point to the binary
+    /// that's currently running.
+    SpawnPrimary,
+}
+
 pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
 where
     F: FnMut(TestEvent) -> io::Result<()>,
@@ -1109,6 +1161,11 @@ where
     let mut pending = 0;
 
     let (tx, rx) = channel::<MonitorMsg>();
+    let run_strategy = if opts.options.panic_abort {
+        RunStrategy::SpawnPrimary
+    } else {
+        RunStrategy::InProcess
+    };
 
     let mut running_tests: TestMap = HashMap::default();
 
@@ -1145,7 +1202,7 @@ where
         while !remaining.is_empty() {
             let test = remaining.pop().unwrap();
             callback(TeWait(test.desc.clone()))?;
-            run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No);
+            run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No);
             let (test, result, exec_time, stdout) = rx.recv().unwrap();
             callback(TeResult(test, result, exec_time, stdout))?;
         }
@@ -1156,7 +1213,7 @@ where
                 let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
                 running_tests.insert(test.desc.clone(), timeout);
                 callback(TeWait(test.desc.clone()))?; //here no pad
-                run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::Yes);
+                run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::Yes);
                 pending += 1;
             }
 
@@ -1188,7 +1245,7 @@ where
         // All benchmarks run at the end, in serial.
         for b in filtered_benchs {
             callback(TeWait(b.desc.clone()))?;
-            run_test(opts, false, b, tx.clone(), Concurrent::No);
+            run_test(opts, false, b, run_strategy, tx.clone(), Concurrent::No);
             let (test, result, exec_time, stdout) = rx.recv().unwrap();
             callback(TeResult(test, result, exec_time, stdout))?;
         }
@@ -1415,64 +1472,38 @@ pub fn run_test(
     opts: &TestOpts,
     force_ignore: bool,
     test: TestDescAndFn,
+    strategy: RunStrategy,
     monitor_ch: Sender<MonitorMsg>,
     concurrency: Concurrent,
 ) {
     let TestDescAndFn { desc, testfn } = test;
 
-    let ignore_because_panic_abort = cfg!(target_arch = "wasm32")
+    let ignore_because_no_process_support = cfg!(target_arch = "wasm32")
         && !cfg!(target_os = "emscripten")
         && desc.should_panic != ShouldPanic::No;
 
-    if force_ignore || desc.ignore || ignore_because_panic_abort {
+    if force_ignore || desc.ignore || ignore_because_no_process_support {
         monitor_ch.send((desc, TrIgnored, None, Vec::new())).unwrap();
         return;
     }
 
     fn run_test_inner(
         desc: TestDesc,
-        monitor_ch: Sender<MonitorMsg>,
         nocapture: bool,
         report_time: bool,
+        strategy: RunStrategy,
+        monitor_ch: Sender<MonitorMsg>,
         testfn: Box<dyn FnOnce() + Send>,
         concurrency: Concurrent,
     ) {
-        // Buffer for capturing standard I/O
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let data2 = data.clone();
-
         let name = desc.name.clone();
-        let runtest = move || {
-            let oldio = if !nocapture {
-                Some((
-                    io::set_print(Some(Box::new(Sink(data2.clone())))),
-                    io::set_panic(Some(Box::new(Sink(data2)))),
-                ))
-            } else {
-                None
-            };
-
-            let start = if report_time {
-                Some(Instant::now())
-            } else {
-                None
-            };
-            let result = catch_unwind(AssertUnwindSafe(testfn));
-            let exec_time = start.map(|start| {
-                let duration = start.elapsed();
-                TestExecTime(duration)
-            });
-
-            if let Some((printio, panicio)) = oldio {
-                io::set_print(printio);
-                io::set_panic(panicio);
-            };
 
-            let test_result = calc_result(&desc, result);
-            let stdout = data.lock().unwrap().to_vec();
-            monitor_ch
-                .send((desc.clone(), test_result, exec_time, stdout))
-                .unwrap();
+        let runtest = move || {
+            match strategy {
+                RunStrategy::InProcess =>
+                    run_test_in_process(desc, nocapture, report_time, testfn, monitor_ch),
+                RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, report_time, monitor_ch),
+            }
         };
 
         // If the platform is single-threaded we're just going to run
@@ -1489,31 +1520,38 @@ pub fn run_test(
 
     match testfn {
         DynBenchFn(bencher) => {
+            // Benchmarks aren't expected to panic, so we run them all in-process.
             crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
                 bencher.run(harness)
             });
         }
         StaticBenchFn(benchfn) => {
+            // Benchmarks aren't expected to panic, so we run them all in-process.
             crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
                 (benchfn.clone())(harness)
             });
         }
         DynTestFn(f) => {
-            let cb = move || __rust_begin_short_backtrace(f);
+            match strategy {
+                RunStrategy::InProcess => (),
+                _ => panic!("Cannot run dynamic test fn out-of-process"),
+            };
             run_test_inner(
                 desc,
-                monitor_ch,
                 opts.nocapture,
                 opts.report_time,
-                Box::new(cb),
-                concurrency,
-            )
+                strategy,
+                monitor_ch,
+                Box::new(move || __rust_begin_short_backtrace(f)),
+                concurrency
+            );
         }
         StaticTestFn(f) => run_test_inner(
             desc,
-            monitor_ch,
             opts.nocapture,
             opts.report_time,
+            strategy,
+            monitor_ch,
             Box::new(move || __rust_begin_short_backtrace(f)),
             concurrency,
         ),
@@ -1526,7 +1564,9 @@ fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
     f()
 }
 
-fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) -> TestResult {
+fn calc_result<'a>(desc: &TestDesc,
+                   task_result: Result<(), &'a (dyn Any + 'static + Send)>)
+-> TestResult {
     match (&desc.should_panic, task_result) {
         (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk,
         (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
@@ -1552,6 +1592,150 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) ->
     }
 }
 
+fn get_result_from_exit_code(desc: &TestDesc, code: i32) -> TestResult {
+    match (desc.allow_fail, code) {
+        (_, TR_OK) => TrOk,
+        (true, TR_FAILED) => TrAllowedFail,
+        (false, TR_FAILED) => TrFailed,
+        (_, _) => TrFailedMsg(format!("got unexpected return code {}", code)),
+    }
+}
+
+fn run_test_in_process(desc: TestDesc,
+                       nocapture: bool,
+                       report_time: bool,
+                       testfn: Box<dyn FnOnce() + Send>,
+                       monitor_ch: Sender<MonitorMsg>) {
+    // Buffer for capturing standard I/O
+    let data = Arc::new(Mutex::new(Vec::new()));
+
+    let oldio = if !nocapture {
+        Some((
+            io::set_print(Some(Box::new(Sink(data.clone())))),
+            io::set_panic(Some(Box::new(Sink(data.clone())))),
+        ))
+    } else {
+        None
+    };
+
+    let start = if report_time {
+        Some(Instant::now())
+    } else {
+        None
+    };
+    let result = catch_unwind(AssertUnwindSafe(testfn));
+    let exec_time = start.map(|start| {
+        let duration = start.elapsed();
+        TestExecTime(duration)
+    });
+
+    if let Some((printio, panicio)) = oldio {
+        io::set_print(printio);
+        io::set_panic(panicio);
+    }
+
+    let test_result = match result {
+        Ok(()) => calc_result(&desc, Ok(())),
+        Err(e) => calc_result(&desc, Err(e.as_ref())),
+    };
+    let stdout = data.lock().unwrap().to_vec();
+    monitor_ch.send((desc.clone(), test_result, exec_time, stdout)).unwrap();
+}
+
+fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender<MonitorMsg>) {
+    let (result, test_output, exec_time) = (|| {
+        let args = env::args().collect::<Vec<_>>();
+        let current_exe = &args[0];
+
+        let start = if report_time {
+            Some(Instant::now())
+        } else {
+            None
+        };
+        let output = match Command::new(current_exe)
+            .env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice())
+            .output() {
+                Ok(out) => out,
+                Err(e) => {
+                    let err = format!("Failed to spawn {} as child for test: {:?}", args[0], e);
+                    return (TrFailed, err.into_bytes(), None);
+                }
+            };
+        let exec_time = start.map(|start| {
+            let duration = start.elapsed();
+            TestExecTime(duration)
+        });
+
+        let std::process::Output { stdout, stderr, status } = output;
+        let mut test_output = stdout;
+        formatters::write_stderr_delimiter(&mut test_output, &desc.name);
+        test_output.extend_from_slice(&stderr);
+
+        let result = match (|| -> Result<TestResult, String> {
+            let exit_code = get_exit_code(status)?;
+            Ok(get_result_from_exit_code(&desc, exit_code))
+        })() {
+            Ok(r) => r,
+            Err(e) => {
+                write!(&mut test_output, "Unexpected error: {}", e).unwrap();
+                TrFailed
+            }
+        };
+
+        (result, test_output, exec_time)
+    })();
+
+    monitor_ch.send((desc.clone(), result, exec_time, test_output)).unwrap();
+}
+
+fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box<dyn FnOnce() + Send>) -> ! {
+    let builtin_panic_hook = panic::take_hook();
+    let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
+        let test_result = match panic_info {
+            Some(info) => calc_result(&desc, Err(info.payload())),
+            None => calc_result(&desc, Ok(())),
+        };
+
+        // We don't support serializing TrFailedMsg, so just
+        // print the message out to stderr.
+        if let TrFailedMsg(msg) = &test_result {
+            eprintln!("{}", msg);
+        }
+
+        if let Some(info) = panic_info {
+            builtin_panic_hook(info);
+        }
+
+        if let TrOk = test_result {
+            process::exit(TR_OK);
+        } else {
+            process::exit(TR_FAILED);
+        }
+    });
+    let record_result2 = record_result.clone();
+    panic::set_hook(Box::new(move |info| record_result2(Some(&info))));
+    testfn();
+    record_result(None);
+    unreachable!("panic=abort callback should have exited the process")
+}
+
+#[cfg(not(unix))]
+fn get_exit_code(status: ExitStatus) -> Result<i32, String> {
+    status.code().ok_or("received no exit code from child process".into())
+}
+
+#[cfg(unix)]
+fn get_exit_code(status: ExitStatus) -> Result<i32, String> {
+    use std::os::unix::process::ExitStatusExt;
+    match status.code() {
+        Some(code) => Ok(code),
+        None => match status.signal() {
+            Some(signal) => Err(format!("child process exited with signal {}", signal)),
+            None => Err("child process exited with unknown signal".into()),
+        }
+    }
+}
+
 #[derive(Clone, PartialEq)]
 pub struct MetricMap(BTreeMap<String, Metric>);
 
@@ -1700,7 +1884,9 @@ where
 }
 
 pub mod bench {
-    use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult};
+    use super::{
+        BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult
+    };
     use crate::stats;
     use std::cmp;
     use std::io;
@@ -1718,12 +1904,10 @@ pub mod bench {
         };
 
         let data = Arc::new(Mutex::new(Vec::new()));
-        let data2 = data.clone();
-
         let oldio = if !nocapture {
             Some((
-                io::set_print(Some(Box::new(Sink(data2.clone())))),
-                io::set_panic(Some(Box::new(Sink(data2)))),
+                io::set_print(Some(Box::new(Sink(data.clone())))),
+                io::set_panic(Some(Box::new(Sink(data.clone())))),
             ))
         } else {
             None
@@ -1734,7 +1918,7 @@ pub mod bench {
         if let Some((printio, panicio)) = oldio {
             io::set_print(printio);
             io::set_panic(panicio);
-        };
+        }
 
         let test_result = match result {
             //bs.bench(f) {
diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs
index 38ec7bd7093..b95fb5df710 100644
--- a/src/libtest/tests.rs
+++ b/src/libtest/tests.rs
@@ -1,7 +1,7 @@
 use super::*;
 
 use crate::test::{
-    filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
+    filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy,
     ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailedMsg,
     TrIgnored, TrOk,
 };
@@ -67,7 +67,7 @@ pub fn do_not_run_ignored_tests() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res != TrOk);
 }
@@ -85,7 +85,7 @@ pub fn ignored_tests_result_in_ignored() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res == TrIgnored);
 }
@@ -105,7 +105,7 @@ fn test_should_panic() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res == TrOk);
 }
@@ -125,7 +125,7 @@ fn test_should_panic_good_message() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res == TrOk);
 }
@@ -147,7 +147,7 @@ fn test_should_panic_bad_message() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
 }
@@ -165,7 +165,7 @@ fn test_should_panic_but_succeeds() {
         testfn: DynTestFn(Box::new(f)),
     };
     let (tx, rx) = channel();
-    run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+    run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
     assert!(res == TrFailedMsg("test did not panic as expected".to_string()));
 }
@@ -186,7 +186,7 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
         ..TestOpts::new()
     };
     let (tx, rx) = channel();
-    run_test(&test_opts, false, desc, tx, Concurrent::No);
+    run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No);
     let (_, _, exec_time, _) = rx.recv().unwrap();
     exec_time
 }