use foundationdb::*; use futures::prelude::*; use std::pin::Pin; use std::task::{Context, Poll}; mod common; struct AbortingFuture { inner: F, polled: bool, } impl Future for AbortingFuture where T: Future + Unpin, { type Output = FdbResult; fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { // poll once only if !self.polled { self.polled = true; match Pin::new(&mut self.as_mut().inner).poll(cx) { Poll::Pending => (), _ => return Poll::Ready(Ok(false)), } } Poll::Ready(Ok(true)) } } #[test] fn test_future_discard() { let _guard = unsafe { foundationdb::boot() }; futures::executor::block_on(test_future_discard_async()).expect("failed to run"); } async fn test_future_discard_async() -> FdbResult<()> { // dropping a future while it's in the pending state should not crash let db = common::database().await?; let mut hit_pending = false; for _i in 0..=1000 { let hit_pending_step = db .transact_boxed_local( (), |trx, ()| { AbortingFuture { inner: trx.get(b"key", false), polled: false, } .boxed_local() }, TransactOption::default(), ) .await?; hit_pending = hit_pending || hit_pending_step; } assert!(hit_pending); Ok(()) }