safina_macros/
lib.rs

1//! # safina-macros
2//! [![crates.io version](https://img.shields.io/crates/v/safina-async-test-core.svg)](https://crates.io/crates/safina-macros)
3//! [![license: Apache 2.0](https://gitlab.com/leonhard-llc/safina-rs/-/raw/main/license-apache-2.0.svg)](http://www.apache.org/licenses/LICENSE-2.0)
4//! [![unsafe forbidden](https://gitlab.com/leonhard-llc/safina-rs/-/raw/main/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
5//! [![pipeline status](https://gitlab.com/leonhard-llc/safina-rs/badges/main/pipeline.svg)](https://gitlab.com/leonhard-llc/safina-rs/-/pipelines)
6//!
7//! Procedural macros for the [safina](https://crates.io/crates/safina) crate.
8//!
9//! License: Apache-2.0
10//!
11//! # Cargo Geiger Safety Report
12#![forbid(unsafe_code)]
13
14mod async_test;
15
16/// A macro for running `async fn` tests.
17///
18/// - Runs tests with [safina::executor](https://docs.rs/safina/latest/safina/executor/)
19/// - Each test gets its own executor with 2 threads for async tasks and 1 thread for blocking tasks.
20/// - Also calls
21///   [safina::timer::start_timer_thread](https://docs.rs/safina/latest/safina/timer/fn.start_timer_thread.html)
22///   before running the test
23/// - Lightweight dependencies
24///
25/// # Examples
26/// ```rust
27/// use safina::async_test;
28/// # async fn async_work() -> Result<(), std::io::Error> { Ok(()) }
29///
30/// #[async_test]
31/// async fn test1() {
32///     async_work().await.unwrap();
33/// }
34/// ```
35///
36/// ```rust
37/// use safina::async_test;
38/// # use core::time::Duration;
39/// # fn blocking_work() -> Result<u8, std::io::Error> { Ok(3) }
40/// # async fn background_task() {}
41/// # async fn async_work() -> Result<u8, std::io::Error> { Ok(42) }
42///
43/// // Make your test an `async fn`.
44/// #[async_test]
45/// async fn test2() {
46///     // You can `await`.
47///     async_work().await.unwrap();
48///
49///     // You can spawn tasks which will run on
50///     // the executor.
51///     // These tasks stop when the test
52///     // function returns and drops the
53///     // executor.
54///     safina::executor::spawn(background_task());
55///
56///     // You can run blocking code without
57///     // stalling other async tasks.
58///     let result = safina::executor::schedule_blocking(
59///         || blocking_work()
60///     ).async_recv().await.unwrap();
61///     assert_eq!(3, result.unwrap());
62///
63///     // You can use timer functions.
64///     safina::timer::sleep_for(
65///         Duration::from_millis(10)).await;
66///     safina::timer::with_timeout(
67///         async_work(),
68///         Duration::from_millis(100)
69///     ).await.unwrap().unwrap();
70/// }
71/// ```
72///
73/// # Alternatives
74/// - [async_std::test](https://docs.rs/async-std/latest/async_std/attr.test.html)
75/// - [futures_await_test::async_test](https://docs.rs/futures-await-test)
76/// - [tokio::test](https://docs.rs/tokio/latest/tokio/attr.test.html)
77#[proc_macro_attribute]
78pub fn async_test(
79    attr: proc_macro::TokenStream,
80    item: proc_macro::TokenStream,
81) -> proc_macro::TokenStream {
82    let output2 = match async_test::implementation(
83        safe_proc_macro2::TokenStream::from(attr),
84        safe_proc_macro2::TokenStream::from(item),
85    ) {
86        Ok(output) => output,
87        Err(error_tokens) => return proc_macro::TokenStream::from(error_tokens),
88    };
89
90    // let mut token_stream_string = String::new();
91    // for tree in output {
92    //     token_stream_string.push_str(format!("tree: {tree}\n").as_str());
93    // }
94    // panic!("TokenStream:\n{}", token_stream_string);
95
96    proc_macro::TokenStream::from(output2)
97}