1 // These tests cannot run as a regular test because cargo would spawn a thread to run it,
2 // failing the signal masking. So we make our own, non-threaded harnessing
3 
4 #[cfg(unix)]
main()5 fn main() {
6     for test in self::test::TESTS {
7         test();
8         // reset the signal mask between tests
9         self::test::reset_mask();
10     }
11 }
12 
13 #[cfg(not(unix))]
main()14 fn main() {}
15 
16 #[cfg(unix)]
17 mod test {
18     extern crate calloop;
19     extern crate nix;
20 
21     use std::io;
22     use std::time::Duration;
23 
24     use self::calloop::signals::{Signal, Signals};
25     use self::calloop::EventLoop;
26 
27     use self::nix::sys::signal::{kill, SigSet};
28     use self::nix::unistd::Pid;
29 
30     pub const TESTS: &'static [fn()] = &[single_usr1, usr2_added_afterwards, usr2_signal_removed];
31 
reset_mask()32     pub fn reset_mask() {
33         SigSet::empty().thread_set_mask().unwrap();
34     }
35 
single_usr1()36     fn single_usr1() {
37         let mut event_loop = EventLoop::new().unwrap();
38 
39         let mut signal_received = false;
40 
41         let _signal_source = event_loop
42             .handle()
43             .insert_source(
44                 Signals::new(&[Signal::SIGUSR1]).unwrap(),
45                 move |evt, rcv| {
46                     assert!(evt.signal() == Signal::SIGUSR1);
47                     *rcv = true;
48                 },
49             )
50             .map_err(Into::<io::Error>::into)
51             .unwrap();
52 
53         // send ourselves a SIGUSR1
54         kill(Pid::this(), Signal::SIGUSR1).unwrap();
55 
56         event_loop
57             .dispatch(Some(Duration::from_millis(10)), &mut signal_received)
58             .unwrap();
59 
60         assert!(signal_received);
61     }
62 
usr2_added_afterwards()63     fn usr2_added_afterwards() {
64         let mut event_loop = EventLoop::new().unwrap();
65 
66         let mut signal_received = None;
67 
68         let mut signal_source = event_loop
69             .handle()
70             .insert_source(
71                 Signals::new(&[Signal::SIGUSR1]).unwrap(),
72                 move |evt, rcv| {
73                     *rcv = Some(evt.signal());
74                 },
75             )
76             .map_err(Into::<io::Error>::into)
77             .unwrap();
78 
79         signal_source.add_signals(&[Signal::SIGUSR2]).unwrap();
80 
81         // send ourselves a SIGUSR2
82         kill(Pid::this(), Signal::SIGUSR2).unwrap();
83 
84         event_loop
85             .dispatch(Some(Duration::from_millis(10)), &mut signal_received)
86             .unwrap();
87 
88         assert_eq!(signal_received, Some(Signal::SIGUSR2));
89     }
90 
usr2_signal_removed()91     fn usr2_signal_removed() {
92         let mut event_loop = EventLoop::new().unwrap();
93 
94         let mut signal_received = None;
95 
96         let mut signal_source = event_loop
97             .handle()
98             .insert_source(
99                 Signals::new(&[Signal::SIGUSR1, Signal::SIGUSR2]).unwrap(),
100                 move |evt, rcv| {
101                     *rcv = Some(evt.signal());
102                 },
103             )
104             .map_err(Into::<io::Error>::into)
105             .unwrap();
106 
107         signal_source.remove_signals(&[Signal::SIGUSR2]).unwrap();
108 
109         // block sigusr2 anyway, to not be killed by it
110         let mut set = SigSet::empty();
111         set.add(Signal::SIGUSR2);
112         set.thread_block().unwrap();
113 
114         // send ourselves a SIGUSR2
115         kill(Pid::this(), Signal::SIGUSR2).unwrap();
116 
117         event_loop
118             .dispatch(Some(Duration::from_millis(10)), &mut signal_received)
119             .unwrap();
120 
121         // we should not have received anything, as we don't listen to SIGUSR2 any more
122         assert!(signal_received.is_none());
123 
124         // swap the signals from [SIGUSR1] to [SIGUSR2]
125         signal_source.set_signals(&[Signal::SIGUSR2]).unwrap();
126 
127         event_loop
128             .dispatch(Some(Duration::from_millis(10)), &mut signal_received)
129             .unwrap();
130 
131         // we should get back the pending SIGUSR2 now
132         assert_eq!(signal_received, Some(Signal::SIGUSR2));
133     }
134 }
135