更新libclamav库1.0.0版本
This commit is contained in:
336
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/after.rs
vendored
Normal file
336
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/after.rs
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
//! Tests for the after channel flavor.
|
||||
|
||||
#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow
|
||||
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crossbeam_channel::{after, select, 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!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
thread::sleep(ms(100));
|
||||
|
||||
assert_eq!(r.len(), 1);
|
||||
assert!(!r.is_empty());
|
||||
assert!(r.is_full());
|
||||
|
||||
r.try_recv().unwrap();
|
||||
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
}
|
||||
744
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/array.rs
vendored
Normal file
744
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/array.rs
vendored
Normal file
@@ -0,0 +1,744 @@
|
||||
//! Tests for the array channel flavor.
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_channel::{bounded, select, Receiver};
|
||||
use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use crossbeam_channel::{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!(s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert!(!s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 1);
|
||||
assert!(!r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 2);
|
||||
assert!(!s.is_empty());
|
||||
assert!(s.is_full());
|
||||
assert_eq!(r.len(), 2);
|
||||
assert!(!r.is_empty());
|
||||
assert!(r.is_full());
|
||||
|
||||
r.recv().unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert!(!s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 1);
|
||||
assert!(!r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
}
|
||||
|
||||
#[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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn len() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 25_000;
|
||||
#[cfg(miri)]
|
||||
const CAP: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const RUNS: usize = 10;
|
||||
#[cfg(not(miri))]
|
||||
const RUNS: usize = 100;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 10_000;
|
||||
|
||||
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..STEPS);
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panic_on_drop() {
|
||||
struct Msg1<'a>(&'a mut bool);
|
||||
impl Drop for Msg1<'_> {
|
||||
fn drop(&mut self) {
|
||||
if *self.0 && !std::thread::panicking() {
|
||||
panic!("double drop");
|
||||
} else {
|
||||
*self.0 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Msg2<'a>(&'a mut bool);
|
||||
impl Drop for Msg2<'_> {
|
||||
fn drop(&mut self) {
|
||||
if *self.0 {
|
||||
panic!("double drop");
|
||||
} else {
|
||||
*self.0 = true;
|
||||
panic!("first drop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normal
|
||||
let (s, r) = bounded(2);
|
||||
let (mut a, mut b) = (false, false);
|
||||
s.send(Msg1(&mut a)).unwrap();
|
||||
s.send(Msg1(&mut b)).unwrap();
|
||||
drop(s);
|
||||
drop(r);
|
||||
assert!(a);
|
||||
assert!(b);
|
||||
|
||||
// panic on drop
|
||||
let (s, r) = bounded(2);
|
||||
let (mut a, mut b) = (false, false);
|
||||
s.send(Msg2(&mut a)).unwrap();
|
||||
s.send(Msg2(&mut b)).unwrap();
|
||||
drop(s);
|
||||
let res = std::panic::catch_unwind(move || {
|
||||
drop(r);
|
||||
});
|
||||
assert_eq!(
|
||||
*res.unwrap_err().downcast_ref::<&str>().unwrap(),
|
||||
"first drop"
|
||||
);
|
||||
assert!(a);
|
||||
// Elements after the panicked element will leak.
|
||||
assert!(!b);
|
||||
}
|
||||
2141
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/golang.rs
vendored
Normal file
2141
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/golang.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
110
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/iter.rs
vendored
Normal file
110
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/iter.rs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
//! Tests for iteration over receivers.
|
||||
|
||||
use crossbeam_channel::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!(iter.next().is_none());
|
||||
}
|
||||
|
||||
#[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!(iter.next().is_none());
|
||||
}
|
||||
582
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/list.rs
vendored
Normal file
582
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/list.rs
vendored
Normal file
@@ -0,0 +1,582 @@
|
||||
//! Tests for the list channel flavor.
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_channel::{select, unbounded, Receiver};
|
||||
use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use crossbeam_channel::{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!(s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
s.send(()).unwrap();
|
||||
|
||||
assert_eq!(s.len(), 1);
|
||||
assert!(!s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 1);
|
||||
assert!(!r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
r.recv().unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert!(s.is_empty());
|
||||
assert!(!s.is_full());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // this test makes timing assumptions, but Miri is so slow it violates them
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(s.try_send(i), Ok(()));
|
||||
}
|
||||
|
||||
drop(r);
|
||||
assert_eq!(s.try_send(777), Err(TrySendError::Disconnected(777)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..COUNT {
|
||||
assert_eq!(s.send(i), Ok(()));
|
||||
}
|
||||
|
||||
drop(r);
|
||||
assert_eq!(s.send(777), Err(SendError(777)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_timeout() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 1000;
|
||||
|
||||
let (s, r) = unbounded();
|
||||
for i in 0..COUNT {
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
}
|
||||
|
||||
#[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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const RUNS: usize = 20;
|
||||
#[cfg(not(miri))]
|
||||
const RUNS: usize = 100;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 10_000;
|
||||
|
||||
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..STEPS);
|
||||
let additional = rng.gen_range(0..STEPS / 10);
|
||||
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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();
|
||||
}
|
||||
2129
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/mpsc.rs
vendored
Normal file
2129
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/mpsc.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
95
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/never.rs
vendored
Normal file
95
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/never.rs
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
//! Tests for the never channel flavor.
|
||||
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crossbeam_channel::{never, select, 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!(r.is_empty());
|
||||
assert!(r.is_full());
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
852
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/ready.rs
vendored
Normal file
852
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/ready.rs
vendored
Normal file
@@ -0,0 +1,852 @@
|
||||
//! Tests for channel readiness using the `Select` struct.
|
||||
|
||||
#![allow(clippy::drop_copy)]
|
||||
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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));
|
||||
}
|
||||
|
||||
loop {
|
||||
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));
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut sel = Select::new();
|
||||
sel.recv(&r);
|
||||
match sel.ready_timeout(ms(100)) {
|
||||
Err(_) => {}
|
||||
Ok(0) => {
|
||||
assert_eq!(r.try_recv(), Ok(i));
|
||||
break;
|
||||
}
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const COUNT: usize = 100_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() > 0));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
112
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/same_channel.rs
vendored
Normal file
112
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/same_channel.rs
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
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));
|
||||
}
|
||||
1328
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/select.rs
vendored
Normal file
1328
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/select.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1480
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/select_macro.rs
vendored
Normal file
1480
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/select_macro.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
53
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/thread_locals.rs
vendored
Normal file
53
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/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.
|
||||
|
||||
#![cfg(not(miri))] // Miri detects that this test is buggy: the destructor of `FOO` uses `std::thread::current()`!
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_channel::{select, 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();
|
||||
}
|
||||
352
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/tick.rs
vendored
Normal file
352
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/tick.rs
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
//! Tests for the tick channel flavor.
|
||||
|
||||
#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow
|
||||
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crossbeam_channel::{after, select, 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!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
|
||||
thread::sleep(ms(100));
|
||||
|
||||
assert_eq!(r.len(), 1);
|
||||
assert!(!r.is_empty());
|
||||
assert!(r.is_full());
|
||||
|
||||
r.try_recv().unwrap();
|
||||
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(!r.is_full());
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
|
||||
#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
|
||||
#[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));
|
||||
}
|
||||
}
|
||||
587
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/zero.rs
vendored
Normal file
587
clamav/libclamav_rust/.cargo/vendor/crossbeam-channel/tests/zero.rs
vendored
Normal file
@@ -0,0 +1,587 @@
|
||||
//! Tests for the zero channel flavor.
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_channel::{bounded, select, Receiver};
|
||||
use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError};
|
||||
use crossbeam_channel::{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!(s.is_empty());
|
||||
assert!(s.is_full());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(r.is_full());
|
||||
|
||||
scope(|scope| {
|
||||
scope.spawn(|_| s.send(0).unwrap());
|
||||
scope.spawn(|_| r.recv().unwrap());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(s.len(), 0);
|
||||
assert!(s.is_empty());
|
||||
assert!(s.is_full());
|
||||
assert_eq!(r.len(), 0);
|
||||
assert!(r.is_empty());
|
||||
assert!(r.is_full());
|
||||
}
|
||||
|
||||
#[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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
thread::sleep(ms(1000));
|
||||
drop(s);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spsc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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_eq!(r.recv(), Err(RecvError));
|
||||
});
|
||||
scope.spawn(move |_| {
|
||||
for i in 0..COUNT {
|
||||
s.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mpmc() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const RUNS: usize = 20;
|
||||
#[cfg(not(miri))]
|
||||
const RUNS: usize = 100;
|
||||
#[cfg(miri)]
|
||||
const STEPS: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
const STEPS: usize = 10_000;
|
||||
|
||||
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..STEPS);
|
||||
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 100;
|
||||
#[cfg(not(miri))]
|
||||
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() {
|
||||
#[cfg(miri)]
|
||||
const COUNT: usize = 50;
|
||||
#[cfg(not(miri))]
|
||||
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