Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,176 @@
|
||||
use dever_runtime::{
|
||||
channel::{Channel, Error},
|
||||
task::{Limits, Runtime},
|
||||
};
|
||||
use std::{
|
||||
future::{Future, poll_fn},
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
},
|
||||
task::Poll,
|
||||
};
|
||||
|
||||
fn runtime() -> Runtime {
|
||||
Runtime::new(Limits {
|
||||
threads: 2,
|
||||
workers: 1,
|
||||
tasks: 8,
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn pending(future: std::pin::Pin<&mut impl Future>) {
|
||||
let mut future = future;
|
||||
poll_fn(|context| {
|
||||
assert!(future.as_mut().poll(context).is_pending());
|
||||
Poll::Ready(())
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capacity_is_bounded() {
|
||||
for capacity in [-1, 0, 65537] {
|
||||
assert!(matches!(
|
||||
Channel::<i64>::new(capacity),
|
||||
Err(Error::Capacity)
|
||||
));
|
||||
}
|
||||
Channel::<i64>::new(1).unwrap();
|
||||
Channel::<i64>::new(65536).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backpressure_preserves_fifo_and_nullable_items() {
|
||||
runtime()
|
||||
.run(async |_| {
|
||||
let channel = Channel::new(1).unwrap();
|
||||
channel.send(Some(1)).await.unwrap();
|
||||
let mut sent = std::pin::pin!(channel.send(None));
|
||||
pending(sent.as_mut()).await;
|
||||
assert_eq!(channel.receive().await, Ok(Some(Some(1))));
|
||||
sent.await.unwrap();
|
||||
let alias = channel.clone();
|
||||
alias.close().await.unwrap();
|
||||
channel.close().await.unwrap();
|
||||
assert_eq!(channel.receive().await, Ok(Some(None)));
|
||||
assert_eq!(alias.receive().await, Ok(None));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn close_wakes_senders_and_all_receivers_without_discarding_queued_values() {
|
||||
runtime()
|
||||
.run(async |_| {
|
||||
let channel = Channel::new(1).unwrap();
|
||||
channel.send(1).await.unwrap();
|
||||
let mut sent = std::pin::pin!(channel.send(2));
|
||||
pending(sent.as_mut()).await;
|
||||
channel.close().await.unwrap();
|
||||
assert_eq!(sent.await, Err(Error::Closed));
|
||||
assert_eq!(channel.receive().await, Ok(Some(1)));
|
||||
assert_eq!(channel.receive().await, Ok(None));
|
||||
let empty = Channel::<i64>::new(1).unwrap();
|
||||
let mut first = std::pin::pin!(empty.receive());
|
||||
let mut second = std::pin::pin!(empty.receive());
|
||||
pending(first.as_mut()).await;
|
||||
pending(second.as_mut()).await;
|
||||
empty.close().await.unwrap();
|
||||
assert_eq!(first.await, Ok(None));
|
||||
assert_eq!(second.await, Ok(None));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelling_waiters_returns_reserved_capacity_and_items() {
|
||||
runtime()
|
||||
.run(async |_| {
|
||||
let channel = Channel::new(1).unwrap();
|
||||
channel.send(1).await.unwrap();
|
||||
{
|
||||
let mut sent = std::pin::pin!(channel.send(2));
|
||||
pending(sent.as_mut()).await;
|
||||
assert_eq!(channel.receive().await, Ok(Some(1)));
|
||||
}
|
||||
channel.send(3).await.unwrap();
|
||||
assert_eq!(channel.receive().await, Ok(Some(3)));
|
||||
{
|
||||
let mut received = std::pin::pin!(channel.receive());
|
||||
pending(received.as_mut()).await;
|
||||
channel.send(4).await.unwrap();
|
||||
}
|
||||
assert_eq!(channel.receive().await, Ok(Some(4)));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn producers_and_consumers_transfer_every_item_once() {
|
||||
runtime()
|
||||
.run(async |scope| {
|
||||
let channel = Channel::new(4).unwrap();
|
||||
let mut producers = Vec::new();
|
||||
let mut consumers = Vec::new();
|
||||
for start in [0, 64] {
|
||||
let sender = channel.clone();
|
||||
producers.push(
|
||||
scope
|
||||
.spawn_leaf(move || async move {
|
||||
for value in start..start + 64 {
|
||||
sender.send(value).await.unwrap();
|
||||
}
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
let channel = channel.clone();
|
||||
consumers.push(
|
||||
scope
|
||||
.spawn_leaf(move || async move {
|
||||
let mut values = Vec::new();
|
||||
while let Some(value) = channel.receive().await.unwrap() {
|
||||
values.push(value);
|
||||
}
|
||||
values
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
for task in producers {
|
||||
task.wait().await.unwrap();
|
||||
}
|
||||
channel.close().await.unwrap();
|
||||
let mut received = Vec::new();
|
||||
for task in consumers {
|
||||
received.extend(task.wait().await.unwrap());
|
||||
}
|
||||
received.sort();
|
||||
assert_eq!(received, (0..128).collect::<Vec<_>>());
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
struct Notice(Arc<AtomicUsize>);
|
||||
impl Drop for Notice {
|
||||
fn drop(&mut self) {
|
||||
self.0.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn last_alias_releases_nonclone_messages_once() {
|
||||
let drops = Arc::new(AtomicUsize::new(0));
|
||||
runtime()
|
||||
.run(async |_| {
|
||||
let channel = Channel::new(1).unwrap();
|
||||
channel.send(Notice(drops.clone())).await.unwrap();
|
||||
let alias = channel.clone();
|
||||
drop(channel);
|
||||
assert_eq!(drops.load(Ordering::SeqCst), 0);
|
||||
drop(alias);
|
||||
assert_eq!(drops.load(Ordering::SeqCst), 1);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
Reference in new issue
Block a user