Browse Source

Drop custom runner support

Fix compilation for use cases with imports, custom main etc. by using a
terminal arm trick with `@_@`.
pull/10/head
Ian Chamberlain 1 year ago
parent
commit
ffd037e11a
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 82
      test-runner/src/macros.rs

82
test-runner/src/macros.rs

@ -5,10 +5,11 @@
// for invalid code though, so we also silence that lint here. // for invalid code though, so we also silence that lint here.
#[cfg_attr(not(doctest), allow(rustdoc::invalid_rust_codeblocks))] #[cfg_attr(not(doctest), allow(rustdoc::invalid_rust_codeblocks))]
/// Helper macro for writing doctests using this runner. Wrap this macro around /// Helper macro for writing doctests using this runner. Wrap this macro around
/// your normal doctest to enable running it with the test runners in this crate. /// your normal doctest to enable running it with this crate's
/// [`GdbRunner`](crate::GdbRunner).
/// ///
/// You may optionally specify a runner before the test body, and may use any of /// You may use any of the various
/// the various [`fn main()`](https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html#using--in-doc-tests) /// [`fn main()`](https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html#using--in-doc-tests)
/// signatures allowed by documentation tests. /// signatures allowed by documentation tests.
/// ///
/// # Examples /// # Examples
@ -18,23 +19,18 @@
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
/// ``` /// ```
/// test_runner::doctest! { /// test_runner::doctest! {
/// assert_eq!(2 + 2, 4); /// let two = 2;
/// } /// let four = 4;
/// ``` /// assert_eq!(two + two, four);
#[cfg_attr(not(doctest), doc = "````")]
///
/// ## Custom runner
///
#[cfg_attr(not(doctest), doc = "````")]
/// ```no_run
/// test_runner::doctest! { SocketRunner,
/// assert_eq!(2 + 2, 4);
/// } /// }
/// ``` /// ```
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
/// ///
/// ## `should_panic` /// ## `should_panic`
/// ///
/// Using `no_run` or `ignore` makes this macro somewhat irrelevant, but
/// `should_panic` is still supported:
///
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
/// ```should_panic /// ```should_panic
/// test_runner::doctest! { /// test_runner::doctest! {
@ -43,23 +39,22 @@
/// ``` /// ```
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
/// ///
/// ## Custom `fn main` /// ## Custom `fn main`, crate attribute
/// ///
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
/// ``` /// ```
/// test_runner::doctest! { /// #![allow(unused)]
/// fn main() { ///
/// assert_eq!(2 + 2, 4); /// use std::error::Error;
/// }
/// }
/// ```
#[cfg_attr(not(doctest), doc = "````")]
/// ///
#[cfg_attr(not(doctest), doc = "````")]
/// ```
/// test_runner::doctest! { /// test_runner::doctest! {
/// fn main() -> Result<(), Box<dyn std::error::Error>> { /// // imports can be added outside or inside the macro
/// assert_eq!(2 + 2, 4); /// use std::ops::Add;
///
/// fn main() -> Result<(), Box<dyn Error>> {
/// let two = 2;
/// let four = 4;
/// assert_eq!(Add::add(two, two), four);
/// Ok(()) /// Ok(())
/// } /// }
/// } /// }
@ -79,23 +74,40 @@
/// Ok::<(), std::io::Error>(()) /// Ok::<(), std::io::Error>(())
/// ``` /// ```
#[cfg_attr(not(doctest), doc = "````")] #[cfg_attr(not(doctest), doc = "````")]
///
#[cfg_attr(not(doctest), doc = "````")]
/// ```should_panic
/// test_runner::doctest! {
/// assert_eq!(2 + 2, 4);
/// Err::<(), &str>("uh oh")
/// }
/// ```
#[cfg_attr(not(doctest), doc = "````")]
#[macro_export] #[macro_export]
macro_rules! doctest { macro_rules! doctest {
($runner:ident, fn main() $(-> $ret:ty)? { $($body:tt)* } ) => { (@_@ $($body:tt)*) => {
fn main() $(-> $ret)? { fn main() -> impl std::process::Termination {
$crate::doctest!{ $runner, $($body)* } #[allow(unused_imports)]
}
};
($runner:ident, $($body:tt)*) => {
use $crate::TestRunner as _; use $crate::TestRunner as _;
let mut _runner = $crate::$runner::default();
let mut _runner = $crate::GdbRunner::default();
_runner.setup(); _runner.setup();
// Luckily, Rust allows $body to define an inner shadowing main()
// and call it, without resulting in infinite recursion.
let _result = { $($body)* }; let _result = { $($body)* };
_runner.cleanup(_result) _runner.cleanup(_result)
}
}; };
( $($body:tt)* ) => { ( $($body:tt)* ) => {
$crate::doctest!{ GdbRunner, $crate::doctest! { @_@ $($body)* }
$($body)* };
( $($attrs:meta)* $($items:item)* ) => {
$(attrs)*
$crate::doctest! { @_@
$($items)*
main()
} }
}; };
} }

Loading…
Cancel
Save