Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
339
vendor/flume/tests/after.rs
vendored
Normal file
339
vendor/flume/tests/after.rs
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
// //! Tests for the after channel flavor.
|
||||
|
||||
// #[macro_use]
|
||||
// extern crate crossbeam_channel;
|
||||
// extern crate crossbeam_utils;
|
||||
// extern crate rand;
|
||||
|
||||
// use std::sync::atomic::AtomicUsize;
|
||||
// use std::sync::atomic::Ordering;
|
||||
// use std::thread;
|
||||
// use std::time::{Duration, Instant};
|
||||
|
||||
// use crossbeam_channel::{after, Select, TryRecvError};
|
||||
// use crossbeam_utils::thread::scope;
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fire() {
|
||||
// let start = Instant::now();
|
||||
// let r = after(ms(50));
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// thread::sleep(ms(100));
|
||||
|
||||
// let fired = r.try_recv().unwrap();
|
||||
// assert!(start < fired);
|
||||
// assert!(fired - start >= ms(50));
|
||||
|
||||
// let now = Instant::now();
|
||||
// assert!(fired < now);
|
||||
// assert!(now - fired >= ms(50));
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
|
||||
// select! {
|
||||
// recv(r) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
|
||||
// select! {
|
||||
// recv(r) -> _ => panic!(),
|
||||
// recv(after(ms(200))) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn capacity() {
|
||||
// const COUNT: usize = 10;
|
||||
|
||||
// for i in 0..COUNT {
|
||||
// let r = after(ms(i as u64));
|
||||
// assert_eq!(r.capacity(), Some(1));
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn len_empty_full() {
|
||||
// let r = after(ms(50));
|
||||
|
||||
// assert_eq!(r.len(), 0);
|
||||
// assert_eq!(r.is_empty(), true);
|
||||
// assert_eq!(r.is_full(), false);
|
||||
|
||||
// thread::sleep(ms(100));
|
||||
|
||||
// assert_eq!(r.len(), 1);
|
||||
// assert_eq!(r.is_empty(), false);
|
||||
// assert_eq!(r.is_full(), true);
|
||||
|
||||
// r.try_recv().unwrap();
|
||||
|
||||
// assert_eq!(r.len(), 0);
|
||||
// assert_eq!(r.is_empty(), true);
|
||||
// assert_eq!(r.is_full(), false);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn try_recv() {
|
||||
// let r = after(ms(200));
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(100));
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(200));
|
||||
// assert!(r.try_recv().is_ok());
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(200));
|
||||
// assert!(r.try_recv().is_err());
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv() {
|
||||
// let start = Instant::now();
|
||||
// let r = after(ms(50));
|
||||
|
||||
// let fired = r.recv().unwrap();
|
||||
// assert!(start < fired);
|
||||
// assert!(fired - start >= ms(50));
|
||||
|
||||
// let now = Instant::now();
|
||||
// assert!(fired < now);
|
||||
// assert!(now - fired < fired - start);
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_timeout() {
|
||||
// let start = Instant::now();
|
||||
// let r = after(ms(200));
|
||||
|
||||
// assert!(r.recv_timeout(ms(100)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(100));
|
||||
// assert!(now - start <= ms(150));
|
||||
|
||||
// let fired = r.recv_timeout(ms(200)).unwrap();
|
||||
// assert!(fired - start >= ms(200));
|
||||
// assert!(fired - start <= ms(250));
|
||||
|
||||
// assert!(r.recv_timeout(ms(200)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(400));
|
||||
// assert!(now - start <= ms(450));
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_two() {
|
||||
// let r1 = after(ms(50));
|
||||
// let r2 = after(ms(50));
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// select! {
|
||||
// recv(r1) -> _ => {}
|
||||
// recv(r2) -> _ => {}
|
||||
// }
|
||||
// });
|
||||
// scope.spawn(|_| {
|
||||
// select! {
|
||||
// recv(r1) -> _ => {}
|
||||
// recv(r2) -> _ => {}
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_race() {
|
||||
// select! {
|
||||
// recv(after(ms(50))) -> _ => {}
|
||||
// recv(after(ms(100))) -> _ => panic!(),
|
||||
// }
|
||||
|
||||
// select! {
|
||||
// recv(after(ms(100))) -> _ => panic!(),
|
||||
// recv(after(ms(50))) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_default() {
|
||||
// const COUNT: usize = 10;
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(after(ms(0))) -> _ => {}
|
||||
// default => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(after(ms(100))) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn select() {
|
||||
// const THREADS: usize = 4;
|
||||
// const COUNT: usize = 1000;
|
||||
// const TIMEOUT_MS: u64 = 100;
|
||||
|
||||
// let v = (0..COUNT)
|
||||
// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2)))
|
||||
// .collect::<Vec<_>>();
|
||||
// let hits = AtomicUsize::new(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// for _ in 0..THREADS {
|
||||
// scope.spawn(|_| {
|
||||
// let v: Vec<&_> = v.iter().collect();
|
||||
|
||||
// loop {
|
||||
// let timeout = after(ms(TIMEOUT_MS));
|
||||
// let mut sel = Select::new();
|
||||
// for r in &v {
|
||||
// sel.recv(r);
|
||||
// }
|
||||
// let oper_timeout = sel.recv(&timeout);
|
||||
|
||||
// let oper = sel.select();
|
||||
// match oper.index() {
|
||||
// i if i == oper_timeout => {
|
||||
// oper.recv(&timeout).unwrap();
|
||||
// break;
|
||||
// }
|
||||
// i => {
|
||||
// oper.recv(&v[i]).unwrap();
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// assert_eq!(hits.load(Ordering::SeqCst), COUNT);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn ready() {
|
||||
// const THREADS: usize = 4;
|
||||
// const COUNT: usize = 1000;
|
||||
// const TIMEOUT_MS: u64 = 100;
|
||||
|
||||
// let v = (0..COUNT)
|
||||
// .map(|i| after(ms(i as u64 / TIMEOUT_MS / 2)))
|
||||
// .collect::<Vec<_>>();
|
||||
// let hits = AtomicUsize::new(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// for _ in 0..THREADS {
|
||||
// scope.spawn(|_| {
|
||||
// let v: Vec<&_> = v.iter().collect();
|
||||
|
||||
// loop {
|
||||
// let timeout = after(ms(TIMEOUT_MS));
|
||||
// let mut sel = Select::new();
|
||||
// for r in &v {
|
||||
// sel.recv(r);
|
||||
// }
|
||||
// let oper_timeout = sel.recv(&timeout);
|
||||
|
||||
// loop {
|
||||
// let i = sel.ready();
|
||||
// if i == oper_timeout {
|
||||
// timeout.try_recv().unwrap();
|
||||
// return;
|
||||
// } else if v[i].try_recv().is_ok() {
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// assert_eq!(hits.load(Ordering::SeqCst), COUNT);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_clone() {
|
||||
// const RUNS: usize = 1000;
|
||||
// const THREADS: usize = 10;
|
||||
// const COUNT: usize = 50;
|
||||
|
||||
// for i in 0..RUNS {
|
||||
// let r = after(ms(i as u64));
|
||||
|
||||
// scope(|scope| {
|
||||
// for _ in 0..THREADS {
|
||||
// scope.spawn(|_| {
|
||||
// let r = r.clone();
|
||||
// let _ = r.try_recv();
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// drop(r.clone());
|
||||
// thread::yield_now();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness() {
|
||||
// const COUNT: usize = 1000;
|
||||
|
||||
// for &dur in &[0, 1] {
|
||||
// let mut hits = [0usize; 2];
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(after(ms(dur))) -> _ => hits[0] += 1,
|
||||
// recv(after(ms(dur))) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness_duplicates() {
|
||||
// const COUNT: usize = 1000;
|
||||
|
||||
// for &dur in &[0, 1] {
|
||||
// let mut hits = [0usize; 5];
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// let r = after(ms(dur));
|
||||
// select! {
|
||||
// recv(r) -> _ => hits[0] += 1,
|
||||
// recv(r) -> _ => hits[1] += 1,
|
||||
// recv(r) -> _ => hits[2] += 1,
|
||||
// recv(r) -> _ => hits[3] += 1,
|
||||
// recv(r) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
// }
|
657
vendor/flume/tests/array.rs
vendored
Normal file
657
vendor/flume/tests/array.rs
vendored
Normal file
@ -0,0 +1,657 @@
|
||||
//! Tests for the array channel flavor.
|
||||
|
||||
extern crate crossbeam_utils;
|
||||
extern crate rand;
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use flume::{bounded, Receiver};
|
||||
use flume::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use flume::{SendError, SendTimeoutError, TrySendError};
|
||||
use crossbeam_utils::thread::scope;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
fn ms(ms: u64) -> Duration {
|
||||
Duration::from_millis(ms)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let (s, r) = bounded(1);
|
||||
s.send(7).unwrap();
|
||||
assert_eq!(r.try_recv(), Ok(7));
|
||||
|
||||
s.send(8).unwrap();
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capacity() {
|
||||
for i in 1..10 {
|
||||
let (s, r) = bounded::<()>(i);
|
||||
assert_eq!(s.capacity(), Some(i));
|
||||
assert_eq!(r.capacity(), Some(i));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len_empty_full() {
|
||||
let (s, r) = bounded(2);
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(s.is_empty(), true);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r.is_full(), false);
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert_eq!(s.is_empty(), false);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 1);
|
||||
assert_eq!(r.is_empty(), false);
|
||||
assert_eq!(r.is_full(), false);
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 2);
|
||||
assert_eq!(s.is_empty(), false);
|
||||
assert_eq!(s.is_full(), true);
|
||||
assert_eq!(r.len(), 2);
|
||||
assert_eq!(r.is_empty(), false);
|
||||
assert_eq!(r.is_full(), true);
|
||||
|
||||
r.recv().unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert_eq!(s.is_empty(), false);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 1);
|
||||
assert_eq!(r.is_empty(), false);
|
||||
assert_eq!(r.is_full(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_recv() {
|
||||
let (s, r) = bounded(100);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.try_recv(), Ok(7));
|
||||
thread::sleep(ms(500));
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv() {
|
||||
let (s, r) = bounded(100);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv(), Ok(7));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(9));
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
s.send(8).unwrap();
|
||||
s.send(9).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_timeout() {
|
||||
let (s, r) = bounded::<i32>(100);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
|
||||
assert_eq!(
|
||||
r.recv_timeout(ms(1000)),
|
||||
Err(RecvTimeoutError::Disconnected)
|
||||
);
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_send() {
|
||||
let (s, r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(s.try_send(1), Ok(()));
|
||||
assert_eq!(s.try_send(2), Err(TrySendError::Full(2)));
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(s.try_send(3), Ok(()));
|
||||
thread::sleep(ms(500));
|
||||
assert_eq!(s.try_send(4), Err(TrySendError::Disconnected(4)));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.try_recv(), Ok(1));
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
assert_eq!(r.recv(), Ok(3));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send() {
|
||||
let (s, r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
s.send(7).unwrap();
|
||||
thread::sleep(ms(1000));
|
||||
s.send(8).unwrap();
|
||||
thread::sleep(ms(1000));
|
||||
s.send(9).unwrap();
|
||||
thread::sleep(ms(1000));
|
||||
s.send(10).unwrap();
|
||||
});
|
||||
scope.spawn(|_| {
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.recv(), Ok(7));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
assert_eq!(r.recv(), Ok(9));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_timeout() {
|
||||
let (s, r) = bounded(2);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(s.send_timeout(1, ms(1000)), Ok(()));
|
||||
assert_eq!(s.send_timeout(2, ms(1000)), Ok(()));
|
||||
assert_eq!(
|
||||
s.send_timeout(3, ms(500)),
|
||||
Err(SendTimeoutError::Timeout(3))
|
||||
);
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(s.send_timeout(4, ms(1000)), Ok(()));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(s.send(5), Err(SendError(5)));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(1));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(2));
|
||||
assert_eq!(r.recv(), Ok(4));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_after_disconnect() {
|
||||
let (s, r) = bounded(100);
|
||||
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
s.send(3).unwrap();
|
||||
|
||||
drop(r);
|
||||
|
||||
assert_eq!(s.send(4), Err(SendError(4)));
|
||||
assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5)));
|
||||
assert_eq!(
|
||||
s.send_timeout(6, ms(500)),
|
||||
Err(SendTimeoutError::Disconnected(6))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_after_disconnect() {
|
||||
let (s, r) = bounded(100);
|
||||
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
s.send(3).unwrap();
|
||||
|
||||
drop(s);
|
||||
|
||||
assert_eq!(r.recv(), Ok(1));
|
||||
assert_eq!(r.recv(), Ok(2));
|
||||
assert_eq!(r.recv(), Ok(3));
|
||||
assert!(r.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len() {
|
||||
const COUNT: usize = 25_000;
|
||||
const CAP: usize = 1000;
|
||||
|
||||
let (s, r) = bounded(CAP);
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
|
||||
for _ in 0..CAP / 10 {
|
||||
for i in 0..50 {
|
||||
s.send(i).unwrap();
|
||||
assert_eq!(s.len(), i + 1);
|
||||
}
|
||||
|
||||
for i in 0..50 {
|
||||
r.recv().unwrap();
|
||||
assert_eq!(r.len(), 50 - i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
|
||||
for i in 0..CAP {
|
||||
s.send(i).unwrap();
|
||||
assert_eq!(s.len(), i + 1);
|
||||
}
|
||||
|
||||
for _ in 0..CAP {
|
||||
r.recv().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(r.recv(), Ok(i));
|
||||
let len = r.len();
|
||||
assert!(len <= CAP);
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
let len = s.len();
|
||||
assert!(len <= CAP);
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_wakes_sender() {
|
||||
let (s, r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(s.send(()), Ok(()));
|
||||
assert_eq!(s.send(()), Err(SendError(())));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(r);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_wakes_receiver() {
|
||||
let (s, r) = bounded::<()>(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let (s, r) = bounded(3);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(r.recv(), Ok(i));
|
||||
}
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
let (s, r) = bounded::<usize>(3);
|
||||
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
|
||||
|
||||
scope(|scope| {
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..COUNT {
|
||||
let n = r.recv().unwrap();
|
||||
v[n].fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for c in v {
|
||||
assert_eq!(c.load(Ordering::SeqCst), THREADS);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_oneshot() {
|
||||
const COUNT: usize = 10_000;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (s, r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| r.recv().unwrap());
|
||||
scope.spawn(|_| s.send(0).unwrap());
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_iter() {
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let (request_s, request_r) = bounded(1);
|
||||
let (response_s, response_r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
for x in response_r.try_iter() {
|
||||
count += x;
|
||||
if count == COUNT {
|
||||
return;
|
||||
}
|
||||
}
|
||||
request_s.send(()).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
for _ in request_r.iter() {
|
||||
if response_s.send(1).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_timeout_two_threads() {
|
||||
const COUNT: usize = 100;
|
||||
|
||||
let (s, r) = bounded(2);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
loop {
|
||||
if let Ok(()) = s.send_timeout(i, ms(10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
loop {
|
||||
if let Ok(x) = r.recv_timeout(ms(10)) {
|
||||
assert_eq!(x, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drops() {
|
||||
const RUNS: usize = 100;
|
||||
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct DropCounter;
|
||||
|
||||
impl Drop for DropCounter {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for _ in 0..RUNS {
|
||||
let steps = rng.gen_range(0..10_000);
|
||||
let additional = rng.gen_range(0..50);
|
||||
|
||||
DROPS.store(0, Ordering::SeqCst);
|
||||
let (s, r) = bounded::<DropCounter>(50);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
r.recv().unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
s.send(DropCounter).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for _ in 0..additional {
|
||||
s.send(DropCounter).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
|
||||
drop(s);
|
||||
drop(r);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linearizable() {
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
let (s, r) = bounded(THREADS);
|
||||
|
||||
scope(|scope| {
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..COUNT {
|
||||
s.send(0).unwrap();
|
||||
r.try_recv().unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn fairness() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = bounded::<()>(COUNT);
|
||||
// let (s2, r2) = bounded::<()>(COUNT);
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// s1.send(()).unwrap();
|
||||
// s2.send(()).unwrap();
|
||||
// }
|
||||
|
||||
// let mut hits = [0usize; 2];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r1) -> _ => hits[0] += 1,
|
||||
// recv(r2) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness_duplicates() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s, r) = bounded::<()>(COUNT);
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// s.send(()).unwrap();
|
||||
// }
|
||||
|
||||
// let mut hits = [0usize; 5];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r) -> _ => hits[0] += 1,
|
||||
// recv(r) -> _ => hits[1] += 1,
|
||||
// recv(r) -> _ => hits[2] += 1,
|
||||
// recv(r) -> _ => hits[3] += 1,
|
||||
// recv(r) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_in_send() {
|
||||
// let (s, _r) = bounded(1);
|
||||
// s.send(()).unwrap();
|
||||
|
||||
// #[allow(unreachable_code)]
|
||||
// {
|
||||
// select! {
|
||||
// send(s, panic!()) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// let (s, r) = bounded(2);
|
||||
// s.send(()).unwrap();
|
||||
|
||||
// select! {
|
||||
// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn channel_through_channel() {
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
type T = Box<dyn Any + Send>;
|
||||
|
||||
let (s, r) = bounded::<T>(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut s = s;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (new_s, new_r) = bounded(1);
|
||||
let new_r: T = Box::new(Some(new_r));
|
||||
|
||||
s.send(new_r).unwrap();
|
||||
s = new_s;
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(move |_| {
|
||||
let mut r = r;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
r = r
|
||||
.recv()
|
||||
.unwrap()
|
||||
.downcast_mut::<Option<Receiver<T>>>()
|
||||
.unwrap()
|
||||
.take()
|
||||
.unwrap()
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
276
vendor/flume/tests/async.rs
vendored
Normal file
276
vendor/flume/tests/async.rs
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
#[cfg(feature = "async")]
|
||||
use {
|
||||
flume::*,
|
||||
futures::{stream::FuturesUnordered, StreamExt, TryFutureExt, Future},
|
||||
futures::task::{Context, Waker, Poll},
|
||||
async_std::prelude::FutureExt,
|
||||
std::{time::Duration, sync::{atomic::{AtomicUsize, Ordering}, Arc}},
|
||||
};
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#async_recv() {
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
tx.send(42u32).unwrap();
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
assert_eq!(rx.recv_async().await.unwrap(), 42);
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#async_send() {
|
||||
let (tx, rx) = bounded(1);
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
assert_eq!(rx.recv(), Ok(42));
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
tx.send_async(42u32).await.unwrap();
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#async_recv_disconnect() {
|
||||
let (tx, rx) = bounded::<i32>(0);
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
drop(tx)
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
assert_eq!(rx.recv_async().await, Err(RecvError::Disconnected));
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#async_send_disconnect() {
|
||||
let (tx, rx) = bounded(0);
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
drop(rx)
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
assert_eq!(tx.send_async(42u32).await, Err(SendError(42)));
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#async_recv_drop_recv() {
|
||||
let (tx, rx) = bounded::<i32>(10);
|
||||
|
||||
let recv_fut = rx.recv_async();
|
||||
|
||||
async_std::task::block_on(async {
|
||||
let res = async_std::future::timeout(std::time::Duration::from_millis(500), rx.recv_async()).await;
|
||||
assert!(res.is_err());
|
||||
});
|
||||
|
||||
let rx2 = rx.clone();
|
||||
let t = std::thread::spawn(move || {
|
||||
async_std::task::block_on(async {
|
||||
rx2.recv_async().await
|
||||
})
|
||||
});
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
tx.send(42).unwrap();
|
||||
|
||||
drop(recv_fut);
|
||||
|
||||
assert_eq!(t.join().unwrap(), Ok(42))
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn r#async_send_1_million_no_drop_or_reorder() {
|
||||
#[derive(Debug)]
|
||||
enum Message {
|
||||
Increment {
|
||||
old: u64,
|
||||
},
|
||||
ReturnCount,
|
||||
}
|
||||
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
let t = async_std::task::spawn(async move {
|
||||
let mut count = 0u64;
|
||||
|
||||
while let Ok(Message::Increment { old }) = rx.recv_async().await {
|
||||
assert_eq!(old, count);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
count
|
||||
});
|
||||
|
||||
for next in 0..1_000_000 {
|
||||
tx.send(Message::Increment { old: next }).unwrap();
|
||||
}
|
||||
|
||||
tx.send(Message::ReturnCount).unwrap();
|
||||
|
||||
let count = t.await;
|
||||
assert_eq!(count, 1_000_000)
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn parallel_async_receivers() {
|
||||
let (tx, rx) = flume::unbounded();
|
||||
let send_fut = async move {
|
||||
let n_sends: usize = 100000;
|
||||
for _ in 0..n_sends {
|
||||
tx.send_async(()).await.unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
async_std::task::spawn(
|
||||
send_fut
|
||||
.timeout(Duration::from_secs(5))
|
||||
.map_err(|_| panic!("Send timed out!"))
|
||||
);
|
||||
|
||||
let mut futures_unordered = (0..250)
|
||||
.map(|_| async {
|
||||
while let Ok(()) = rx.recv_async().await
|
||||
/* rx.recv() is OK */
|
||||
{}
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>();
|
||||
|
||||
let recv_fut = async {
|
||||
while futures_unordered.next().await.is_some() {}
|
||||
};
|
||||
|
||||
recv_fut
|
||||
.timeout(Duration::from_secs(5))
|
||||
.map_err(|_| panic!("Receive timed out!"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("recv end");
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn change_waker() {
|
||||
let (tx, rx) = flume::bounded(1);
|
||||
tx.send(()).unwrap();
|
||||
|
||||
struct DebugWaker(Arc<AtomicUsize>, Waker);
|
||||
|
||||
impl DebugWaker {
|
||||
fn new() -> Self {
|
||||
let woken = Arc::new(AtomicUsize::new(0));
|
||||
let woken_cloned = woken.clone();
|
||||
let waker = waker_fn::waker_fn(move || {
|
||||
woken.fetch_add(1, Ordering::SeqCst);
|
||||
});
|
||||
DebugWaker(woken_cloned, waker)
|
||||
}
|
||||
|
||||
fn woken(&self) -> usize {
|
||||
self.0.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn ctx(&self) -> Context {
|
||||
Context::from_waker(&self.1)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the waker is correctly updated when sending tasks change their wakers
|
||||
{
|
||||
let send_fut = tx.send_async(());
|
||||
futures::pin_mut!(send_fut);
|
||||
|
||||
let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new());
|
||||
|
||||
// Set the waker to waker1
|
||||
assert_eq!(send_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending);
|
||||
|
||||
// Change the waker to waker2
|
||||
assert_eq!(send_fut.poll(&mut waker2.ctx()), Poll::Pending);
|
||||
|
||||
// Wake the future
|
||||
rx.recv().unwrap();
|
||||
|
||||
// Check that waker2 was woken and waker1 was not
|
||||
assert_eq!(waker1.woken(), 0);
|
||||
assert_eq!(waker2.woken(), 1);
|
||||
}
|
||||
|
||||
// Check that the waker is correctly updated when receiving tasks change their wakers
|
||||
{
|
||||
rx.recv().unwrap();
|
||||
let recv_fut = rx.recv_async();
|
||||
futures::pin_mut!(recv_fut);
|
||||
|
||||
let (waker1, waker2) = (DebugWaker::new(), DebugWaker::new());
|
||||
|
||||
// Set the waker to waker1
|
||||
assert_eq!(recv_fut.as_mut().poll(&mut waker1.ctx()), Poll::Pending);
|
||||
|
||||
// Change the waker to waker2
|
||||
assert_eq!(recv_fut.poll(&mut waker2.ctx()), Poll::Pending);
|
||||
|
||||
// Wake the future
|
||||
tx.send(()).unwrap();
|
||||
|
||||
// Check that waker2 was woken and waker1 was not
|
||||
assert_eq!(waker1.woken(), 0);
|
||||
assert_eq!(waker2.woken(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn spsc_single_threaded_value_ordering() {
|
||||
async fn test() {
|
||||
let (tx, rx) = flume::bounded(4);
|
||||
tokio::select! {
|
||||
_ = producer(tx) => {},
|
||||
_ = consumer(rx) => {},
|
||||
}
|
||||
}
|
||||
|
||||
async fn producer(tx: flume::Sender<usize>) {
|
||||
for i in 0..100 {
|
||||
tx.send_async(i).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
async fn consumer(rx: flume::Receiver<usize>) {
|
||||
let mut expected = 0;
|
||||
while let Ok(value) = rx.recv_async().await {
|
||||
assert_eq!(value, expected);
|
||||
expected += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let rt = tokio::runtime::Builder::new_current_thread().build().unwrap();
|
||||
rt.block_on(test());
|
||||
}
|
428
vendor/flume/tests/basic.rs
vendored
Normal file
428
vendor/flume/tests/basic.rs
vendored
Normal file
@ -0,0 +1,428 @@
|
||||
use std::time::{Instant, Duration};
|
||||
use flume::*;
|
||||
|
||||
#[test]
|
||||
fn send_recv() {
|
||||
let (tx, rx) = unbounded();
|
||||
for i in 0..1000 { tx.send(i).unwrap(); }
|
||||
for i in 0..1000 { assert_eq!(rx.try_recv().unwrap(), i); }
|
||||
assert!(rx.try_recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter() {
|
||||
let (tx, rx) = unbounded();
|
||||
for i in 0..1000 { tx.send(i).unwrap(); }
|
||||
drop(tx);
|
||||
assert_eq!(rx.iter().sum::<u32>(), (0..1000).sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_iter() {
|
||||
let (tx, rx) = unbounded();
|
||||
for i in 0..1000 { tx.send(i).unwrap(); }
|
||||
assert_eq!(rx.try_iter().sum::<u32>(), (0..1000).sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_threaded() {
|
||||
let (tx, rx) = unbounded();
|
||||
for i in 0..1000 {
|
||||
let tx = tx.clone();
|
||||
std::thread::spawn(move || tx.send(i).unwrap());
|
||||
}
|
||||
drop(tx);
|
||||
assert_eq!(rx.iter().sum::<u32>(), (0..1000).sum());
|
||||
}
|
||||
|
||||
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
|
||||
#[test]
|
||||
fn send_timeout() {
|
||||
let dur = Duration::from_millis(350);
|
||||
let max_error = Duration::from_millis(5);
|
||||
let dur_min = dur.checked_sub(max_error).unwrap();
|
||||
let dur_max = dur.checked_add(max_error).unwrap();
|
||||
|
||||
let (tx, rx) = bounded(1);
|
||||
|
||||
assert!(tx.send_timeout(42, dur).is_ok());
|
||||
|
||||
let then = Instant::now();
|
||||
assert!(tx.send_timeout(43, dur).is_err());
|
||||
let now = Instant::now();
|
||||
|
||||
let this = now.duration_since(then);
|
||||
if !(dur_min < this && this < dur_max) {
|
||||
panic!("timeout exceeded: {:?}", this);
|
||||
}
|
||||
|
||||
assert_eq!(rx.drain().count(), 1);
|
||||
|
||||
drop(rx);
|
||||
|
||||
assert!(tx.send_timeout(42, Duration::from_millis(350)).is_err());
|
||||
}
|
||||
|
||||
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
|
||||
#[test]
|
||||
fn recv_timeout() {
|
||||
let dur = Duration::from_millis(350);
|
||||
let max_error = Duration::from_millis(5);
|
||||
let dur_min = dur.checked_sub(max_error).unwrap();
|
||||
let dur_max = dur.checked_add(max_error).unwrap();
|
||||
|
||||
let (tx, rx) = unbounded();
|
||||
let then = Instant::now();
|
||||
assert!(rx.recv_timeout(dur).is_err());
|
||||
let now = Instant::now();
|
||||
|
||||
let this = now.duration_since(then);
|
||||
if !(dur_min < this && this < dur_max) {
|
||||
panic!("timeout exceeded: {:?}", this);
|
||||
}
|
||||
|
||||
tx.send(42).unwrap();
|
||||
assert_eq!(rx.recv_timeout(dur), Ok(42));
|
||||
assert!(Instant::now().duration_since(now) < max_error);
|
||||
}
|
||||
|
||||
#[cfg_attr(any(target_os = "macos", windows), ignore)] // FIXME #41
|
||||
#[test]
|
||||
fn recv_deadline() {
|
||||
let dur = Duration::from_millis(350);
|
||||
let max_error = Duration::from_millis(5);
|
||||
let dur_min = dur.checked_sub(max_error).unwrap();
|
||||
let dur_max = dur.checked_add(max_error).unwrap();
|
||||
|
||||
let (tx, rx) = unbounded();
|
||||
let then = Instant::now();
|
||||
assert!(rx.recv_deadline(then.checked_add(dur).unwrap()).is_err());
|
||||
let now = Instant::now();
|
||||
|
||||
let this = now.duration_since(then);
|
||||
if !(dur_min < this && this < dur_max) {
|
||||
panic!("timeout exceeded: {:?}", this);
|
||||
}
|
||||
|
||||
tx.send(42).unwrap();
|
||||
assert_eq!(rx.recv_deadline(now.checked_add(dur).unwrap()), Ok(42));
|
||||
assert!(Instant::now().duration_since(now) < max_error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_timeout_missed_send() {
|
||||
let (tx, rx) = bounded(10);
|
||||
|
||||
assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());
|
||||
|
||||
tx.send(42).unwrap();
|
||||
|
||||
assert_eq!(rx.recv(), Ok(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_tx() {
|
||||
let (tx, rx) = unbounded::<()>();
|
||||
drop(tx);
|
||||
assert!(rx.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_rx() {
|
||||
let (tx, rx) = unbounded();
|
||||
drop(rx);
|
||||
assert!(tx.send(0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain() {
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
for i in 0..100 {
|
||||
tx.send(i).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(rx.drain().sum::<u32>(), (0..100).sum());
|
||||
|
||||
for i in 0..100 {
|
||||
tx.send(i).unwrap();
|
||||
}
|
||||
|
||||
for i in 0..100 {
|
||||
tx.send(i).unwrap();
|
||||
}
|
||||
|
||||
rx.recv().unwrap();
|
||||
|
||||
(1u32..100).chain(0..100).zip(rx).for_each(|(l, r)| assert_eq!(l, r));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_send() {
|
||||
let (tx, rx) = bounded(5);
|
||||
|
||||
for i in 0..5 {
|
||||
tx.try_send(i).unwrap();
|
||||
}
|
||||
|
||||
assert!(tx.try_send(42).is_err());
|
||||
|
||||
assert_eq!(rx.recv(), Ok(0));
|
||||
|
||||
assert_eq!(tx.try_send(42), Ok(()));
|
||||
|
||||
assert_eq!(rx.recv(), Ok(1));
|
||||
drop(rx);
|
||||
|
||||
assert!(tx.try_send(42).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_bounded() {
|
||||
let (tx, rx) = bounded(5);
|
||||
|
||||
for _ in 0..5 {
|
||||
tx.send(42).unwrap();
|
||||
}
|
||||
|
||||
let _ = rx.recv().unwrap();
|
||||
|
||||
tx.send(42).unwrap();
|
||||
|
||||
assert!(tx.try_send(42).is_err());
|
||||
|
||||
rx.drain();
|
||||
|
||||
let mut ts = Vec::new();
|
||||
for _ in 0..100 {
|
||||
let tx = tx.clone();
|
||||
ts.push(std::thread::spawn(move || {
|
||||
for i in 0..10000 {
|
||||
tx.send(i).unwrap();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
drop(tx);
|
||||
|
||||
assert_eq!(rx.iter().sum::<u64>(), (0..10000).sum::<u64>() * 100);
|
||||
|
||||
for t in ts {
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
assert!(rx.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rendezvous() {
|
||||
let (tx, rx) = bounded(0);
|
||||
|
||||
for i in 0..5 {
|
||||
let tx = tx.clone();
|
||||
let t = std::thread::spawn(move || {
|
||||
assert!(tx.try_send(()).is_err());
|
||||
|
||||
let then = Instant::now();
|
||||
tx.send(()).unwrap();
|
||||
let now = Instant::now();
|
||||
|
||||
assert!(now.duration_since(then) > Duration::from_millis(100), "iter = {}", i);
|
||||
});
|
||||
|
||||
std::thread::sleep(Duration::from_millis(1000));
|
||||
rx.recv().unwrap();
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hydra() {
|
||||
let thread_num = 32;
|
||||
let msg_num = 1000;
|
||||
|
||||
let (main_tx, main_rx) = unbounded::<()>();
|
||||
|
||||
let mut txs = Vec::new();
|
||||
for _ in 0..thread_num {
|
||||
let main_tx = main_tx.clone();
|
||||
let (tx, rx) = unbounded();
|
||||
txs.push(tx);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
for msg in rx.iter() {
|
||||
main_tx.send(msg).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
drop(main_tx);
|
||||
|
||||
for _ in 0..10 {
|
||||
for tx in &txs {
|
||||
for _ in 0..msg_num {
|
||||
tx.send(Default::default()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..thread_num {
|
||||
for _ in 0..msg_num {
|
||||
main_rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop(txs);
|
||||
assert!(main_rx.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn robin() {
|
||||
let thread_num = 32;
|
||||
let msg_num = 10;
|
||||
|
||||
let (mut main_tx, main_rx) = bounded::<()>(1);
|
||||
|
||||
for _ in 0..thread_num {
|
||||
let (mut tx, rx) = bounded(100);
|
||||
std::mem::swap(&mut tx, &mut main_tx);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
for msg in rx.iter() {
|
||||
tx.send(msg).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for _ in 0..10 {
|
||||
let main_tx = main_tx.clone();
|
||||
std::thread::spawn(move || {
|
||||
for _ in 0..msg_num {
|
||||
main_tx.send(Default::default()).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
for _ in 0..msg_num {
|
||||
main_rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "select")]
|
||||
#[test]
|
||||
fn select_general() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Foo(usize);
|
||||
|
||||
let (tx0, rx0) = bounded(1);
|
||||
let (tx1, rx1) = unbounded();
|
||||
|
||||
for (i, t) in vec![tx0.clone(), tx1].into_iter().enumerate() {
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
let _ = t.send(Foo(i));
|
||||
});
|
||||
}
|
||||
|
||||
let x = Selector::new()
|
||||
.recv(&rx0, |x| x)
|
||||
.recv(&rx1, |x| x)
|
||||
.wait()
|
||||
.unwrap();
|
||||
|
||||
if x == Foo(0) {
|
||||
assert!(rx1.recv().unwrap() == Foo(1));
|
||||
} else {
|
||||
assert!(rx0.recv().unwrap() == Foo(0));
|
||||
}
|
||||
|
||||
tx0.send(Foo(42)).unwrap();
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
assert_eq!(rx0.recv().unwrap(), Foo(42));
|
||||
assert_eq!(rx0.recv().unwrap(), Foo(43));
|
||||
|
||||
});
|
||||
|
||||
Selector::new()
|
||||
.send(&tx0, Foo(43), |x| x)
|
||||
.wait()
|
||||
.unwrap();
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
struct MessageWithoutDebug(u32);
|
||||
|
||||
#[test]
|
||||
// This is a 'does it build' test, to make sure that the error types can turn
|
||||
// into a std::error::Error without requiring the payload (which is not used
|
||||
// there) to impl Debug.
|
||||
fn std_error_without_debug() {
|
||||
let (tx, rx) = unbounded::<MessageWithoutDebug>();
|
||||
|
||||
match tx.send(MessageWithoutDebug(1)) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
|
||||
match rx.recv() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
|
||||
match tx.try_send(MessageWithoutDebug(2)) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
|
||||
match rx.try_recv() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
|
||||
match tx.send_timeout(MessageWithoutDebug(3), Duration::from_secs(1000000)) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
|
||||
match rx.recv_timeout(Duration::from_secs(10000000)) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
let _std_err: &dyn std::error::Error = &e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weak_close() {
|
||||
let (tx, rx) = unbounded::<()>();
|
||||
let weak = tx.downgrade();
|
||||
drop(tx);
|
||||
assert!(weak.upgrade().is_none());
|
||||
assert!(rx.is_disconnected());
|
||||
assert!(rx.try_recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weak_upgrade() {
|
||||
let (tx, rx) = unbounded();
|
||||
let weak = tx.downgrade();
|
||||
let tx2 = weak.upgrade().unwrap();
|
||||
drop(tx);
|
||||
assert!(!rx.is_disconnected());
|
||||
tx2.send(()).unwrap();
|
||||
assert!(rx.try_recv().is_ok());
|
||||
}
|
57
vendor/flume/tests/check_same_channel.rs
vendored
Normal file
57
vendor/flume/tests/check_same_channel.rs
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#[test]
|
||||
fn same_sender() {
|
||||
let (tx1, _rx) = flume::unbounded::<()>();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
assert!(tx1.same_channel(&tx2));
|
||||
|
||||
let (tx3, _rx) = flume::unbounded::<()>();
|
||||
|
||||
assert!(!tx1.same_channel(&tx3));
|
||||
assert!(!tx2.same_channel(&tx3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_receiver() {
|
||||
let (_tx, rx1) = flume::unbounded::<()>();
|
||||
let rx2 = rx1.clone();
|
||||
|
||||
assert!(rx1.same_channel(&rx2));
|
||||
|
||||
let (_tx, rx3) = flume::unbounded::<()>();
|
||||
|
||||
assert!(!rx1.same_channel(&rx3));
|
||||
assert!(!rx2.same_channel(&rx3));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn same_send_sink() {
|
||||
let (tx1, _rx) = flume::unbounded::<()>();
|
||||
let tx1 = tx1.into_sink();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
assert!(tx1.same_channel(&tx2));
|
||||
|
||||
let (tx3, _rx) = flume::unbounded::<()>();
|
||||
let tx3 = tx3.into_sink();
|
||||
|
||||
assert!(!tx1.same_channel(&tx3));
|
||||
assert!(!tx2.same_channel(&tx3));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn same_recv_stream() {
|
||||
let (_tx, rx1) = flume::unbounded::<()>();
|
||||
let rx1 = rx1.into_stream();
|
||||
let rx2 = rx1.clone();
|
||||
|
||||
assert!(rx1.same_channel(&rx2));
|
||||
|
||||
let (_tx, rx3) = flume::unbounded::<()>();
|
||||
let rx3 = rx3.into_stream();
|
||||
|
||||
assert!(!rx1.same_channel(&rx3));
|
||||
assert!(!rx2.same_channel(&rx3));
|
||||
}
|
1445
vendor/flume/tests/golang.rs
vendored
Normal file
1445
vendor/flume/tests/golang.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
112
vendor/flume/tests/iter.rs
vendored
Normal file
112
vendor/flume/tests/iter.rs
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
//! Tests for iteration over receivers.
|
||||
|
||||
extern crate crossbeam_utils;
|
||||
|
||||
use flume::unbounded;
|
||||
use crossbeam_utils::thread::scope;
|
||||
|
||||
#[test]
|
||||
fn nested_recv_iter() {
|
||||
let (s, r) = unbounded::<i32>();
|
||||
let (total_s, total_r) = unbounded::<i32>();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut acc = 0;
|
||||
for x in r.iter() {
|
||||
acc += x;
|
||||
}
|
||||
total_s.send(acc).unwrap();
|
||||
});
|
||||
|
||||
s.send(3).unwrap();
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
drop(s);
|
||||
assert_eq!(total_r.recv().unwrap(), 6);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_iter_break() {
|
||||
let (s, r) = unbounded::<i32>();
|
||||
let (count_s, count_r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut count = 0;
|
||||
for x in r.iter() {
|
||||
if count >= 3 {
|
||||
break;
|
||||
} else {
|
||||
count += x;
|
||||
}
|
||||
}
|
||||
count_s.send(count).unwrap();
|
||||
});
|
||||
|
||||
s.send(2).unwrap();
|
||||
s.send(2).unwrap();
|
||||
s.send(2).unwrap();
|
||||
let _ = s.send(2);
|
||||
drop(s);
|
||||
assert_eq!(count_r.recv().unwrap(), 4);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_try_iter() {
|
||||
let (request_s, request_r) = unbounded();
|
||||
let (response_s, response_r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
for x in response_r.try_iter() {
|
||||
count += x;
|
||||
if count == 6 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
request_s.send(()).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
for _ in request_r.iter() {
|
||||
if response_s.send(2).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_into_iter_owned() {
|
||||
let mut iter = {
|
||||
let (s, r) = unbounded::<i32>();
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
r.into_iter()
|
||||
};
|
||||
|
||||
assert_eq!(iter.next().unwrap(), 1);
|
||||
assert_eq!(iter.next().unwrap(), 2);
|
||||
assert_eq!(iter.next().is_none(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_into_iter_borrowed() {
|
||||
let (s, r) = unbounded::<i32>();
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
drop(s);
|
||||
|
||||
let mut iter = (&r).into_iter();
|
||||
assert_eq!(iter.next().unwrap(), 1);
|
||||
assert_eq!(iter.next().unwrap(), 2);
|
||||
assert_eq!(iter.next().is_none(), true);
|
||||
}
|
536
vendor/flume/tests/list.rs
vendored
Normal file
536
vendor/flume/tests/list.rs
vendored
Normal file
@ -0,0 +1,536 @@
|
||||
//! Tests for the list channel flavor.
|
||||
|
||||
extern crate crossbeam_utils;
|
||||
extern crate rand;
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use flume::{unbounded, Receiver};
|
||||
use flume::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use flume::{SendError, SendTimeoutError, TrySendError};
|
||||
use crossbeam_utils::thread::scope;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
fn ms(ms: u64) -> Duration {
|
||||
Duration::from_millis(ms)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let (s, r) = unbounded();
|
||||
s.try_send(7).unwrap();
|
||||
assert_eq!(r.try_recv(), Ok(7));
|
||||
|
||||
s.send(8).unwrap();
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capacity() {
|
||||
let (s, r) = unbounded::<()>();
|
||||
assert_eq!(s.capacity(), None);
|
||||
assert_eq!(r.capacity(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len_empty_full() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(s.is_empty(), true);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r.is_full(), false);
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert_eq!(s.is_empty(), false);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 1);
|
||||
assert_eq!(r.is_empty(), false);
|
||||
assert_eq!(r.is_full(), false);
|
||||
|
||||
r.recv().unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(s.is_empty(), true);
|
||||
assert_eq!(s.is_full(), false);
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r.is_full(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_recv() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.try_recv(), Ok(7));
|
||||
thread::sleep(ms(500));
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv(), Ok(7));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(9));
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
s.send(8).unwrap();
|
||||
s.send(9).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_timeout() {
|
||||
let (s, r) = unbounded::<i32>();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
|
||||
assert_eq!(
|
||||
r.recv_timeout(ms(1000)),
|
||||
Err(RecvTimeoutError::Disconnected)
|
||||
);
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_send() {
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..1000 {
|
||||
assert_eq!(s.try_send(i), Ok(()));
|
||||
}
|
||||
|
||||
drop(r);
|
||||
assert_eq!(s.try_send(777), Err(TrySendError::Disconnected(777)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send() {
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..1000 {
|
||||
assert_eq!(s.send(i), Ok(()));
|
||||
}
|
||||
|
||||
drop(r);
|
||||
assert_eq!(s.send(777), Err(SendError(777)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_timeout() {
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..1000 {
|
||||
assert_eq!(s.send_timeout(i, ms(i as u64)), Ok(()));
|
||||
}
|
||||
|
||||
drop(r);
|
||||
assert_eq!(
|
||||
s.send_timeout(777, ms(0)),
|
||||
Err(SendTimeoutError::Disconnected(777))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_after_disconnect() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
s.send(3).unwrap();
|
||||
|
||||
drop(r);
|
||||
|
||||
assert_eq!(s.send(4), Err(SendError(4)));
|
||||
assert_eq!(s.try_send(5), Err(TrySendError::Disconnected(5)));
|
||||
assert_eq!(
|
||||
s.send_timeout(6, ms(0)),
|
||||
Err(SendTimeoutError::Disconnected(6))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_after_disconnect() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
s.send(1).unwrap();
|
||||
s.send(2).unwrap();
|
||||
s.send(3).unwrap();
|
||||
|
||||
drop(s);
|
||||
|
||||
assert_eq!(r.recv(), Ok(1));
|
||||
assert_eq!(r.recv(), Ok(2));
|
||||
assert_eq!(r.recv(), Ok(3));
|
||||
assert!(r.recv().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len() {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
|
||||
for i in 0..50 {
|
||||
s.send(i).unwrap();
|
||||
assert_eq!(s.len(), i + 1);
|
||||
}
|
||||
|
||||
for i in 0..50 {
|
||||
r.recv().unwrap();
|
||||
assert_eq!(r.len(), 50 - i - 1);
|
||||
}
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_wakes_receiver() {
|
||||
let (s, r) = unbounded::<()>();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(r.recv(), Ok(i));
|
||||
}
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
let (s, r) = unbounded::<usize>();
|
||||
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
|
||||
|
||||
scope(|scope| {
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..COUNT {
|
||||
let n = r.recv().unwrap();
|
||||
v[n].fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
|
||||
for c in v {
|
||||
assert_eq!(c.load(Ordering::SeqCst), THREADS);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_oneshot() {
|
||||
const COUNT: usize = 10_000;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| r.recv().unwrap());
|
||||
scope.spawn(|_| s.send(0).unwrap());
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_iter() {
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let (request_s, request_r) = unbounded();
|
||||
let (response_s, response_r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
for x in response_r.try_iter() {
|
||||
count += x;
|
||||
if count == COUNT {
|
||||
return;
|
||||
}
|
||||
}
|
||||
request_s.send(()).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
for _ in request_r.iter() {
|
||||
if response_s.send(1).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_timeout_two_threads() {
|
||||
const COUNT: usize = 100;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
loop {
|
||||
if let Ok(x) = r.recv_timeout(ms(10)) {
|
||||
assert_eq!(x, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drops() {
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct DropCounter;
|
||||
|
||||
impl Drop for DropCounter {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for _ in 0..100 {
|
||||
let steps = rng.gen_range(0..10_000);
|
||||
let additional = rng.gen_range(0..1000);
|
||||
|
||||
DROPS.store(0, Ordering::SeqCst);
|
||||
let (s, r) = unbounded::<DropCounter>();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
r.recv().unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
s.send(DropCounter).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for _ in 0..additional {
|
||||
s.try_send(DropCounter).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
|
||||
drop(s);
|
||||
drop(r);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linearizable() {
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
|
||||
scope(|scope| {
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..COUNT {
|
||||
s.send(0).unwrap();
|
||||
r.try_recv().unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn fairness() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = unbounded::<()>();
|
||||
// let (s2, r2) = unbounded::<()>();
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// s1.send(()).unwrap();
|
||||
// s2.send(()).unwrap();
|
||||
// }
|
||||
|
||||
// let mut hits = [0usize; 2];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r1) -> _ => hits[0] += 1,
|
||||
// recv(r2) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness_duplicates() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s, r) = unbounded();
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// s.send(()).unwrap();
|
||||
// }
|
||||
|
||||
// let mut hits = [0usize; 5];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r) -> _ => hits[0] += 1,
|
||||
// recv(r) -> _ => hits[1] += 1,
|
||||
// recv(r) -> _ => hits[2] += 1,
|
||||
// recv(r) -> _ => hits[3] += 1,
|
||||
// recv(r) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_in_send() {
|
||||
// let (s, r) = unbounded();
|
||||
// s.send(()).unwrap();
|
||||
|
||||
// select! {
|
||||
// send(s, assert_eq!(r.recv(), Ok(()))) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn channel_through_channel() {
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
type T = Box<dyn Any + Send>;
|
||||
|
||||
let (s, r) = unbounded::<T>();
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut s = s;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (new_s, new_r) = unbounded();
|
||||
let new_r: T = Box::new(Some(new_r));
|
||||
|
||||
s.send(new_r).unwrap();
|
||||
s = new_s;
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(move |_| {
|
||||
let mut r = r;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
r = r
|
||||
.recv()
|
||||
.unwrap()
|
||||
.downcast_mut::<Option<Receiver<T>>>()
|
||||
.unwrap()
|
||||
.take()
|
||||
.unwrap()
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
39
vendor/flume/tests/method_sharing.rs
vendored
Normal file
39
vendor/flume/tests/method_sharing.rs
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#[cfg(feature = "async")]
|
||||
use flume::*;
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn sender() {
|
||||
let (sender, receiver) = bounded(1);
|
||||
|
||||
let sender_fut = sender.send_async(());
|
||||
assert_eq!(sender.is_disconnected(), sender_fut.is_disconnected());
|
||||
assert_eq!(sender.is_empty(), sender_fut.is_empty());
|
||||
assert_eq!(sender.is_full(), sender_fut.is_full());
|
||||
assert_eq!(sender.len(), sender_fut.len());
|
||||
assert_eq!(sender.capacity(), sender_fut.capacity());
|
||||
|
||||
let sender_sink = sender.sink();
|
||||
assert_eq!(sender.is_disconnected(), sender_sink.is_disconnected());
|
||||
assert_eq!(sender.is_empty(), sender_sink.is_empty());
|
||||
assert_eq!(sender.is_full(), sender_sink.is_full());
|
||||
assert_eq!(sender.len(), sender_sink.len());
|
||||
assert_eq!(sender.capacity(), sender_sink.capacity());
|
||||
|
||||
let receiver_fut = receiver.recv_async();
|
||||
assert_eq!(receiver.is_disconnected(), receiver_fut.is_disconnected());
|
||||
assert_eq!(receiver.is_empty(), receiver_fut.is_empty());
|
||||
assert_eq!(receiver.is_full(), receiver_fut.is_full());
|
||||
assert_eq!(receiver.len(), receiver_fut.len());
|
||||
assert_eq!(receiver.capacity(), receiver_fut.capacity());
|
||||
|
||||
let receiver_stream = receiver.stream();
|
||||
assert_eq!(
|
||||
receiver.is_disconnected(),
|
||||
receiver_stream.is_disconnected()
|
||||
);
|
||||
assert_eq!(receiver.is_empty(), receiver_stream.is_empty());
|
||||
assert_eq!(receiver.is_full(), receiver_stream.is_full());
|
||||
assert_eq!(receiver.len(), receiver_stream.len());
|
||||
assert_eq!(receiver.capacity(), receiver_stream.capacity());
|
||||
}
|
2095
vendor/flume/tests/mpsc.rs
vendored
Normal file
2095
vendor/flume/tests/mpsc.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
99
vendor/flume/tests/never.rs
vendored
Normal file
99
vendor/flume/tests/never.rs
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
// //! Tests for the never channel flavor.
|
||||
|
||||
// #[macro_use]
|
||||
// extern crate crossbeam_channel;
|
||||
// extern crate rand;
|
||||
|
||||
// use std::thread;
|
||||
// use std::time::{Duration, Instant};
|
||||
|
||||
// use crossbeam_channel::{never, tick, unbounded};
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn smoke() {
|
||||
// select! {
|
||||
// recv(never::<i32>()) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn optional() {
|
||||
// let (s, r) = unbounded::<i32>();
|
||||
// s.send(1).unwrap();
|
||||
// s.send(2).unwrap();
|
||||
|
||||
// let mut r = Some(&r);
|
||||
// select! {
|
||||
// recv(r.unwrap_or(&never())) -> _ => {}
|
||||
// default => panic!(),
|
||||
// }
|
||||
|
||||
// r = None;
|
||||
// select! {
|
||||
// recv(r.unwrap_or(&never())) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn tick_n() {
|
||||
// let mut r = tick(ms(100));
|
||||
// let mut step = 0;
|
||||
|
||||
// loop {
|
||||
// select! {
|
||||
// recv(r) -> _ => step += 1,
|
||||
// default(ms(500)) => break,
|
||||
// }
|
||||
|
||||
// if step == 10 {
|
||||
// r = never();
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert_eq!(step, 10);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn capacity() {
|
||||
// let r = never::<i32>();
|
||||
// assert_eq!(r.capacity(), Some(0));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn len_empty_full() {
|
||||
// let r = never::<i32>();
|
||||
// assert_eq!(r.len(), 0);
|
||||
// assert_eq!(r.is_empty(), true);
|
||||
// assert_eq!(r.is_full(), true);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn try_recv() {
|
||||
// let r = never::<i32>();
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(100));
|
||||
// assert!(r.try_recv().is_err());
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_timeout() {
|
||||
// let start = Instant::now();
|
||||
// let r = never::<i32>();
|
||||
|
||||
// assert!(r.recv_timeout(ms(100)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(100));
|
||||
// assert!(now - start <= ms(150));
|
||||
|
||||
// assert!(r.recv_timeout(ms(100)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(200));
|
||||
// assert!(now - start <= ms(250));
|
||||
// }
|
837
vendor/flume/tests/ready.rs
vendored
Normal file
837
vendor/flume/tests/ready.rs
vendored
Normal file
@ -0,0 +1,837 @@
|
||||
// //! Tests for channel readiness using the `Select` struct.
|
||||
|
||||
// extern crate crossbeam_channel;
|
||||
// extern crate crossbeam_utils;
|
||||
|
||||
// use std::any::Any;
|
||||
// use std::cell::Cell;
|
||||
// use std::thread;
|
||||
// use std::time::{Duration, Instant};
|
||||
|
||||
// use crossbeam_channel::{after, bounded, tick, unbounded};
|
||||
// use crossbeam_channel::{Receiver, Select, TryRecvError, TrySendError};
|
||||
// use crossbeam_utils::thread::scope;
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn smoke1() {
|
||||
// let (s1, r1) = unbounded::<usize>();
|
||||
// let (s2, r2) = unbounded::<usize>();
|
||||
|
||||
// s1.send(1).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// assert_eq!(sel.ready(), 0);
|
||||
// assert_eq!(r1.try_recv(), Ok(1));
|
||||
|
||||
// s2.send(2).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// assert_eq!(sel.ready(), 1);
|
||||
// assert_eq!(r2.try_recv(), Ok(2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn smoke2() {
|
||||
// let (_s1, r1) = unbounded::<i32>();
|
||||
// let (_s2, r2) = unbounded::<i32>();
|
||||
// let (_s3, r3) = unbounded::<i32>();
|
||||
// let (_s4, r4) = unbounded::<i32>();
|
||||
// let (s5, r5) = unbounded::<i32>();
|
||||
|
||||
// s5.send(5).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// sel.recv(&r3);
|
||||
// sel.recv(&r4);
|
||||
// sel.recv(&r5);
|
||||
// assert_eq!(sel.ready(), 4);
|
||||
// assert_eq!(r5.try_recv(), Ok(5));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn disconnected() {
|
||||
// let (s1, r1) = unbounded::<i32>();
|
||||
// let (s2, r2) = unbounded::<i32>();
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// drop(s1);
|
||||
// thread::sleep(ms(500));
|
||||
// s2.send(5).unwrap();
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// r2.recv().unwrap();
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(0) => assert_eq!(r1.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(500));
|
||||
// drop(s2);
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(0) => assert_eq!(r2.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn default() {
|
||||
// let (s1, r1) = unbounded::<i32>();
|
||||
// let (s2, r2) = unbounded::<i32>();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// assert!(sel.try_ready().is_err());
|
||||
|
||||
// drop(s1);
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.try_ready() {
|
||||
// Ok(0) => assert!(r1.try_recv().is_err()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// s2.send(2).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r2);
|
||||
// match sel.try_ready() {
|
||||
// Ok(0) => assert_eq!(r2.try_recv(), Ok(2)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r2);
|
||||
// assert!(sel.try_ready().is_err());
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// assert!(sel.try_ready().is_err());
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn timeout() {
|
||||
// let (_s1, r1) = unbounded::<i32>();
|
||||
// let (s2, r2) = unbounded::<i32>();
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(1500));
|
||||
// s2.send(2).unwrap();
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// assert!(sel.ready_timeout(ms(1000)).is_err());
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// scope(|scope| {
|
||||
// let (s, r) = unbounded::<i32>();
|
||||
|
||||
// scope.spawn(move |_| {
|
||||
// thread::sleep(ms(500));
|
||||
// drop(s);
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// assert!(sel.ready_timeout(ms(1000)).is_err());
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.try_ready() {
|
||||
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn default_when_disconnected() {
|
||||
// let (_, r) = unbounded::<i32>();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.try_ready() {
|
||||
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// let (_, r) = unbounded::<i32>();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(0) => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// let (s, _) = bounded::<i32>(0);
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.try_ready() {
|
||||
// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// let (s, _) = bounded::<i32>(0);
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(0) => assert_eq!(s.try_send(0), Err(TrySendError::Disconnected(0))),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn default_only() {
|
||||
// let start = Instant::now();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// assert!(sel.try_ready().is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start <= ms(50));
|
||||
|
||||
// let start = Instant::now();
|
||||
// let mut sel = Select::new();
|
||||
// assert!(sel.ready_timeout(ms(500)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(450));
|
||||
// assert!(now - start <= ms(550));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn unblocks() {
|
||||
// let (s1, r1) = bounded::<i32>(0);
|
||||
// let (s2, r2) = bounded::<i32>(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(500));
|
||||
// s2.send(2).unwrap();
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready_timeout(ms(1000)) {
|
||||
// Ok(1) => assert_eq!(r2.try_recv(), Ok(2)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(500));
|
||||
// assert_eq!(r1.recv().unwrap(), 1);
|
||||
// });
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// let oper1 = sel.send(&s1);
|
||||
// let oper2 = sel.send(&s2);
|
||||
// let oper = sel.select_timeout(ms(1000));
|
||||
// match oper {
|
||||
// Err(_) => panic!(),
|
||||
// Ok(oper) => match oper.index() {
|
||||
// i if i == oper1 => oper.send(&s1, 1).unwrap(),
|
||||
// i if i == oper2 => panic!(),
|
||||
// _ => unreachable!(),
|
||||
// },
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn both_ready() {
|
||||
// let (s1, r1) = bounded(0);
|
||||
// let (s2, r2) = bounded(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(500));
|
||||
// s1.send(1).unwrap();
|
||||
// assert_eq!(r2.recv().unwrap(), 2);
|
||||
// });
|
||||
|
||||
// for _ in 0..2 {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.send(&s2);
|
||||
// match sel.ready() {
|
||||
// 0 => assert_eq!(r1.try_recv(), Ok(1)),
|
||||
// 1 => s2.try_send(2).unwrap(),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn cloning1() {
|
||||
// scope(|scope| {
|
||||
// let (s1, r1) = unbounded::<i32>();
|
||||
// let (_s2, r2) = unbounded::<i32>();
|
||||
// let (s3, r3) = unbounded::<()>();
|
||||
|
||||
// scope.spawn(move |_| {
|
||||
// r3.recv().unwrap();
|
||||
// drop(s1.clone());
|
||||
// assert!(r3.try_recv().is_err());
|
||||
// s1.send(1).unwrap();
|
||||
// r3.recv().unwrap();
|
||||
// });
|
||||
|
||||
// s3.send(()).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready() {
|
||||
// 0 => drop(r1.try_recv()),
|
||||
// 1 => drop(r2.try_recv()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// s3.send(()).unwrap();
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn cloning2() {
|
||||
// let (s1, r1) = unbounded::<()>();
|
||||
// let (s2, r2) = unbounded::<()>();
|
||||
// let (_s3, _r3) = unbounded::<()>();
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(move |_| {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready() {
|
||||
// 0 => panic!(),
|
||||
// 1 => drop(r2.try_recv()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// });
|
||||
|
||||
// thread::sleep(ms(500));
|
||||
// drop(s1.clone());
|
||||
// s2.send(()).unwrap();
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn preflight1() {
|
||||
// let (s, r) = unbounded();
|
||||
// s.send(()).unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => drop(r.try_recv()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn preflight2() {
|
||||
// let (s, r) = unbounded();
|
||||
// drop(s.clone());
|
||||
// s.send(()).unwrap();
|
||||
// drop(s);
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => assert_eq!(r.try_recv(), Ok(())),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn preflight3() {
|
||||
// let (s, r) = unbounded();
|
||||
// drop(s.clone());
|
||||
// s.send(()).unwrap();
|
||||
// drop(s);
|
||||
// r.recv().unwrap();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn duplicate_operations() {
|
||||
// let (s, r) = unbounded::<i32>();
|
||||
// let hit = vec![Cell::new(false); 4];
|
||||
|
||||
// while hit.iter().map(|h| h.get()).any(|hit| !hit) {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// sel.recv(&r);
|
||||
// sel.send(&s);
|
||||
// sel.send(&s);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// assert!(r.try_recv().is_ok());
|
||||
// hit[0].set(true);
|
||||
// }
|
||||
// 1 => {
|
||||
// assert!(r.try_recv().is_ok());
|
||||
// hit[1].set(true);
|
||||
// }
|
||||
// 2 => {
|
||||
// assert!(s.try_send(0).is_ok());
|
||||
// hit[2].set(true);
|
||||
// }
|
||||
// 3 => {
|
||||
// assert!(s.try_send(0).is_ok());
|
||||
// hit[3].set(true);
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn nesting() {
|
||||
// let (s, r) = unbounded::<i32>();
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// assert!(s.try_send(0).is_ok());
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// assert_eq!(r.try_recv(), Ok(0));
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// assert!(s.try_send(1).is_ok());
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// assert_eq!(r.try_recv(), Ok(1));
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_recv() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = unbounded();
|
||||
// let (s2, r2) = bounded(5);
|
||||
// let (s3, r3) = bounded(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for i in 0..COUNT {
|
||||
// s1.send(i).unwrap();
|
||||
// r3.recv().unwrap();
|
||||
|
||||
// s2.send(i).unwrap();
|
||||
// r3.recv().unwrap();
|
||||
// }
|
||||
// });
|
||||
|
||||
// for i in 0..COUNT {
|
||||
// for _ in 0..2 {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// match sel.ready() {
|
||||
// 0 => assert_eq!(r1.try_recv(), Ok(i)),
|
||||
// 1 => assert_eq!(r2.try_recv(), Ok(i)),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
|
||||
// s3.send(()).unwrap();
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_send() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = bounded(0);
|
||||
// let (s2, r2) = bounded(0);
|
||||
// let (s3, r3) = bounded(100);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for i in 0..COUNT {
|
||||
// assert_eq!(r1.recv().unwrap(), i);
|
||||
// assert_eq!(r2.recv().unwrap(), i);
|
||||
// r3.recv().unwrap();
|
||||
// }
|
||||
// });
|
||||
|
||||
// for i in 0..COUNT {
|
||||
// for _ in 0..2 {
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s1);
|
||||
// sel.send(&s2);
|
||||
// match sel.ready() {
|
||||
// 0 => assert!(s1.try_send(i).is_ok()),
|
||||
// 1 => assert!(s2.try_send(i).is_ok()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// s3.send(()).unwrap();
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_mixed() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = bounded(0);
|
||||
// let (s2, r2) = bounded(0);
|
||||
// let (s3, r3) = bounded(100);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for i in 0..COUNT {
|
||||
// s1.send(i).unwrap();
|
||||
// assert_eq!(r2.recv().unwrap(), i);
|
||||
// r3.recv().unwrap();
|
||||
// }
|
||||
// });
|
||||
|
||||
// for i in 0..COUNT {
|
||||
// for _ in 0..2 {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.send(&s2);
|
||||
// match sel.ready() {
|
||||
// 0 => assert_eq!(r1.try_recv(), Ok(i)),
|
||||
// 1 => assert!(s2.try_send(i).is_ok()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// s3.send(()).unwrap();
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_timeout_two_threads() {
|
||||
// const COUNT: usize = 20;
|
||||
|
||||
// let (s, r) = bounded(2);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for i in 0..COUNT {
|
||||
// if i % 2 == 0 {
|
||||
// thread::sleep(ms(500));
|
||||
// }
|
||||
|
||||
// let done = false;
|
||||
// while !done {
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.ready_timeout(ms(100)) {
|
||||
// Err(_) => {}
|
||||
// Ok(0) => {
|
||||
// assert!(s.try_send(i).is_ok());
|
||||
// break;
|
||||
// }
|
||||
// Ok(_) => panic!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// scope.spawn(|_| {
|
||||
// for i in 0..COUNT {
|
||||
// if i % 2 == 0 {
|
||||
// thread::sleep(ms(500));
|
||||
// }
|
||||
|
||||
// let mut done = false;
|
||||
// while !done {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready_timeout(ms(100)) {
|
||||
// Err(_) => {}
|
||||
// Ok(0) => {
|
||||
// assert_eq!(r.try_recv(), Ok(i));
|
||||
// done = true;
|
||||
// }
|
||||
// Ok(_) => panic!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn send_recv_same_channel() {
|
||||
// let (s, r) = bounded::<i32>(0);
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// sel.recv(&r);
|
||||
// assert!(sel.ready_timeout(ms(100)).is_err());
|
||||
|
||||
// let (s, r) = unbounded::<i32>();
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// sel.recv(&r);
|
||||
// match sel.ready_timeout(ms(100)) {
|
||||
// Err(_) => panic!(),
|
||||
// Ok(0) => assert!(s.try_send(0).is_ok()),
|
||||
// Ok(_) => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn channel_through_channel() {
|
||||
// const COUNT: usize = 1000;
|
||||
|
||||
// type T = Box<dyn Any + Send>;
|
||||
|
||||
// for cap in 1..4 {
|
||||
// let (s, r) = bounded::<T>(cap);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(move |_| {
|
||||
// let mut s = s;
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// let (new_s, new_r) = bounded(cap);
|
||||
// let new_r: T = Box::new(Some(new_r));
|
||||
|
||||
// {
|
||||
// let mut sel = Select::new();
|
||||
// sel.send(&s);
|
||||
// match sel.ready() {
|
||||
// 0 => assert!(s.try_send(new_r).is_ok()),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// s = new_s;
|
||||
// }
|
||||
// });
|
||||
|
||||
// scope.spawn(move |_| {
|
||||
// let mut r = r;
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// let new = {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r);
|
||||
// match sel.ready() {
|
||||
// 0 => r
|
||||
// .try_recv()
|
||||
// .unwrap()
|
||||
// .downcast_mut::<Option<Receiver<T>>>()
|
||||
// .unwrap()
|
||||
// .take()
|
||||
// .unwrap(),
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// };
|
||||
// r = new;
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness1() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = bounded::<()>(COUNT);
|
||||
// let (s2, r2) = unbounded::<()>();
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// s1.send(()).unwrap();
|
||||
// s2.send(()).unwrap();
|
||||
// }
|
||||
|
||||
// let hits = vec![Cell::new(0usize); 4];
|
||||
// for _ in 0..COUNT {
|
||||
// let after = after(ms(0));
|
||||
// let tick = tick(ms(0));
|
||||
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// sel.recv(&after);
|
||||
// sel.recv(&tick);
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// r1.try_recv().unwrap();
|
||||
// hits[0].set(hits[0].get() + 1);
|
||||
// }
|
||||
// 1 => {
|
||||
// r2.try_recv().unwrap();
|
||||
// hits[1].set(hits[1].get() + 1);
|
||||
// }
|
||||
// 2 => {
|
||||
// after.try_recv().unwrap();
|
||||
// hits[2].set(hits[2].get() + 1);
|
||||
// }
|
||||
// 3 => {
|
||||
// tick.try_recv().unwrap();
|
||||
// hits[3].set(hits[3].get() + 1);
|
||||
// }
|
||||
// _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness2() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = unbounded::<()>();
|
||||
// let (s2, r2) = bounded::<()>(1);
|
||||
// let (s3, r3) = bounded::<()>(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for _ in 0..COUNT {
|
||||
// let mut sel = Select::new();
|
||||
// let mut oper1 = None;
|
||||
// let mut oper2 = None;
|
||||
// if s1.is_empty() {
|
||||
// oper1 = Some(sel.send(&s1));
|
||||
// }
|
||||
// if s2.is_empty() {
|
||||
// oper2 = Some(sel.send(&s2));
|
||||
// }
|
||||
// let oper3 = sel.send(&s3);
|
||||
// let oper = sel.select();
|
||||
// match oper.index() {
|
||||
// i if Some(i) == oper1 => assert!(oper.send(&s1, ()).is_ok()),
|
||||
// i if Some(i) == oper2 => assert!(oper.send(&s2, ()).is_ok()),
|
||||
// i if i == oper3 => assert!(oper.send(&s3, ()).is_ok()),
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// let hits = vec![Cell::new(0usize); 3];
|
||||
// for _ in 0..COUNT {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// sel.recv(&r3);
|
||||
// loop {
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// if r1.try_recv().is_ok() {
|
||||
// hits[0].set(hits[0].get() + 1);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// 1 => {
|
||||
// if r2.try_recv().is_ok() {
|
||||
// hits[1].set(hits[1].get() + 1);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// 2 => {
|
||||
// if r3.try_recv().is_ok() {
|
||||
// hits[2].set(hits[2].get() + 1);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 10));
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
114
vendor/flume/tests/same_channel.rs
vendored
Normal file
114
vendor/flume/tests/same_channel.rs
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
// extern crate crossbeam_channel;
|
||||
|
||||
// use std::time::Duration;
|
||||
|
||||
// use crossbeam_channel::{after, bounded, never, tick, unbounded};
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn after_same_channel() {
|
||||
// let r = after(ms(50));
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// let r3 = after(ms(50));
|
||||
// assert!(!r.same_channel(&r3));
|
||||
// assert!(!r2.same_channel(&r3));
|
||||
|
||||
// let r4 = after(ms(100));
|
||||
// assert!(!r.same_channel(&r4));
|
||||
// assert!(!r2.same_channel(&r4));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn array_same_channel() {
|
||||
// let (s, r) = bounded::<usize>(1);
|
||||
|
||||
// let s2 = s.clone();
|
||||
// assert!(s.same_channel(&s2));
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// let (s3, r3) = bounded::<usize>(1);
|
||||
// assert!(!s.same_channel(&s3));
|
||||
// assert!(!s2.same_channel(&s3));
|
||||
// assert!(!r.same_channel(&r3));
|
||||
// assert!(!r2.same_channel(&r3));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn list_same_channel() {
|
||||
// let (s, r) = unbounded::<usize>();
|
||||
|
||||
// let s2 = s.clone();
|
||||
// assert!(s.same_channel(&s2));
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// let (s3, r3) = unbounded::<usize>();
|
||||
// assert!(!s.same_channel(&s3));
|
||||
// assert!(!s2.same_channel(&s3));
|
||||
// assert!(!r.same_channel(&r3));
|
||||
// assert!(!r2.same_channel(&r3));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn never_same_channel() {
|
||||
// let r = never::<usize>();
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// // Never channel are always equal to one another.
|
||||
// let r3 = never::<usize>();
|
||||
// assert!(r.same_channel(&r3));
|
||||
// assert!(r2.same_channel(&r3));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn tick_same_channel() {
|
||||
// let r = tick(ms(50));
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// let r3 = tick(ms(50));
|
||||
// assert!(!r.same_channel(&r3));
|
||||
// assert!(!r2.same_channel(&r3));
|
||||
|
||||
// let r4 = tick(ms(100));
|
||||
// assert!(!r.same_channel(&r4));
|
||||
// assert!(!r2.same_channel(&r4));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn zero_same_channel() {
|
||||
// let (s, r) = bounded::<usize>(0);
|
||||
|
||||
// let s2 = s.clone();
|
||||
// assert!(s.same_channel(&s2));
|
||||
|
||||
// let r2 = r.clone();
|
||||
// assert!(r.same_channel(&r2));
|
||||
|
||||
// let (s3, r3) = bounded::<usize>(0);
|
||||
// assert!(!s.same_channel(&s3));
|
||||
// assert!(!s2.same_channel(&s3));
|
||||
// assert!(!r.same_channel(&r3));
|
||||
// assert!(!r2.same_channel(&r3));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn different_flavors_same_channel() {
|
||||
// let (s1, r1) = bounded::<usize>(0);
|
||||
// let (s2, r2) = unbounded::<usize>();
|
||||
|
||||
// assert!(!s1.same_channel(&s2));
|
||||
// assert!(!r1.same_channel(&r2));
|
||||
// }
|
1304
vendor/flume/tests/select.rs
vendored
Normal file
1304
vendor/flume/tests/select.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1440
vendor/flume/tests/select_macro.rs
vendored
Normal file
1440
vendor/flume/tests/select_macro.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
255
vendor/flume/tests/stream.rs
vendored
Normal file
255
vendor/flume/tests/stream.rs
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
#[cfg(feature = "async")]
|
||||
use {
|
||||
flume::*,
|
||||
futures::{stream::FuturesUnordered, StreamExt, TryFutureExt},
|
||||
async_std::prelude::FutureExt,
|
||||
std::time::Duration,
|
||||
};
|
||||
use futures::{stream, Stream};
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn stream_recv() {
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
tx.send(42u32).unwrap();
|
||||
println!("sent");
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
println!("receiving...");
|
||||
let x = rx.stream().next().await;
|
||||
println!("received");
|
||||
assert_eq!(x, Some(42));
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn stream_recv_disconnect() {
|
||||
let (tx, rx) = bounded::<i32>(0);
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
tx.send(42);
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
drop(tx)
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
let mut stream = rx.into_stream();
|
||||
assert_eq!(stream.next().await, Some(42));
|
||||
assert_eq!(stream.next().await, None);
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn stream_recv_drop_recv() {
|
||||
let (tx, rx) = bounded::<i32>(10);
|
||||
|
||||
let rx2 = rx.clone();
|
||||
let mut stream = rx.into_stream();
|
||||
|
||||
async_std::task::block_on(async {
|
||||
let res = async_std::future::timeout(
|
||||
std::time::Duration::from_millis(500),
|
||||
stream.next()
|
||||
).await;
|
||||
|
||||
assert!(res.is_err());
|
||||
});
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
async_std::task::block_on(async {
|
||||
rx2.stream().next().await
|
||||
})
|
||||
});
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
tx.send(42).unwrap();
|
||||
|
||||
drop(stream);
|
||||
|
||||
assert_eq!(t.join().unwrap(), Some(42))
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn r#stream_drop_send_disconnect() {
|
||||
let (tx, rx) = bounded::<i32>(1);
|
||||
|
||||
let t = std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
drop(tx);
|
||||
});
|
||||
|
||||
async_std::task::block_on(async {
|
||||
let mut stream = rx.into_stream();
|
||||
assert_eq!(stream.next().await, None);
|
||||
});
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn stream_send_1_million_no_drop_or_reorder() {
|
||||
#[derive(Debug)]
|
||||
enum Message {
|
||||
Increment {
|
||||
old: u64,
|
||||
},
|
||||
ReturnCount,
|
||||
}
|
||||
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
let t = async_std::task::spawn(async move {
|
||||
let mut count = 0u64;
|
||||
let mut stream = rx.into_stream();
|
||||
|
||||
while let Some(Message::Increment { old }) = stream.next().await {
|
||||
assert_eq!(old, count);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
count
|
||||
});
|
||||
|
||||
for next in 0..1_000_000 {
|
||||
tx.send(Message::Increment { old: next }).unwrap();
|
||||
}
|
||||
|
||||
tx.send(Message::ReturnCount).unwrap();
|
||||
|
||||
let count = t.await;
|
||||
assert_eq!(count, 1_000_000)
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn parallel_streams_and_async_recv() {
|
||||
let (tx, rx) = flume::unbounded();
|
||||
let rx = ℞
|
||||
let send_fut = async move {
|
||||
let n_sends: usize = 100000;
|
||||
for _ in 0..n_sends {
|
||||
tx.send_async(()).await.unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
async_std::task::spawn(
|
||||
send_fut
|
||||
.timeout(Duration::from_secs(5))
|
||||
.map_err(|_| panic!("Send timed out!"))
|
||||
);
|
||||
|
||||
let mut futures_unordered = (0..250)
|
||||
.map(|n| async move {
|
||||
if n % 2 == 0 {
|
||||
let mut stream = rx.stream();
|
||||
while let Some(()) = stream.next().await {}
|
||||
} else {
|
||||
while let Ok(()) = rx.recv_async().await {}
|
||||
}
|
||||
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>();
|
||||
|
||||
let recv_fut = async {
|
||||
while futures_unordered.next().await.is_some() {}
|
||||
};
|
||||
|
||||
recv_fut
|
||||
.timeout(Duration::from_secs(5))
|
||||
.map_err(|_| panic!("Receive timed out!"))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[test]
|
||||
fn stream_no_double_wake() {
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use futures::task::{waker, ArcWake};
|
||||
use futures::Stream;
|
||||
|
||||
let count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
// all this waker does is count how many times it is called
|
||||
struct CounterWaker {
|
||||
count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl ArcWake for CounterWaker {
|
||||
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||
arc_self.count.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
// create waker and context
|
||||
let w = CounterWaker {
|
||||
count: count.clone(),
|
||||
};
|
||||
let w = waker(Arc::new(w));
|
||||
let cx = &mut Context::from_waker(&w);
|
||||
|
||||
// create unbounded channel
|
||||
let (tx, rx) = unbounded::<()>();
|
||||
let mut stream = rx.stream();
|
||||
|
||||
// register waker with stream
|
||||
let _ = Pin::new(&mut stream).poll_next(cx);
|
||||
|
||||
// send multiple items
|
||||
tx.send(()).unwrap();
|
||||
tx.send(()).unwrap();
|
||||
tx.send(()).unwrap();
|
||||
|
||||
// verify that stream is only woken up once.
|
||||
assert_eq!(count.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_std::test]
|
||||
async fn stream_forward_issue_55() { // https://github.com/zesterer/flume/issues/55
|
||||
fn dummy_stream() -> impl Stream<Item = usize> {
|
||||
stream::unfold(0, |count| async move {
|
||||
if count < 1000 {
|
||||
Some((count, count + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let (send_task, recv_task) = {
|
||||
use futures::SinkExt;
|
||||
let (tx, rx) = flume::bounded(100);
|
||||
|
||||
let send_task = dummy_stream()
|
||||
.map(|i| Ok(i))
|
||||
.forward(tx.into_sink().sink_map_err(|e| {
|
||||
panic!("send error:{:#?}", e)
|
||||
}));
|
||||
|
||||
let recv_task = rx
|
||||
.into_stream()
|
||||
.for_each(|item| async move {});
|
||||
(send_task, recv_task)
|
||||
};
|
||||
|
||||
let jh = async_std::task::spawn(send_task);
|
||||
async_std::task::block_on(recv_task);
|
||||
jh.await.unwrap();
|
||||
}
|
53
vendor/flume/tests/thread_locals.rs
vendored
Normal file
53
vendor/flume/tests/thread_locals.rs
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// //! Tests that make sure accessing thread-locals while exiting the thread doesn't cause panics.
|
||||
|
||||
// extern crate crossbeam_utils;
|
||||
|
||||
// use std::thread;
|
||||
// use std::time::Duration;
|
||||
|
||||
// use flume::unbounded;
|
||||
// use crossbeam_utils::thread::scope;
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// #[cfg_attr(target_os = "macos", ignore = "TLS is destroyed too early on macOS")]
|
||||
// fn use_while_exiting() {
|
||||
// struct Foo;
|
||||
|
||||
// impl Drop for Foo {
|
||||
// fn drop(&mut self) {
|
||||
// // A blocking operation after the thread-locals have been dropped. This will attempt to
|
||||
// // use the thread-locals and must not panic.
|
||||
// let (_s, r) = unbounded::<()>();
|
||||
// select! {
|
||||
// recv(r) -> _ => {}
|
||||
// default(ms(100)) => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// thread_local! {
|
||||
// static FOO: Foo = Foo;
|
||||
// }
|
||||
|
||||
// let (s, r) = unbounded::<()>();
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// // First initialize `FOO`, then the thread-locals related to crossbeam-channel.
|
||||
// FOO.with(|_| ());
|
||||
// r.recv().unwrap();
|
||||
// // At thread exit, thread-locals related to crossbeam-channel get dropped first and
|
||||
// // `FOO` is dropped last.
|
||||
// });
|
||||
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(100));
|
||||
// s.send(()).unwrap();
|
||||
// });
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
353
vendor/flume/tests/tick.rs
vendored
Normal file
353
vendor/flume/tests/tick.rs
vendored
Normal file
@ -0,0 +1,353 @@
|
||||
// //! Tests for the tick channel flavor.
|
||||
|
||||
// #[macro_use]
|
||||
// extern crate crossbeam_channel;
|
||||
// extern crate crossbeam_utils;
|
||||
// extern crate rand;
|
||||
|
||||
// use std::sync::atomic::AtomicUsize;
|
||||
// use std::sync::atomic::Ordering;
|
||||
// use std::thread;
|
||||
// use std::time::{Duration, Instant};
|
||||
|
||||
// use crossbeam_channel::{after, tick, Select, TryRecvError};
|
||||
// use crossbeam_utils::thread::scope;
|
||||
|
||||
// fn ms(ms: u64) -> Duration {
|
||||
// Duration::from_millis(ms)
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fire() {
|
||||
// let start = Instant::now();
|
||||
// let r = tick(ms(50));
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// thread::sleep(ms(100));
|
||||
|
||||
// let fired = r.try_recv().unwrap();
|
||||
// assert!(start < fired);
|
||||
// assert!(fired - start >= ms(50));
|
||||
|
||||
// let now = Instant::now();
|
||||
// assert!(fired < now);
|
||||
// assert!(now - fired >= ms(50));
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
|
||||
// select! {
|
||||
// recv(r) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
|
||||
// select! {
|
||||
// recv(r) -> _ => {}
|
||||
// recv(tick(ms(200))) -> _ => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn intervals() {
|
||||
// let start = Instant::now();
|
||||
// let r = tick(ms(50));
|
||||
|
||||
// let t1 = r.recv().unwrap();
|
||||
// assert!(start + ms(50) <= t1);
|
||||
// assert!(start + ms(100) > t1);
|
||||
|
||||
// thread::sleep(ms(300));
|
||||
// let t2 = r.try_recv().unwrap();
|
||||
// assert!(start + ms(100) <= t2);
|
||||
// assert!(start + ms(150) > t2);
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// let t3 = r.recv().unwrap();
|
||||
// assert!(start + ms(400) <= t3);
|
||||
// assert!(start + ms(450) > t3);
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn capacity() {
|
||||
// const COUNT: usize = 10;
|
||||
|
||||
// for i in 0..COUNT {
|
||||
// let r = tick(ms(i as u64));
|
||||
// assert_eq!(r.capacity(), Some(1));
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn len_empty_full() {
|
||||
// let r = tick(ms(50));
|
||||
|
||||
// assert_eq!(r.len(), 0);
|
||||
// assert_eq!(r.is_empty(), true);
|
||||
// assert_eq!(r.is_full(), false);
|
||||
|
||||
// thread::sleep(ms(100));
|
||||
|
||||
// assert_eq!(r.len(), 1);
|
||||
// assert_eq!(r.is_empty(), false);
|
||||
// assert_eq!(r.is_full(), true);
|
||||
|
||||
// r.try_recv().unwrap();
|
||||
|
||||
// assert_eq!(r.len(), 0);
|
||||
// assert_eq!(r.is_empty(), true);
|
||||
// assert_eq!(r.is_full(), false);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn try_recv() {
|
||||
// let r = tick(ms(200));
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(100));
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(200));
|
||||
// assert!(r.try_recv().is_ok());
|
||||
// assert!(r.try_recv().is_err());
|
||||
|
||||
// thread::sleep(ms(200));
|
||||
// assert!(r.try_recv().is_ok());
|
||||
// assert!(r.try_recv().is_err());
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv() {
|
||||
// let start = Instant::now();
|
||||
// let r = tick(ms(50));
|
||||
|
||||
// let fired = r.recv().unwrap();
|
||||
// assert!(start < fired);
|
||||
// assert!(fired - start >= ms(50));
|
||||
|
||||
// let now = Instant::now();
|
||||
// assert!(fired < now);
|
||||
// assert!(now - fired < fired - start);
|
||||
|
||||
// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_timeout() {
|
||||
// let start = Instant::now();
|
||||
// let r = tick(ms(200));
|
||||
|
||||
// assert!(r.recv_timeout(ms(100)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(100));
|
||||
// assert!(now - start <= ms(150));
|
||||
|
||||
// let fired = r.recv_timeout(ms(200)).unwrap();
|
||||
// assert!(fired - start >= ms(200));
|
||||
// assert!(fired - start <= ms(250));
|
||||
|
||||
// assert!(r.recv_timeout(ms(100)).is_err());
|
||||
// let now = Instant::now();
|
||||
// assert!(now - start >= ms(300));
|
||||
// assert!(now - start <= ms(350));
|
||||
|
||||
// let fired = r.recv_timeout(ms(200)).unwrap();
|
||||
// assert!(fired - start >= ms(400));
|
||||
// assert!(fired - start <= ms(450));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_two() {
|
||||
// let r1 = tick(ms(50));
|
||||
// let r2 = tick(ms(50));
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// for _ in 0..10 {
|
||||
// select! {
|
||||
// recv(r1) -> _ => {}
|
||||
// recv(r2) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// scope.spawn(|_| {
|
||||
// for _ in 0..10 {
|
||||
// select! {
|
||||
// recv(r1) -> _ => {}
|
||||
// recv(r2) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_race() {
|
||||
// select! {
|
||||
// recv(tick(ms(50))) -> _ => {}
|
||||
// recv(tick(ms(100))) -> _ => panic!(),
|
||||
// }
|
||||
|
||||
// select! {
|
||||
// recv(tick(ms(100))) -> _ => panic!(),
|
||||
// recv(tick(ms(50))) -> _ => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn stress_default() {
|
||||
// const COUNT: usize = 10;
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(tick(ms(0))) -> _ => {}
|
||||
// default => panic!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(tick(ms(100))) -> _ => panic!(),
|
||||
// default => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn select() {
|
||||
// const THREADS: usize = 4;
|
||||
|
||||
// let hits = AtomicUsize::new(0);
|
||||
// let r1 = tick(ms(200));
|
||||
// let r2 = tick(ms(300));
|
||||
|
||||
// scope(|scope| {
|
||||
// for _ in 0..THREADS {
|
||||
// scope.spawn(|_| {
|
||||
// let timeout = after(ms(1100));
|
||||
// loop {
|
||||
// let mut sel = Select::new();
|
||||
// let oper1 = sel.recv(&r1);
|
||||
// let oper2 = sel.recv(&r2);
|
||||
// let oper3 = sel.recv(&timeout);
|
||||
// let oper = sel.select();
|
||||
// match oper.index() {
|
||||
// i if i == oper1 => {
|
||||
// oper.recv(&r1).unwrap();
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// }
|
||||
// i if i == oper2 => {
|
||||
// oper.recv(&r2).unwrap();
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// }
|
||||
// i if i == oper3 => {
|
||||
// oper.recv(&timeout).unwrap();
|
||||
// break;
|
||||
// }
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// assert_eq!(hits.load(Ordering::SeqCst), 8);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn ready() {
|
||||
// const THREADS: usize = 4;
|
||||
|
||||
// let hits = AtomicUsize::new(0);
|
||||
// let r1 = tick(ms(200));
|
||||
// let r2 = tick(ms(300));
|
||||
|
||||
// scope(|scope| {
|
||||
// for _ in 0..THREADS {
|
||||
// scope.spawn(|_| {
|
||||
// let timeout = after(ms(1100));
|
||||
// 'outer: loop {
|
||||
// let mut sel = Select::new();
|
||||
// sel.recv(&r1);
|
||||
// sel.recv(&r2);
|
||||
// sel.recv(&timeout);
|
||||
// loop {
|
||||
// match sel.ready() {
|
||||
// 0 => {
|
||||
// if r1.try_recv().is_ok() {
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// 1 => {
|
||||
// if r2.try_recv().is_ok() {
|
||||
// hits.fetch_add(1, Ordering::SeqCst);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// 2 => {
|
||||
// if timeout.try_recv().is_ok() {
|
||||
// break 'outer;
|
||||
// }
|
||||
// }
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// assert_eq!(hits.load(Ordering::SeqCst), 8);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness() {
|
||||
// const COUNT: usize = 30;
|
||||
|
||||
// for &dur in &[0, 1] {
|
||||
// let mut hits = [0usize; 2];
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// let r1 = tick(ms(dur));
|
||||
// let r2 = tick(ms(dur));
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r1) -> _ => hits[0] += 1,
|
||||
// recv(r2) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness_duplicates() {
|
||||
// const COUNT: usize = 30;
|
||||
|
||||
// for &dur in &[0, 1] {
|
||||
// let mut hits = [0usize; 5];
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// let r = tick(ms(dur));
|
||||
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r) -> _ => hits[0] += 1,
|
||||
// recv(r) -> _ => hits[1] += 1,
|
||||
// recv(r) -> _ => hits[2] += 1,
|
||||
// recv(r) -> _ => hits[3] += 1,
|
||||
// recv(r) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// }
|
||||
// }
|
557
vendor/flume/tests/zero.rs
vendored
Normal file
557
vendor/flume/tests/zero.rs
vendored
Normal file
@ -0,0 +1,557 @@
|
||||
//! Tests for the zero channel flavor.
|
||||
|
||||
extern crate crossbeam_utils;
|
||||
extern crate rand;
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use flume::{bounded, Receiver};
|
||||
use flume::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use flume::{SendError, SendTimeoutError, TrySendError};
|
||||
use crossbeam_utils::thread::scope;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
fn ms(ms: u64) -> Duration {
|
||||
Duration::from_millis(ms)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let (s, r) = bounded(0);
|
||||
assert_eq!(s.try_send(7), Err(TrySendError::Full(7)));
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capacity() {
|
||||
let (s, r) = bounded::<()>(0);
|
||||
assert_eq!(s.capacity(), Some(0));
|
||||
assert_eq!(r.capacity(), Some(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len_empty_full() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(s.is_empty(), true);
|
||||
assert_eq!(s.is_full(), true);
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r.is_full(), true);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| s.send(0).unwrap());
|
||||
scope.spawn(|_| r.recv().unwrap());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(s.is_empty(), true);
|
||||
assert_eq!(s.is_full(), true);
|
||||
assert_eq!(r.len(), 0);
|
||||
assert_eq!(r.is_empty(), true);
|
||||
assert_eq!(r.is_full(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_recv() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.try_recv(), Ok(7));
|
||||
thread::sleep(ms(500));
|
||||
assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv(), Ok(7));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(9));
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
s.send(8).unwrap();
|
||||
s.send(9).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_timeout() {
|
||||
let (s, r) = bounded::<i32>(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Err(RecvTimeoutError::Timeout));
|
||||
assert_eq!(r.recv_timeout(ms(1000)), Ok(7));
|
||||
assert_eq!(
|
||||
r.recv_timeout(ms(1000)),
|
||||
Err(RecvTimeoutError::Disconnected)
|
||||
);
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
s.send(7).unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_send() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(s.try_send(7), Err(TrySendError::Full(7)));
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(s.try_send(8), Ok(()));
|
||||
thread::sleep(ms(500));
|
||||
assert_eq!(s.try_send(9), Err(TrySendError::Disconnected(9)));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
s.send(7).unwrap();
|
||||
thread::sleep(ms(1000));
|
||||
s.send(8).unwrap();
|
||||
thread::sleep(ms(1000));
|
||||
s.send(9).unwrap();
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.recv(), Ok(7));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
assert_eq!(r.recv(), Ok(9));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_timeout() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(
|
||||
s.send_timeout(7, ms(1000)),
|
||||
Err(SendTimeoutError::Timeout(7))
|
||||
);
|
||||
assert_eq!(s.send_timeout(8, ms(1000)), Ok(()));
|
||||
assert_eq!(
|
||||
s.send_timeout(9, ms(1000)),
|
||||
Err(SendTimeoutError::Disconnected(9))
|
||||
);
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1500));
|
||||
assert_eq!(r.recv(), Ok(8));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len() {
|
||||
const COUNT: usize = 25_000;
|
||||
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(r.recv(), Ok(i));
|
||||
assert_eq!(r.len(), 0);
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
assert_eq!(s.len(), 0);
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert_eq!(r.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_wakes_sender() {
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert_eq!(s.send(()), Err(SendError(())));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(r);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_wakes_receiver() {
|
||||
let (s, r) = bounded::<()>(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
const COUNT: usize = 100_000;
|
||||
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(r.recv(), Ok(i));
|
||||
}
|
||||
assert!(r.recv().is_err());
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
const COUNT: usize = 25_000;
|
||||
const THREADS: usize = 4;
|
||||
|
||||
let (s, r) = bounded::<usize>(0);
|
||||
let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
|
||||
|
||||
scope(|scope| {
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..COUNT {
|
||||
let n = r.recv().unwrap();
|
||||
v[n].fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
});
|
||||
}
|
||||
for _ in 0..THREADS {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for c in v {
|
||||
assert_eq!(c.load(Ordering::SeqCst), THREADS);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_oneshot() {
|
||||
const COUNT: usize = 10_000;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (s, r) = bounded(1);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| r.recv().unwrap());
|
||||
scope.spawn(|_| s.send(0).unwrap());
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_iter() {
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
let (request_s, request_r) = bounded(0);
|
||||
let (response_s, response_r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
for x in response_r.try_iter() {
|
||||
count += x;
|
||||
if count == COUNT {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let _ = request_s.try_send(());
|
||||
}
|
||||
});
|
||||
|
||||
for _ in request_r.iter() {
|
||||
if response_s.send(1).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stress_timeout_two_threads() {
|
||||
const COUNT: usize = 100;
|
||||
|
||||
let (s, r) = bounded(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
loop {
|
||||
if let Ok(()) = s.send_timeout(i, ms(10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for i in 0..COUNT {
|
||||
if i % 2 == 0 {
|
||||
thread::sleep(ms(50));
|
||||
}
|
||||
loop {
|
||||
if let Ok(x) = r.recv_timeout(ms(10)) {
|
||||
assert_eq!(x, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drops() {
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct DropCounter;
|
||||
|
||||
impl Drop for DropCounter {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for _ in 0..100 {
|
||||
let steps = rng.gen_range(0..3_000);
|
||||
|
||||
DROPS.store(0, Ordering::SeqCst);
|
||||
let (s, r) = bounded::<DropCounter>(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
r.recv().unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(|_| {
|
||||
for _ in 0..steps {
|
||||
s.send(DropCounter).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
|
||||
drop(s);
|
||||
drop(r);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), steps);
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn fairness() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s1, r1) = bounded::<()>(0);
|
||||
// let (s2, r2) = bounded::<()>(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// let mut hits = [0usize; 2];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r1) -> _ => hits[0] += 1,
|
||||
// recv(r2) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// });
|
||||
|
||||
// let mut hits = [0usize; 2];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// send(s1, ()) -> _ => hits[0] += 1,
|
||||
// send(s2, ()) -> _ => hits[1] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn fairness_duplicates() {
|
||||
// const COUNT: usize = 10_000;
|
||||
|
||||
// let (s, r) = bounded::<()>(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// let mut hits = [0usize; 5];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// recv(r) -> _ => hits[0] += 1,
|
||||
// recv(r) -> _ => hits[1] += 1,
|
||||
// recv(r) -> _ => hits[2] += 1,
|
||||
// recv(r) -> _ => hits[3] += 1,
|
||||
// recv(r) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// });
|
||||
|
||||
// let mut hits = [0usize; 5];
|
||||
// for _ in 0..COUNT {
|
||||
// select! {
|
||||
// send(s, ()) -> _ => hits[0] += 1,
|
||||
// send(s, ()) -> _ => hits[1] += 1,
|
||||
// send(s, ()) -> _ => hits[2] += 1,
|
||||
// send(s, ()) -> _ => hits[3] += 1,
|
||||
// send(s, ()) -> _ => hits[4] += 1,
|
||||
// }
|
||||
// }
|
||||
// assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn recv_in_send() {
|
||||
// let (s, r) = bounded(0);
|
||||
|
||||
// scope(|scope| {
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(100));
|
||||
// r.recv()
|
||||
// });
|
||||
|
||||
// scope.spawn(|_| {
|
||||
// thread::sleep(ms(500));
|
||||
// s.send(()).unwrap();
|
||||
// });
|
||||
|
||||
// select! {
|
||||
// send(s, r.recv().unwrap()) -> _ => {}
|
||||
// }
|
||||
// })
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn channel_through_channel() {
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
type T = Box<dyn Any + Send>;
|
||||
|
||||
let (s, r) = bounded::<T>(0);
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(move |_| {
|
||||
let mut s = s;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
let (new_s, new_r) = bounded(0);
|
||||
let new_r: T = Box::new(Some(new_r));
|
||||
|
||||
s.send(new_r).unwrap();
|
||||
s = new_s;
|
||||
}
|
||||
});
|
||||
|
||||
scope.spawn(move |_| {
|
||||
let mut r = r;
|
||||
|
||||
for _ in 0..COUNT {
|
||||
r = r
|
||||
.recv()
|
||||
.unwrap()
|
||||
.downcast_mut::<Option<Receiver<T>>>()
|
||||
.unwrap()
|
||||
.take()
|
||||
.unwrap()
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
Reference in New Issue
Block a user