arty 0.5.0

Single-threaded, thread-aware application runtime.
Documentation
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! A completed task's destructor is still part of task panic containment.

#![cfg(feature = "rt")]
#![cfg(test)]

mod panic_support;

mod support;

use std::marker::PhantomPinned;
use std::pin::Pin;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::task::{Context, Poll};

use panic_support::runtime;
use support::JoinHandleExt as _;
use thread_aware::Unaware;

testing_aids::init_tracing!();

struct ReadyDropPanic {
    drops: Arc<AtomicUsize>,
    _pinned: PhantomPinned,
}

impl Future for ReadyDropPanic {
    type Output = u32;

    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<u32> {
        Poll::Ready(42)
    }
}

impl Drop for ReadyDropPanic {
    fn drop(&mut self) {
        self.drops.fetch_add(1, Ordering::SeqCst);
        panic!("completed future destructor panic");
    }
}

#[test]
fn remote_completed_future_drop_is_a_join_error() {
    let runtime = runtime();
    let drops = Arc::new(AtomicUsize::new(0));
    let task = runtime
        .scheduler()
        .spawn_anywhere(Unaware(Arc::clone(&drops)), |_, Unaware(drops)| ReadyDropPanic {
            drops,
            _pinned: PhantomPinned,
        });
    assert!(task.join().unwrap_err().is_panic());
    assert_eq!(drops.load(Ordering::SeqCst), 1);
    assert_eq!(runtime.scheduler().spawn_anywhere((), |_, ()| async { 7 }).join().unwrap(), 7);
    runtime.stop().unwrap();
}

#[test]
fn borrowing_completed_future_drop_is_a_root_error() {
    use std::error::Error as _;

    let runtime = runtime();
    let drops = Arc::new(AtomicUsize::new(0));
    let captured = Arc::clone(&drops);
    let error = runtime
        .scheduler()
        .block_on(move |_| ReadyDropPanic {
            drops: captured,
            _pinned: PhantomPinned,
        })
        .unwrap_err();
    assert!(error.source().unwrap().downcast_ref::<arty::task::JoinError>().unwrap().is_panic());
    assert_eq!(drops.load(Ordering::SeqCst), 1);
    assert_eq!(runtime.scheduler().block_on(async |_| 7).unwrap(), 7);
    runtime.stop().unwrap();
}