1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! [![crates.io version](https://img.shields.io/crates/v/safina-async-test.svg)](https://crates.io/crates/safina-async-test)
//! [![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)
//! [![unsafe forbidden](https://gitlab.com/leonhard-llc/safina-rs/-/raw/main/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
//! [![pipeline status](https://gitlab.com/leonhard-llc/safina-rs/badges/main/pipeline.svg)](https://gitlab.com/leonhard-llc/safina-rs/-/pipelines)
//!
//! An `async_test` macro for running `async fn` tests.
//!
//! It is part of [`safina`](https://crates.io/crates/safina), a safe async runtime.
//!
//! # Features
//! - Runs tests with [`safina_executor`](https://docs.rs/safina-executor)
//! - Each test gets its own executor with 2 threads for async tasks and 1 thread for blocking tasks.
//! - Also calls
//!   [`safina_timer::start_timer_thread`](https://docs.rs/safina-timer/latest/safina_timer/fn.start_timer_thread.html)
//!   before running the test
//! - `forbid(unsafe_code)`
//! - Lightweight dependencies
//! - Straightforward implementation
//!
//! # Limitations
//! - Building on `stable` requires [`once_cell`](https://crates.io/crates/once_cell)
//!   crate which contains some unsafe code.
//!   This is necessary until
//!   [`std::lazy::OnceCell`](https://doc.rust-lang.org/std/lazy/struct.OnceCell.html)
//!   is stable.
//!
//! # Examples
//! ```rust
//! use safina_async_test::async_test;
//! # async fn async_work() -> Result<(), std::io::Error> { Ok(()) }
//!
//! #[async_test]
//! async fn test1() {
//!     async_work().await.unwrap();
//! }
//! ```
//!
//! ```rust
//! use safina;
//! use safina_async_test::async_test;
//! # use core::time::Duration;
//! # fn blocking_work() -> Result<u8, std::io::Error> { Ok(3) }
//! # async fn background_task() {}
//! # async fn async_work() -> Result<u8, std::io::Error> { Ok(42) }
//!
//! // Make your test an `async fn`.
//! #[async_test]
//! async fn test2() {
//!     // You can `await`.
//!     async_work().await.unwrap();
//!
//!     // You can spawn tasks which will run on
//!     // the executor.
//!     // These tasks stop when the test
//!     // function returns and drops the
//!     // executor.
//!     safina::spawn(background_task());
//!
//!     // You can run blocking code without
//!     // stalling other async tasks.
//!     let result = safina::schedule_blocking(
//!         || blocking_work()
//!     );
//!     assert_eq!(3, result.await.unwrap());
//!
//!     // You can use timer functions.
//!     safina::sleep_for(
//!         Duration::from_millis(10)).await;
//!     safina::with_timeout(
//!         async_work(),
//!         Duration::from_millis(100)
//!     ).await.unwrap();
//! }
//! ```
//!
//! # Documentation
//! <https://docs.rs/safina-async-test>
//!
//! # Alternatives
//! - [`async_std::test`](https://docs.rs/async-std/latest/async_std/attr.test.html)
//! - [`futures_await_test::async_test`](https://docs.rs/futures-await-test/0.3.0/futures_await_test/)
//! - [`tokio::test`](https://docs.rs/tokio/latest/tokio/attr.test.html)
//!
//! # Changelog
//! - v0.1.9 - Don't require users to also depend on `safina-executor` and
//!   `safina-timer` crates.
//! - v0.1.8
//!   - Support stable with rust 1.51 and `once_cell`.
//!   - Start an Executor for each test
//! - v0.1.7 - Update to safina-executor v0.1.4
//! - v0.1.6 - Start [`safina-timer`](https://crates.io/crates/safina-timer)
//!   thread
//! - v0.1.5 - Use [`safina-executor`](https://crates.io/crates/safina-executor)
//!   v0.1.3 API
//! - v0.1.4 - Upgrade to new
//!   [`safina-executor`](https://crates.io/crates/safina-executor)
//!   version which removes need for `Box::pin`.
//! - v0.1.3 - Rename [`safina`](https://crates.io/crates/safina) package to
//!   [`safina-executor`](https://crates.io/crates/safina-executor).
//! - v0.1.2 - Update docs
//! - v0.1.1 - First published version
//!
//! # Happy Contributors 🙂
//! Fixing bugs and adding features is easy and fast.
//! Send us a pull request and we intend to:
//! - Always respond within 24 hours
//! - Provide clear & concrete feedback
//! - Immediately make a new release for your accepted change
//!
//! # TO DO
//! - DONE - Implement as declarative macro.  UX is bad.
//! - DONE - Implement as procedural macro.
//! - DONE - Report errors nicely
//! - DONE - Publish on crates.io
//! - DONE - Automatically start a worker thread and timer thread.
//! - DONE - Let users depend only on safina-async-test:
//!   - DONE - Move proc macro to its own crate.
//!   - DONE - Make `safina_async_test` re-export the macro and `safina_executor::block_on`.
//!   - DONE - Change the macro to call `safina_async_test::block_on`.
//!
//! # Release Process
//! 1. Edit `Cargo.toml` and bump version number.
//! 1. Run `./release.sh`
#![forbid(unsafe_code)]

pub use safina_async_test_core::async_test;
pub use safina_executor::Executor;
pub use safina_timer::start_timer_thread;