| //- |
| // Copyright 2018 Jason Lingle |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| #![deny(missing_docs, unsafe_code)] |
| |
| //! Rusty-fork provides a way to "fork" unit tests into separate processes. |
| //! |
| //! There are a number of reasons to want to run some tests in isolated |
| //! processes: |
| //! |
| //! - When tests share a process, if any test causes the process to abort, |
| //! segfault, overflow the stack, etc., the entire test runner process dies. If |
| //! the test is in a subprocess, only the subprocess dies and the test runner |
| //! simply fails the test. |
| //! |
| //! - Isolating a test to a subprocess makes it possible to add a timeout to |
| //! the test and forcibly terminate it and produce a normal test failure. |
| //! |
| //! - Tests which need to interact with some inherently global property, such |
| //! as the current working directory, can do so without interfering with other |
| //! tests. |
| //! |
| //! This crate itself provides two things: |
| //! |
| //! - The [`rusty_fork_test!`](macro.rusty_fork_test.html) macro, which is a |
| //! simple way to wrap standard Rust tests to be run in subprocesses with |
| //! optional timeouts. |
| //! |
| //! - The [`fork`](fn.fork.html) function which can be used as a building block |
| //! to make other types of process isolation strategies. |
| //! |
| //! ## Quick Start |
| //! |
| //! If you just want to run normal Rust tests in isolated processes, getting |
| //! started is pretty quick. |
| //! |
| //! In `Cargo.toml`, add |
| //! |
| //! ```toml |
| //! [dev-dependencies] |
| //! rusty-fork = "0.2.1" |
| //! ``` |
| //! |
| //! and to your crate root add |
| //! |
| //! ```rust,ignore |
| //! #[macro_use] extern crate rusty_fork; |
| //! ``` |
| //! |
| //! Then, you can simply wrap any test(s) to be isolated with the |
| //! [`rusty_fork_test!`](macro.rusty_fork_test.html) macro. |
| //! |
| //! ```rust |
| //! #[macro_use] extern crate rusty_fork; |
| //! |
| //! rusty_fork_test! { |
| //! # /* NOREADME |
| //! #[test] |
| //! # NOREADME */ |
| //! fn my_test() { |
| //! assert_eq!(2, 1 + 1); |
| //! } |
| //! |
| //! // more tests... |
| //! } |
| //! # // NOREADME |
| //! # fn main() { my_test(); } // NOREADME |
| //! ``` |
| //! |
| //! For more advanced usage, have a look at the [`fork`](fn.fork.html) |
| //! function. |
| //! |
| //! ## How rusty-fork works |
| //! |
| //! Unix-style process forking isn't really viable within the standard Rust |
| //! test environment for a number of reasons. |
| //! |
| //! - While true process forking can be done on Windows, it's neither fast nor |
| //! reliable. |
| //! |
| //! - The Rust test environment is multi-threaded, so attempting to do anything |
| //! non-trivial after a process fork would result in undefined behaviour. |
| //! |
| //! Rusty-fork instead works by _spawning_ a fresh instance of the current |
| //! process, after adjusting the command-line to ensure that only the desired |
| //! test is entered. Some additional coordination establishes the parent/child |
| //! branches and (not quite seamlessly) integrates the child's output with the |
| //! test output capture system. |
| //! |
| //! Coordination between the processes is performed via environment variables, |
| //! since there is otherwise no way to pass parameters to a test. |
| //! |
| //! Since it needs to spawn new copies of the test runner executable, |
| //! rusty-fork does need to know about the meaning of every flag passed by the |
| //! user. If any unknown flags are encountered, forking will fail. Please do |
| //! not hesitate to file |
| //! [issues](https://github.com/AltSysrq/rusty-fork/issues) if rusty-fork fails |
| //! to recognise any valid flags passed to the test runner. |
| //! |
| //! It is possible to inform rusty-fork of new flags without patching by |
| //! setting environment variables. For example, if a new `--frob-widgets` flag |
| //! were added to the test runner, you could set `RUSTY_FORK_FLAG_FROB_WIDGETS` |
| //! to one of the following: |
| //! |
| //! - `pass` — Pass the flag (just the flag) to the child process |
| //! - `pass-arg` — Pass the flag and its following argument to the child process |
| //! - `drop` — Don't pass the flag to the child process |
| //! - `drop-arg` — Don't pass the flag to the child process, and ignore whatever |
| //! argument follows. |
| //! |
| //! In general, arguments that affect which tests are run should be dropped, |
| //! and others should be passed. |
| //! |
| //! <!-- ENDREADME --> |
| |
| extern crate fnv; |
| #[macro_use] extern crate quick_error; |
| extern crate tempfile; |
| #[cfg(feature = "timeout")] extern crate wait_timeout; |
| |
| #[macro_use] mod sugar; |
| #[macro_use] pub mod fork_test; |
| mod error; |
| mod cmdline; |
| mod fork; |
| mod child_wrapper; |
| |
| pub use sugar::RustyForkId; |
| pub use error::{Error, Result}; |
| pub use fork::fork; |
| pub use child_wrapper::{ChildWrapper, ExitStatusWrapper}; |