kernal-api 0.1.21

Async OS HAL, profiling, symbolization, and allocator instrumentation
use kernal_api::async_engine::{channel, BlockingSendError, RuntimeBuilder, TryRecvError};
use std::time::Duration;

#[test]
fn blocking_sender_works_without_a_runtime_and_preserves_order() {
    let (sender, mut receiver) = channel(1);
    sender.blocking_send(1).unwrap();
    let (finished, completion) = std::sync::mpsc::channel();
    let worker = std::thread::spawn(move || {
        sender.blocking_send(2).unwrap();
        finished.send(()).unwrap();
    });
    assert!(completion.recv_timeout(Duration::from_millis(50)).is_err());
    assert_eq!(receiver.try_recv(), Ok(1));
    completion.recv_timeout(Duration::from_secs(2)).unwrap();
    worker.join().unwrap();
    assert_eq!(receiver.try_recv(), Ok(2));
    assert_eq!(receiver.try_recv(), Err(TryRecvError::Disconnected));
}

#[test]
fn closing_or_dropping_receiver_wakes_blocked_sender_with_its_value() {
    for close in [true, false] {
        let (sender, mut receiver) = channel(1);
        sender.blocking_send(1).unwrap();
        let (finished, completion) = std::sync::mpsc::channel();
        let worker = std::thread::spawn(move || {
            finished.send(sender.blocking_send(2)).unwrap();
        });
        assert!(completion.recv_timeout(Duration::from_millis(50)).is_err());
        if close {
            receiver.close();
            assert_eq!(receiver.try_recv(), Ok(1));
        } else {
            drop(receiver);
        }
        assert!(matches!(
            completion.recv_timeout(Duration::from_secs(2)).unwrap(),
            Err(BlockingSendError::Closed(2))
        ));
        worker.join().unwrap();
    }
}

#[test]
fn blocking_sender_rejects_async_context_without_enqueuing() {
    let runtime = RuntimeBuilder::current_thread()
        .enable_all()
        .build()
        .unwrap();
    let (sender, mut receiver) = channel(1);
    runtime.run(async {
        assert!(matches!(
            sender.blocking_send(7),
            Err(BlockingSendError::AsyncContext(7))
        ));
        assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
    });
    sender.blocking_send(8).unwrap();
    assert_eq!(receiver.try_recv(), Ok(8));
}