gorust 0.1.7

Go-style concurrency in Rust - bringing Go-style concurrency patterns to Rust with familiar primitives like goroutines and channels
Documentation
#[cfg(test)]
mod channel_tests {
    use gorust::channel::{self, Channel, RecvError, SendError};
    use gorust::go;
    use gorust::sync::WaitGroup;
    use gorust::Runtime;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};

    #[test]
    fn test_unbuffered_channel() {
        Runtime::init();
        
        let (tx, rx) = channel::new::<i32>();
        let wg = WaitGroup::new();
        
        wg.add(1);
        let tx_clone = tx.clone();
        let wg_clone = wg.clone();
        go(move || {
            tx_clone.send(42).unwrap();
            wg_clone.done();
        });
        
        let value = rx.recv().unwrap();
        assert_eq!(value, 42);
        
        wg.wait();
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_buffered_channel() {
        Runtime::init();
        
        let (tx, rx) = channel::new_with_capacity::<String>(10);
        
        tx.send("hello".to_string()).unwrap();
        tx.send("world".to_string()).unwrap();
        
        assert_eq!(rx.recv().unwrap(), "hello");
        assert_eq!(rx.recv().unwrap(), "world");
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_channel_close() {
        Runtime::init();
        
        let (tx, rx) = channel::new::<i32>();
        tx.close();
        
        assert!(tx.is_closed());
        assert!(rx.is_closed());
        
        let result = tx.send(1);
        assert!(matches!(result, Err(SendError::Disconnected(_))));
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_recv_from_closed_channel() {
        Runtime::init();
        
        let (tx, rx) = channel::new_with_capacity::<i32>(1);
        tx.send(1).unwrap();
        tx.close();
        
        assert_eq!(rx.recv().unwrap(), 1);
        
        let result = rx.recv();
        assert!(matches!(result, Err(RecvError::Disconnected)));
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_try_send_full() {
        Runtime::init();
        
        let (tx, _rx) = channel::new_with_capacity::<i32>(1);
        tx.send(1).unwrap();
        
        let result = tx.try_send(2);
        assert!(matches!(result, Err(SendError::Full(2))));
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_multiple_senders_receivers() {
        Runtime::init();
        
        let (tx, rx) = channel::new_with_capacity::<i32>(100);
        let counter = Arc::new(AtomicUsize::new(0));
        let wg = WaitGroup::new();
        
        for i in 0..10 {
            wg.add(1);
            let tx_clone = tx.clone();
            let counter_clone = counter.clone();
            let wg_clone = wg.clone();
            go(move || {
                for j in 0..10 {
                    tx_clone.send(i * 10 + j).unwrap();
                    counter_clone.fetch_add(1, Ordering::Relaxed);
                }
                wg_clone.done();
            });
        }
        
        wg.wait();
        
        let mut received = 0;
        while received < 100 {
            if let Ok(_) = rx.try_recv() {
                received += 1;
            }
        }
        
        assert_eq!(received, 100);
        assert_eq!(counter.load(Ordering::Relaxed), 100);
        
        Runtime::wait_and_shutdown();
    }
}

#[cfg(test)]
mod sync_tests {
    use gorust::sync::{WaitGroup, Mutex, RWMutex, Pool, Context, AtomicCounter, Once};
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::time::Duration;

    #[test]
    fn test_waitgroup() {
        let wg = WaitGroup::new();
        let counter = Arc::new(AtomicUsize::new(0));
        
        for i in 0..5 {
            wg.add(1);
            let counter_clone = counter.clone();
            let wg_clone = wg.clone();
            std::thread::spawn(move || {
                counter_clone.fetch_add(i, Ordering::Relaxed);
                wg_clone.done();
            });
        }
        
        wg.wait();
        assert_eq!(counter.load(Ordering::Relaxed), 10);
    }

    #[test]
    fn test_mutex() {
        let mutex = Mutex::new(0);
        
        {
            let mut guard = mutex.lock();
            *guard += 1;
        }
        
        assert_eq!(*mutex.lock(), 1);
    }

    #[test]
    fn test_rwlock() {
        let rwlock = RWMutex::new(vec![1, 2, 3]);
        
        {
            let read_guard = rwlock.read();
            assert_eq!(read_guard.len(), 3);
        }
        
        {
            let mut write_guard = rwlock.write();
            write_guard.push(4);
        }
        
        assert_eq!(*rwlock.read(), vec![1, 2, 3, 4]);
    }

    #[test]
    fn test_pool() {
        let pool = Pool::new(|| String::from("default"), 10);
        
        let s1 = pool.get();
        assert_eq!(s1, "default");
        pool.put(s1);
        
        assert_eq!(pool.len(), 1);
    }

    #[test]
    fn test_context_background() {
        let ctx = Context::background();
        assert!(!ctx.done());
        assert!(ctx.err().is_none());
        assert!(ctx.deadline().is_none());
    }

    #[test]
    fn test_context_with_cancel() {
        let parent = Context::background();
        let (child, cancel) = Context::with_cancel(parent);
        
        assert!(!child.done());
        
        cancel();
        
        assert!(child.done());
        assert_eq!(child.err().unwrap(), "context canceled");
    }

    #[test]
    fn test_context_with_timeout() {
        let parent = Context::background();
        let (child, _cancel) = Context::with_timeout(parent, Duration::from_millis(50));
        
        assert!(!child.done());
        assert!(child.deadline().is_some());
        
        std::thread::sleep(Duration::from_millis(100));
        
        assert!(child.is_expired());
    }

    #[test]
    fn test_atomic_counter() {
        let counter = AtomicCounter::new();
        
        counter.inc();
        counter.inc();
        counter.dec();
        
        assert_eq!(counter.get(), 1);
    }

    #[test]
    fn test_once() {
        let once = Arc::new(Once::new());
        let counter = Arc::new(AtomicUsize::new(0));
        
        let mut handles = vec![];
        for _ in 0..10 {
            let counter_clone = counter.clone();
            let once_clone = once.clone();
            handles.push(std::thread::spawn(move || {
                once_clone.call_once(|| {
                    counter_clone.fetch_add(1, Ordering::Relaxed);
                });
            }));
        }
        
        for handle in handles {
            handle.join().unwrap();
        }
        
        assert_eq!(counter.load(Ordering::Relaxed), 1);
    }
}

#[cfg(test)]
mod timer_tests {
    use gorust::timer::{sleep, sleep_ms};
    use gorust::Runtime;
    use std::time::Instant;

    #[test]
    fn test_sleep_ms() {
        Runtime::init();
        
        let start = Instant::now();
        sleep_ms(50);
        let elapsed = start.elapsed();
        
        assert!(elapsed.as_millis() >= 50);
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_sleep_duration() {
        Runtime::init();
        
        let start = Instant::now();
        sleep(std::time::Duration::from_millis(100));
        let elapsed = start.elapsed();
        
        assert!(elapsed.as_millis() >= 100);
        
        Runtime::wait_and_shutdown();
    }
}

#[cfg(test)]
mod select_tests {
    use gorust::channel;
    use gorust::g_select::{Select, SelectOutcome};
    use gorust::Runtime;

    #[test]
    fn test_select_non_blocking() {
        Runtime::init();
        
        let (tx1, rx1) = channel::new_with_capacity::<i32>(1);
        let (_tx2, rx2) = channel::new_with_capacity::<i32>(1);
        
        tx1.send(42).unwrap();
        
        let result = Select::new()
            .recv(rx1)
            .recv(rx2)
            .with_default()
            .execute();
        
        assert!(result.is_received());
        
        Runtime::wait_and_shutdown();
    }

    #[test]
    fn test_select_default() {
        Runtime::init();
        
        let (_tx1, rx1) = channel::new_with_capacity::<i32>(1);
        let (_tx2, rx2) = channel::new_with_capacity::<i32>(1);
        
        let result = Select::new()
            .recv(rx1)
            .recv(rx2)
            .with_default()
            .execute();
        
        assert!(result.is_default());
        
        Runtime::wait_and_shutdown();
    }
}