diff --git a/crossbeam-channel/tests/golang.rs b/crossbeam-channel/tests/golang.rs index e999aea36..69a9315a0 100644 --- a/crossbeam-channel/tests/golang.rs +++ b/crossbeam-channel/tests/golang.rs @@ -9,14 +9,16 @@ //! - https://golang.org/LICENSE //! - https://golang.org/PATENTS +use std::alloc::{GlobalAlloc, Layout, System}; use std::any::Any; use std::cell::Cell; use std::collections::HashMap; +use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::time::Duration; -use crossbeam_channel::{bounded, select, tick, Receiver, Select, Sender}; +use crossbeam_channel::{bounded, select, tick, unbounded, Receiver, Select, Sender}; fn ms(ms: u64) -> Duration { Duration::from_millis(ms) @@ -111,6 +113,12 @@ fn make(cap: usize) -> Chan { } } +fn make_unbounded() -> Chan { + let (s, r) = unbounded(); + Chan { + inner: Arc::new(Mutex::new(ChanInner { s: Some(s), r })), + } +} #[derive(Clone)] struct WaitGroup(Arc); @@ -159,6 +167,27 @@ impl Drop for Defer { } } +struct Counter; + +static ALLOCATED: AtomicUsize = AtomicUsize::new(0); +unsafe impl GlobalAlloc for Counter { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let ret = System.alloc(layout); + if !ret.is_null() { + ALLOCATED.fetch_add(layout.size(), SeqCst); + } + return ret; + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + System.dealloc(ptr, layout); + ALLOCATED.fetch_sub(layout.size(), SeqCst); + } +} + +#[global_allocator] +static A: Counter = Counter; + macro_rules! defer { ($body:expr) => { let _defer = Defer { @@ -660,7 +689,44 @@ mod select { // https://github.com/golang/go/blob/master/test/chan/select2.go mod select2 { - // TODO + use super::*; + + #[test] + fn main() { + fn sender(c: &Chan, n: i32) { + for _ in 0..n { + c.send(1); + } + } + + fn receiver(c: &Chan, dummy: &Chan, n: i32) { + for _ in 0..n { + select! { + recv(c.rx()) -> _ => { + () + } + recv(dummy.rx()) -> _ => { + panic!("dummy"); + } + } + } + } + + let c = make_unbounded::(); + let dummy = make_unbounded::(); + + ALLOCATED.store(0, SeqCst); + + go!(c, sender(&c, 100000)); + receiver(&c, &dummy, 100000); + + let alloc = ALLOCATED.load(SeqCst); + + go!(c, sender(&c, 100000)); + receiver(&c, &dummy, 100000); + + assert!(!(ALLOCATED.load(SeqCst) > alloc && (ALLOCATED.load(SeqCst) - alloc) > 110000)) + } } // https://github.com/golang/go/blob/master/test/chan/select3.go