|
|
@ -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() |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|