From 64f520453f6e85a355f65ff7a60936e3141aaf9a Mon Sep 17 00:00:00 2001 From: notoriaga Date: Wed, 9 Nov 2022 10:42:29 -0800 Subject: [PATCH] add Send/Sync tests --- crates/esthri/tests/integration/main.rs | 1 + crates/esthri/tests/integration/send_sync.rs | 117 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 crates/esthri/tests/integration/send_sync.rs diff --git a/crates/esthri/tests/integration/main.rs b/crates/esthri/tests/integration/main.rs index 70b12e40..545a81d0 100644 --- a/crates/esthri/tests/integration/main.rs +++ b/crates/esthri/tests/integration/main.rs @@ -3,6 +3,7 @@ mod delete_test; mod download_test; mod list_object_test; +mod send_sync; mod sync_test; mod upload_test; diff --git a/crates/esthri/tests/integration/send_sync.rs b/crates/esthri/tests/integration/send_sync.rs new file mode 100644 index 00000000..2576ef65 --- /dev/null +++ b/crates/esthri/tests/integration/send_sync.rs @@ -0,0 +1,117 @@ +use std::{cell::Cell, future, path::Path, pin::Pin, rc::Rc}; + +use tokio::io; + +use esthri::opts; + +// From https://github.com/tokio-rs/tokio/blob/master/tokio/tests/async_send_sync.rs + +// The names of these structs behaves better when sorted. +// Send: Yes, Sync: Yes +#[derive(Clone)] +struct YY {} + +// Send: Yes, Sync: No +#[derive(Clone)] +struct YN { + _value: Cell, +} + +// Send: No, Sync: No +#[derive(Clone)] +struct NN { + _value: Rc, +} + +#[allow(dead_code)] +type BoxFutureSync = Pin + Send + Sync>>; +#[allow(dead_code)] +type BoxFutureSend = Pin + Send>>; +#[allow(dead_code)] +type BoxFuture = Pin>>; + +#[allow(dead_code)] +type BoxAsyncRead = Pin>; +#[allow(dead_code)] +type BoxAsyncSeek = Pin>; +#[allow(dead_code)] +type BoxAsyncWrite = Pin>; + +#[allow(dead_code)] +fn require_send(_t: &T) {} +#[allow(dead_code)] +fn require_sync(_t: &T) {} +#[allow(dead_code)] +fn require_unpin(_t: &T) {} + +#[allow(dead_code)] +struct Invalid; + +trait AmbiguousIfSend { + fn some_item(&self) {} +} +impl AmbiguousIfSend<()> for T {} +impl AmbiguousIfSend for T {} + +trait AmbiguousIfSync { + fn some_item(&self) {} +} +impl AmbiguousIfSync<()> for T {} +impl AmbiguousIfSync for T {} + +trait AmbiguousIfUnpin { + fn some_item(&self) {} +} +impl AmbiguousIfUnpin<()> for T {} +impl AmbiguousIfUnpin for T {} + +macro_rules! into_todo { + ($typ:ty) => {{ + let x: $typ = todo!(); + x + }}; +} + +macro_rules! async_assert_fn_send { + (Send & $(!)?Sync & $(!)?Unpin, $value:expr) => { + require_send(&$value); + }; + (!Send & $(!)?Sync & $(!)?Unpin, $value:expr) => { + AmbiguousIfSend::some_item(&$value); + }; +} + +macro_rules! async_assert_fn_sync { + ($(!)?Send & Sync & $(!)?Unpin, $value:expr) => { + require_sync(&$value); + }; + ($(!)?Send & !Sync & $(!)?Unpin, $value:expr) => { + AmbiguousIfSync::some_item(&$value); + }; +} + +macro_rules! async_assert_fn_unpin { + ($(!)?Send & $(!)?Sync & Unpin, $value:expr) => { + require_unpin(&$value); + }; + ($(!)?Send & $(!)?Sync & !Unpin, $value:expr) => { + AmbiguousIfUnpin::some_item(&$value); + }; +} + +macro_rules! async_assert_fn { + ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): $($tok:tt)*) => { + #[allow(unreachable_code)] + #[allow(unused_variables)] + const _: fn() = || { + let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); + async_assert_fn_send!($($tok)*, f); + async_assert_fn_sync!($($tok)*, f); + async_assert_fn_unpin!($($tok)*, f); + }; + }; +} + +async_assert_fn!( + esthri::upload(_, &str, &str, &Path, opts::EsthriPutOptParams): Send & !Sync & !Unpin +);