#![forbid(unsafe_code)]
#![deny(
clippy::dbg_macro,
missing_copy_implementations,
rustdoc::missing_crate_level_docs,
missing_debug_implementations,
missing_docs,
nonstandard_style,
unused_qualifications
)]
mod assertions;
mod test_transport;
use std::future::{Future, IntoFuture};
use std::process::Termination;
pub use test_transport::TestTransport;
mod test_conn;
pub use test_conn::TestConn;
pub mod methods;
pub mod prelude {
pub use crate::{
assert_body, assert_body_contains, assert_headers, assert_not_handled, assert_ok,
assert_response, assert_status, block_on, connector, init, methods::*,
};
pub use trillium::{Conn, Method, Status};
}
pub use trillium::{Method, Status};
pub use url::Url;
pub fn init(handler: &mut impl trillium::Handler) {
let mut info = "testing".into();
block_on(handler.init(&mut info))
}
pub use futures_lite;
pub use futures_lite::{AsyncRead, AsyncReadExt, AsyncWrite};
mod server_connector;
pub use server_connector::{connector, ServerConnector};
use trillium_server_common::Config;
pub use trillium_server_common::{Connector, ObjectSafeConnector, Server, ServerHandle};
#[derive(Debug)]
pub struct SpawnHandle<F>(F);
impl<F> IntoFuture for SpawnHandle<F>
where
F: Future,
{
type IntoFuture = F;
type Output = F::Output;
fn into_future(self) -> Self::IntoFuture {
self.0
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "smol")] {
pub fn config() -> Config<impl Server, ()> {
trillium_smol::config()
}
pub fn spawn<Fut, Out>(future: Fut) -> SpawnHandle<impl Future<Output = Option<Out>>>
where
Fut: Future<Output = Out> + Send + 'static,
Out: Send + 'static
{
let (tx, rx) = async_channel::bounded::<Out>(1);
trillium_smol::async_global_executor::spawn(async move { let _ = tx.send(future.await).await; }).detach();
SpawnHandle(async move {
let rx = rx;
rx.recv().await.ok()
})
}
pub fn client_config() -> impl Connector {
ClientConfig::default()
}
pub use trillium_smol::async_global_executor::block_on;
pub use trillium_smol::ClientConfig;
} else if #[cfg(feature = "async-std")] {
pub fn config() -> Config<impl Server, ()> {
trillium_async_std::config()
}
pub use trillium_async_std::async_std::task::block_on;
pub use trillium_async_std::ClientConfig;
pub fn spawn<Fut, Out>(future: Fut) -> SpawnHandle<impl Future<Output = Option<Out>>>
where
Fut: Future<Output = Out> + Send + 'static,
Out: Send + 'static
{
let (tx, rx) = async_channel::bounded::<Out>(1);
trillium_async_std::async_std::task::spawn(async move { let _ = tx.send(future.await).await; });
SpawnHandle(async move {
let rx = rx;
rx.recv().await.ok()
})
}
pub fn client_config() -> impl Connector {
ClientConfig::default()
}
} else if #[cfg(feature = "tokio")] {
pub fn config() -> Config<impl Server, ()> {
trillium_tokio::config()
}
pub use trillium_tokio::ClientConfig;
pub use trillium_tokio::block_on;
pub fn spawn<Fut, Out>(future: Fut) -> SpawnHandle<impl Future<Output = Option<Out>>>
where
Fut: Future<Output = Out> + Send + 'static,
Out: Send + 'static
{
let (tx, rx) = async_channel::bounded::<Out>(1);
trillium_tokio::tokio::task::spawn(async move { let _ = tx.send(future.await).await; });
SpawnHandle(async move {
let rx = rx;
rx.recv().await.ok()
})
}
pub fn client_config() -> impl Connector {
ClientConfig::default()
}
} else {
pub fn config() -> Config<impl Server, ()> {
Config::<RuntimelessServer, ()>::new()
}
pub use RuntimelessClientConfig as ClientConfig;
pub fn client_config() -> impl Connector {
RuntimelessClientConfig::default()
}
pub use futures_lite::future::block_on;
pub fn spawn<Fut, Out>(future: Fut) -> SpawnHandle<impl Future<Output = Option<Out>>>
where
Fut: Future<Output = Out> + Send + 'static,
Out: Send + 'static
{
let (tx, rx) = async_channel::bounded::<Out>(1);
std::thread::spawn(move || { let _ = tx.send_blocking(block_on(future)); });
SpawnHandle(async move {
let rx = rx;
rx.recv().await.ok()
})
}
}
}
mod with_server;
pub use with_server::{with_server, with_transport};
mod runtimeless;
pub use runtimeless::{RuntimelessClientConfig, RuntimelessServer};
pub type TestResult = Result<(), Box<dyn std::error::Error>>;
#[track_caller]
pub fn harness<F, Fut, Output>(test: F) -> Output
where
F: FnOnce() -> Fut,
Fut: Future<Output = Output>,
Output: Termination,
{
block_on(test())
}