| use {localhost, sleep_ms}; |
| use mio::*; |
| use mio::deprecated::{EventLoop, EventLoopBuilder, Handler, Sender, NotifyError}; |
| use mio::net::TcpListener; |
| use std::thread; |
| |
| struct TestHandler { |
| sender: Sender<String>, |
| notify: usize |
| } |
| |
| impl TestHandler { |
| fn new(sender: Sender<String>) -> TestHandler { |
| TestHandler { |
| sender: sender, |
| notify: 0 |
| } |
| } |
| } |
| |
| impl Handler for TestHandler { |
| type Timeout = usize; |
| type Message = String; |
| |
| fn notify(&mut self, event_loop: &mut EventLoop<TestHandler>, msg: String) { |
| match self.notify { |
| 0 => { |
| assert!(msg == "First", "actual={}", msg); |
| self.sender.send("Second".to_string()).unwrap(); |
| } |
| 1 => { |
| assert!(msg == "Second", "actual={}", msg); |
| event_loop.shutdown(); |
| } |
| v => panic!("unexpected value for notify; val={}", v) |
| } |
| |
| self.notify += 1; |
| } |
| } |
| |
| #[test] |
| pub fn test_notify() { |
| debug!("Starting TEST_NOTIFY"); |
| let mut event_loop = EventLoop::new().unwrap(); |
| |
| let addr = localhost(); |
| |
| // Setup a server socket so that the event loop blocks |
| let srv = TcpListener::bind(&addr).unwrap(); |
| |
| event_loop.register(&srv, Token(0), Ready::readable() | Ready::writable(), PollOpt::edge()).unwrap(); |
| |
| let sender = event_loop.channel(); |
| |
| thread::spawn(move || { |
| sleep_ms(1_000); |
| sender.send("First".to_string()).unwrap(); |
| }); |
| |
| let sender = event_loop.channel(); |
| let mut handler = TestHandler::new(sender); |
| |
| // Start the event loop |
| event_loop.run(&mut handler).unwrap(); |
| |
| assert!(handler.notify == 2, "actual={}", handler.notify); |
| } |
| |
| #[test] |
| pub fn test_notify_capacity() { |
| use std::sync::mpsc::*; |
| use std::thread; |
| |
| struct Capacity(Receiver<i32>); |
| |
| impl Handler for Capacity { |
| type Message = i32; |
| type Timeout = (); |
| |
| fn notify(&mut self, event_loop: &mut EventLoop<Capacity>, msg: i32) { |
| if msg == 1 { |
| self.0.recv().unwrap(); |
| } else if msg == 3 { |
| event_loop.shutdown(); |
| } |
| } |
| } |
| |
| let mut builder = EventLoopBuilder::new(); |
| builder.notify_capacity(1); |
| |
| let (tx, rx) = channel::<i32>(); |
| let mut event_loop = builder.build().unwrap(); |
| let notify = event_loop.channel(); |
| |
| let handle = thread::spawn(move || { |
| let mut handler = Capacity(rx); |
| event_loop.run(&mut handler).unwrap(); |
| }); |
| |
| assert!(notify.send(1).is_ok()); |
| |
| loop { |
| if notify.send(2).is_err() { |
| break; |
| } |
| } |
| |
| tx.send(1).unwrap(); |
| |
| loop { |
| if notify.send(3).is_ok() { |
| break; |
| } |
| } |
| |
| handle.join().unwrap(); |
| } |
| |
| #[test] |
| pub fn test_notify_drop() { |
| use std::sync::mpsc::{self,Sender}; |
| use std::thread; |
| |
| struct MessageDrop(Sender<u8>); |
| |
| impl Drop for MessageDrop { |
| fn drop(&mut self) { |
| self.0.send(0).unwrap(); |
| } |
| } |
| |
| struct DummyHandler; |
| |
| impl Handler for DummyHandler { |
| type Timeout = (); |
| type Message = MessageDrop; |
| |
| fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: MessageDrop) { |
| msg.0.send(1).unwrap(); |
| drop(msg); |
| // We stop after the first message |
| event_loop.shutdown(); |
| } |
| } |
| |
| let (tx_notif_1, rx_notif_1) = mpsc::channel(); |
| let (tx_notif_2, rx_notif_2) = mpsc::channel(); |
| let (tx_notif_3, _unused) = mpsc::channel(); |
| let (tx_exit_loop, rx_exit_loop) = mpsc::channel(); |
| let (tx_drop_loop, rx_drop_loop) = mpsc::channel(); |
| |
| let mut event_loop = EventLoop::new().unwrap(); |
| let notify = event_loop.channel(); |
| |
| let handle = thread::spawn(move || { |
| let mut handler = DummyHandler; |
| event_loop.run(&mut handler).unwrap(); |
| |
| // Confirmation we exited the loop |
| tx_exit_loop.send(()).unwrap(); |
| |
| // Order to drop the loop |
| rx_drop_loop.recv().unwrap(); |
| drop(event_loop); |
| }); |
| notify.send(MessageDrop(tx_notif_1)).unwrap(); |
| assert_eq!(rx_notif_1.recv().unwrap(), 1); // Response from the loop |
| assert_eq!(rx_notif_1.recv().unwrap(), 0); // Drop notification |
| |
| // We wait for the event loop to exit before sending the second notification |
| rx_exit_loop.recv().unwrap(); |
| notify.send(MessageDrop(tx_notif_2)).unwrap(); |
| |
| // We ensure the message is indeed stuck in the queue |
| sleep_ms(100); |
| assert!(rx_notif_2.try_recv().is_err()); |
| |
| // Give the order to drop the event loop |
| tx_drop_loop.send(()).unwrap(); |
| assert_eq!(rx_notif_2.recv().unwrap(), 0); // Drop notification |
| |
| // Check that sending a new notification will return an error |
| // We should also get our message back |
| match notify.send(MessageDrop(tx_notif_3)).unwrap_err() { |
| NotifyError::Closed(Some(..)) => {} |
| _ => panic!(), |
| } |
| |
| handle.join().unwrap(); |
| } |