#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] use wasm_bindgen_test::wasm_bindgen_test as test; #[cfg(all(target_family = "wasm", not(target_os = "wasi")))] use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;
#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] use tokio::test as maybe_tokio_test;
use std::fmt; use std::sync::Arc; use tokio::sync::mpsc; use tokio::sync::mpsc::error::{TryRecvError, TrySendError}; use tokio_test::*;
#[cfg(not(target_family = "wasm"))] mod support { pub(crate) mod mpsc_stream;
}
#[allow(unused)] trait AssertSend: Send {} impl AssertSend for mpsc::Sender<i32> {} impl AssertSend for mpsc::Receiver<i32> {}
#[maybe_tokio_test] asyncfn send_recv_with_buffer() { let (tx, mut rx) = mpsc::channel::<i32>(16);
// Using poll_ready / try_send // let permit assert_ready_ok!(tx.reserve()); let permit = tx.reserve().await.unwrap();
permit.send(1);
// Without poll_ready
tx.try_send(2).unwrap();
drop(tx);
let val = rx.recv().await;
assert_eq!(val, Some(1));
let val = rx.recv().await;
assert_eq!(val, Some(2));
let val = rx.recv().await;
assert!(val.is_none());
}
#[tokio::test] #[cfg(feature = "full")] asyncfn reserve_disarm() { let (tx, mut rx) = mpsc::channel::<i32>(2); let tx1 = tx.clone(); let tx2 = tx.clone(); let tx3 = tx.clone(); let tx4 = tx;
// We should be able to `poll_ready` two handles without problem let permit1 = assert_ok!(tx1.reserve().await); let permit2 = assert_ok!(tx2.reserve().await);
// But a third should not be ready letmut r3 = tokio_test::task::spawn(tx3.reserve());
assert_pending!(r3.poll());
// Using one of the reserved slots should allow a new handle to become ready
permit1.send(1);
// We also need to receive for the slot to be free
assert!(!r3.is_woken());
rx.recv().await.unwrap(); // Now there's a free slot!
assert!(r3.is_woken());
assert!(!r4.is_woken());
// Dropping a permit should also open up a slot
drop(permit2);
assert!(r4.is_woken());
// recv_many will immediately return zero if the channel // is closed and no more messages are waiting
assert_eq!(0, rx.recv_many(&mut buffer, 4).await);
assert!(rx.recv().await.is_none());
}
letmut expected: Vec<String> = (0..limit)
.map(|x: usize| format!("{x}"))
.collect::<Vec<_>>(); for x in expected.clone() {
tx.send(x).await.unwrap()
}
tx.send("one more".to_string()).await.unwrap();
// Here `recv_many` receives all but the last value; // the initial capacity is adequate, so the buffer does // not increase in side.
assert_eq!(buffer.capacity(), rx.recv_many(&mut buffer, limit).await);
assert_eq!(expected, buffer);
assert_eq!(limit, buffer.capacity());
// Receive up more values:
assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
assert!(buffer.capacity() > limit);
expected.push("one more".to_string());
assert_eq!(expected, buffer);
// 'tx' is dropped, but `recv_many` is guaranteed not // to return 0 as the channel has outstanding permits
assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
expected.push("final".to_string());
assert_eq!(expected, buffer); // The channel is now closed and `recv_many` returns 0.
assert_eq!(0, rx.recv_many(&mut buffer, limit).await);
assert_eq!(expected, buffer);
}
letmut expected: Vec<String> = (0..limit)
.map(|x: usize| format!("{x}"))
.collect::<Vec<_>>(); for x in expected.clone() {
tx.send(x).unwrap()
}
tx.send("one more".to_string()).unwrap();
// Here `recv_many` receives all but the last value; // the initial capacity is adequate, so the buffer does // not increase in side.
assert_eq!(buffer.capacity(), rx.recv_many(&mut buffer, limit).await);
assert_eq!(expected, buffer);
assert_eq!(limit, buffer.capacity());
// Receive up more values:
assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
assert!(buffer.capacity() > limit);
expected.push("one more".to_string());
assert_eq!(expected, buffer);
// 'tx' is dropped, but `recv_many` is guaranteed not // to return 0 as the channel has outstanding permits
assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
expected.push("final".to_string());
assert_eq!(expected, buffer); // The channel is now closed and `recv_many` returns 0.
assert_eq!(0, rx.recv_many(&mut buffer, limit).await);
assert_eq!(expected, buffer);
}
// sender should be Debug even though T isn't Debug
is_debug(&tx); // same with Receiver
is_debug(&rx); // and sender should be Clone even though T isn't Clone
assert!(tx.clone().try_send(NoImpls).is_ok());
// sender should be Debug even though T isn't Debug
is_debug(&tx); // same with Receiver
is_debug(&rx); // and sender should be Clone even though T isn't Clone
assert!(tx.clone().send(NoImpls).is_ok());
#[maybe_tokio_test] asyncfn try_reserve_many_full() { // Reserve n capacity and send k messages for n in1..100 { for k in0..n { let (tx, mut rx) = mpsc::channel::<usize>(n); let permits = assert_ok!(tx.try_reserve_many(n));
match assert_err!(tx.try_reserve_many(1)) {
TrySendError::Full(..) => {}
_ => panic!(),
};
for permit in permits.take(k) {
permit.send(0);
} // We only used k permits on the n reserved
assert_eq!(tx.capacity(), n - k);
// We can reserve more permits
assert_ok!(tx.try_reserve_many(1));
// But not more than the current capacity match assert_err!(tx.try_reserve_many(n - k + 1)) {
TrySendError::Full(..) => {}
_ => panic!(),
};
for _i in0..k {
assert_eq!(rx.recv().await, Some(0));
}
// Now that we've received everything, capacity should be back to n
assert_eq!(tx.capacity(), n);
}
}
}
#[tokio::test] #[cfg(feature = "full")] asyncfn drop_permit_releases_permit() { // poll_ready reserves capacity, ensure that the capacity is released if tx // is dropped w/o sending a value. let (tx1, _rx) = mpsc::channel::<i32>(1); let tx2 = tx1.clone();
#[maybe_tokio_test] asyncfn drop_permit_iterator_releases_permits() { // poll_ready reserves capacity, ensure that the capacity is released if tx // is dropped w/o sending a value. for n in1..100 { let (tx1, _rx) = mpsc::channel::<i32>(n); let tx2 = tx1.clone();
let permits = assert_ok!(tx1.reserve_many(n).await);
#[test] #[should_panic = "there is no reactor running, must be called from the context of a Tokio 1.x runtime"] #[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding fn recv_timeout_panic() { use futures::future::FutureExt; use tokio::time::Duration;
let (tx, _rx) = mpsc::channel(5);
tx.send_timeout(10, Duration::from_secs(1)).now_or_never();
}
// Tests that channel `capacity` changes and `max_capacity` stays the same #[tokio::test] asyncfn test_tx_capacity() { let (tx, _rx) = mpsc::channel::<()>(10); // both capacities are same before
assert_eq!(tx.capacity(), 10);
assert_eq!(tx.max_capacity(), 10);
let _permit = tx.reserve().await.unwrap(); // after reserve, only capacity should drop by one
assert_eq!(tx.capacity(), 9);
assert_eq!(tx.max_capacity(), 10);
tx.send(()).await.unwrap(); // after send, capacity should drop by one again
assert_eq!(tx.capacity(), 8);
assert_eq!(tx.max_capacity(), 10);
}
#[tokio::test] asyncfn test_rx_is_closed_when_calling_close_with_sender() { // is_closed should return true after calling close but still has a sender let (_tx, mut rx) = mpsc::channel::<()>(10);
rx.close();
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_closed_when_dropping_all_senders() { // is_closed should return true after dropping all senders let (tx, rx) = mpsc::channel::<()>(10); let another_tx = tx.clone(); let task = tokio::spawn(asyncmove {
drop(another_tx);
});
drop(tx); let _ = task.await;
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_not_closed_when_there_are_senders() { // is_closed should return false when there is a sender let (_tx, rx) = mpsc::channel::<()>(10);
assert!(!rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_not_closed_when_there_are_senders_and_buffer_filled() { // is_closed should return false when there is a sender, even if enough messages have been sent to fill the channel let (tx, rx) = mpsc::channel(10); for i in0..10 {
assert!(tx.send(i).await.is_ok());
}
assert!(!rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_closed_when_there_are_no_senders_and_there_are_messages() { // is_closed should return true when there are messages in the buffer, but no senders let (tx, rx) = mpsc::channel(10); for i in0..10 {
assert!(tx.send(i).await.is_ok());
}
drop(tx);
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_closed_when_there_are_messages_and_close_is_called() { // is_closed should return true when there are messages in the buffer, and close is called let (tx, mut rx) = mpsc::channel(10); for i in0..10 {
assert!(tx.send(i).await.is_ok());
}
rx.close();
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_is_not_closed_when_there_are_permits_but_not_senders() { // is_closed should return false when there is a permit (but no senders) let (tx, rx) = mpsc::channel::<()>(10); let _permit = tx.reserve_owned().await.expect("Failed to reserve permit");
assert!(!rx.is_closed());
}
#[tokio::test] asyncfn test_rx_len_on_empty_channel_without_senders() { // when all senders are dropped, a "closed" value is added to the end of the linked list. // here we test that the "closed" value does not change the len of the channel.
let (tx, rx) = mpsc::channel::<()>(100);
drop(tx);
assert_eq!(rx.len(), 0);
}
#[tokio::test] asyncfn test_rx_len_on_filled_channel() { let (tx, rx) = mpsc::channel(100);
for i in0..100 {
assert!(tx.send(i).await.is_ok());
}
assert_eq!(rx.len(), 100);
}
#[tokio::test] asyncfn test_rx_len_on_filled_channel_without_senders() { let (tx, rx) = mpsc::channel(100);
for i in0..100 {
assert!(tx.send(i).await.is_ok());
}
drop(tx);
assert_eq!(rx.len(), 100);
}
#[tokio::test] asyncfn test_rx_len_when_consuming_all_messages() { let (tx, mut rx) = mpsc::channel(100);
for i in0..100 {
assert!(tx.send(i).await.is_ok());
assert_eq!(rx.len(), i + 1);
}
drop(tx);
for i in (0..100).rev() {
assert!(rx.recv().await.is_some());
assert_eq!(rx.len(), i);
}
}
#[tokio::test] asyncfn test_rx_unbounded_is_closed_when_calling_close_with_sender() { // is_closed should return true after calling close but still has a sender let (_tx, mut rx) = mpsc::unbounded_channel::<()>();
rx.close();
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_unbounded_is_closed_when_dropping_all_senders() { // is_closed should return true after dropping all senders let (tx, rx) = mpsc::unbounded_channel::<()>(); let another_tx = tx.clone(); let task = tokio::spawn(asyncmove {
drop(another_tx);
});
drop(tx); let _ = task.await;
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_unbounded_is_not_closed_when_there_are_senders() { // is_closed should return false when there is a sender let (_tx, rx) = mpsc::unbounded_channel::<()>();
assert!(!rx.is_closed());
}
#[tokio::test] asyncfn test_rx_unbounded_is_closed_when_there_are_no_senders_and_there_are_messages() { // is_closed should return true when there are messages in the buffer, but no senders let (tx, rx) = mpsc::unbounded_channel(); for i in0..10 {
assert!(tx.send(i).is_ok());
}
drop(tx);
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_unbounded_is_closed_when_there_are_messages_and_close_is_called() { // is_closed should return true when there are messages in the buffer, and close is called let (tx, mut rx) = mpsc::unbounded_channel(); for i in0..10 {
assert!(tx.send(i).is_ok());
}
rx.close();
assert!(rx.is_closed());
}
#[tokio::test] asyncfn test_rx_unbounded_len_on_empty_channel_without_senders() { // when all senders are dropped, a "closed" value is added to the end of the linked list. // here we test that the "closed" value does not change the len of the channel.
let (tx, rx) = mpsc::unbounded_channel::<()>();
drop(tx);
assert_eq!(rx.len(), 0);
}
#[tokio::test] asyncfn test_rx_unbounded_len_with_multiple_messages() { let (tx, rx) = mpsc::unbounded_channel();
for i in0..100 {
assert!(tx.send(i).is_ok());
}
assert_eq!(rx.len(), 100);
}
#[tokio::test] asyncfn test_rx_unbounded_len_with_multiple_messages_and_dropped_senders() { let (tx, rx) = mpsc::unbounded_channel();
for i in0..100 {
assert!(tx.send(i).is_ok());
}
drop(tx);
assert_eq!(rx.len(), 100);
}
#[tokio::test] asyncfn test_rx_unbounded_len_when_consuming_all_messages() { let (tx, mut rx) = mpsc::unbounded_channel();
for i in0..100 {
assert!(tx.send(i).is_ok());
assert_eq!(rx.len(), i + 1);
}
drop(tx);
for i in (0..100).rev() {
assert!(rx.recv().await.is_some());
assert_eq!(rx.len(), i);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.