OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 //! Tests all functionality in the system package | |
6 //! | |
7 //! Test failure is defined as the function returning via panicking | |
8 //! and the result being caught in the test! macro. If a test function | |
9 //! returns without panicking, it is assumed to pass. | |
10 | |
11 #[macro_use] | |
12 extern crate mojo; | |
13 | |
14 #[macro_use] | |
15 mod util; | |
16 | |
17 use mojo::bindings::run_loop; | |
18 use mojo::bindings::run_loop::{RunLoop, Token, Handler, WaitError}; | |
19 use mojo::system::MOJO_INDEFINITE; | |
20 use mojo::system::message_pipe; | |
21 | |
22 use std::cell::Cell; | |
23 use std::rc::Rc; | |
24 | |
25 struct HandlerExpectReady {} | |
26 | |
27 impl Handler for HandlerExpectReady { | |
28 fn on_ready(&mut self, runloop: &mut RunLoop, token: Token) { | |
29 runloop.deregister(token); | |
30 } | |
31 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
32 panic!("Timed-out when expected ready"); | |
33 } | |
34 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
35 panic!("Error when expected ready"); | |
36 } | |
37 } | |
38 | |
39 struct HandlerExpectTimeout {} | |
40 | |
41 impl Handler for HandlerExpectTimeout { | |
42 fn on_ready(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
43 panic!("Ready when expected timeout"); | |
44 } | |
45 fn on_timeout(&mut self, runloop: &mut RunLoop, token: Token) { | |
46 runloop.deregister(token); | |
47 } | |
48 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
49 panic!("Error when expected timeout"); | |
50 } | |
51 } | |
52 | |
53 struct HandlerExpectError {} | |
54 | |
55 impl Handler for HandlerExpectError { | |
56 fn on_ready(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
57 panic!("Ready when expected error"); | |
58 } | |
59 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
60 panic!("Timed-out when expected error"); | |
61 } | |
62 fn on_error(&mut self, runloop: &mut RunLoop, token: Token, error: WaitError
) { | |
63 assert_eq!(error, WaitError::Unsatisfiable); | |
64 runloop.deregister(token); | |
65 } | |
66 } | |
67 | |
68 struct HandlerQuit {} | |
69 | |
70 impl Handler for HandlerQuit { | |
71 fn on_ready(&mut self, runloop: &mut RunLoop, _token: Token) { | |
72 runloop.quit(); | |
73 } | |
74 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
75 panic!("Timed-out when expected error"); | |
76 } | |
77 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
78 panic!("Error when expected ready"); | |
79 } | |
80 } | |
81 | |
82 struct HandlerRegister {} | |
83 | |
84 impl Handler for HandlerRegister { | |
85 fn on_ready(&mut self, runloop: &mut RunLoop, token: Token) { | |
86 let (_, endpt1) = message_pipe::create(mpflags!(Create::None)).unwrap(); | |
87 let _ = runloop.register(&endpt1, signals!(Signals::Writable), MOJO_INDE
FINITE, HandlerDeregisterOther { other: token }); | |
88 } | |
89 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
90 panic!("Timed-out when expected error"); | |
91 } | |
92 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
93 panic!("Error when expected ready"); | |
94 } | |
95 } | |
96 | |
97 struct HandlerDeregisterOther { | |
98 other: Token, | |
99 } | |
100 | |
101 impl Handler for HandlerDeregisterOther { | |
102 fn on_ready(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
103 panic!("Ready when expected error"); | |
104 } | |
105 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
106 panic!("Timed-out when expected error"); | |
107 } | |
108 fn on_error(&mut self, runloop: &mut RunLoop, token: Token, error: WaitError
) { | |
109 assert_eq!(error, WaitError::HandleClosed); | |
110 runloop.deregister(token); | |
111 runloop.deregister(self.other.clone()); | |
112 } | |
113 } | |
114 | |
115 struct HandlerReregister { | |
116 count: u64, | |
117 } | |
118 | |
119 impl Handler for HandlerReregister { | |
120 fn on_ready(&mut self, runloop: &mut RunLoop, token: Token) { | |
121 runloop.deregister(token); | |
122 } | |
123 fn on_timeout(&mut self, runloop: &mut RunLoop, token: Token) { | |
124 if self.count < 10 { | |
125 runloop.reregister(&token, signals!(Signals::Readable), 0); | |
126 self.count += 1; | |
127 } else { | |
128 runloop.reregister(&token, signals!(Signals::Writable), MOJO_INDEFIN
ITE); | |
129 } | |
130 } | |
131 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
132 panic!("Error when expected ready"); | |
133 } | |
134 } | |
135 | |
136 struct HandlerNesting { | |
137 count: u64, | |
138 } | |
139 | |
140 impl Handler for HandlerNesting { | |
141 fn on_ready(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
142 panic!("Ready when expected timeout"); | |
143 } | |
144 fn on_timeout(&mut self, runloop: &mut RunLoop, token: Token) { | |
145 let mut nested_runloop = run_loop::RunLoop::new(); | |
146 if self.count < 10 { | |
147 let handler = HandlerNesting { count: self.count + 1 }; | |
148 let (endpt0, _endpt1) = message_pipe::create(mpflags!(Create::None))
.unwrap(); | |
149 let _ = nested_runloop.register(&endpt0, signals!(Signals::Readable)
, 0, handler); | |
150 nested_runloop.run(); | |
151 } else { | |
152 let handler = HandlerNesting { count: self.count + 1 }; | |
153 let (endpt0, _) = message_pipe::create(mpflags!(Create::None)).unwra
p(); | |
154 let _ = nested_runloop.register(&endpt0, signals!(Signals::Readable)
, 0, handler); | |
155 nested_runloop.run(); | |
156 } | |
157 runloop.deregister(token); | |
158 } | |
159 fn on_error(&mut self, runloop: &mut RunLoop, token: Token, error: WaitError
) { | |
160 assert_eq!(error, WaitError::Unsatisfiable); | |
161 assert_eq!(self.count, 11); | |
162 runloop.deregister(token); | |
163 } | |
164 } | |
165 | |
166 struct HandlerBadNesting {} | |
167 | |
168 impl Handler for HandlerBadNesting { | |
169 fn on_ready(&mut self, runloop: &mut RunLoop, _token: Token) { | |
170 runloop.quit(); | |
171 } | |
172 fn on_timeout(&mut self, runloop: &mut RunLoop, _token: Token) { | |
173 runloop.run(); | |
174 } | |
175 fn on_error(&mut self, runloop: &mut RunLoop, _token: Token, _error: WaitErr
or) { | |
176 runloop.quit(); | |
177 } | |
178 } | |
179 | |
180 struct HandlerTasks { | |
181 count: Rc<Cell<u64>>, | |
182 } | |
183 | |
184 impl Handler for HandlerTasks { | |
185 fn on_ready(&mut self, runloop: &mut RunLoop, token: Token) { | |
186 let r = self.count.clone(); | |
187 let _ = runloop.post_task(move |_runloop| { | |
188 let val = (*r).get(); | |
189 (*r).set(val+1); | |
190 }, 10); | |
191 if (*self.count).get() > 10 { | |
192 runloop.deregister(token); | |
193 } | |
194 } | |
195 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
196 panic!("Timed-out when expected error"); | |
197 } | |
198 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
199 panic!("Error when expected ready"); | |
200 } | |
201 } | |
202 | |
203 struct NestedTasks { | |
204 count: Rc<Cell<u64>>, | |
205 quitter: bool, | |
206 } | |
207 | |
208 impl Handler for NestedTasks { | |
209 fn on_ready(&mut self, runloop: &mut RunLoop, token: Token) { | |
210 let r = self.count.clone(); | |
211 let quit = self.quitter; | |
212 let _ = runloop.post_task(move |runloop| { | |
213 let r2 = r.clone(); | |
214 let tk = token.clone(); | |
215 if (*r).get() < 10 { | |
216 let _ = runloop.post_task(move |_runloop| { | |
217 let val = (*r2).get(); | |
218 (*r2).set(val+1); | |
219 }, 0); | |
220 } else { | |
221 if quit { | |
222 runloop.quit(); | |
223 } else { | |
224 runloop.deregister(tk); | |
225 } | |
226 } | |
227 }, 0); | |
228 } | |
229 fn on_timeout(&mut self, _runloop: &mut RunLoop, _token: Token) { | |
230 panic!("Timed-out when expected error"); | |
231 } | |
232 fn on_error(&mut self, _runloop: &mut RunLoop, _token: Token, _error: WaitEr
ror) { | |
233 panic!("Error when expected ready"); | |
234 } | |
235 } | |
236 | |
237 tests! { | |
238 // Verifies that after adding and removing, we can run, exit and be | |
239 // left in a consistent state. | |
240 fn add_remove() { | |
241 run_loop::with_current(|runloop| { | |
242 let (endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).
unwrap(); | |
243 let token0 = runloop.register(&endpt0, signals!(Signals::Writable),
0, HandlerExpectReady {}); | |
244 let token1 = runloop.register(&endpt1, signals!(Signals::Writable),
0, HandlerExpectReady {}); | |
245 runloop.deregister(token1); | |
246 runloop.deregister(token0); | |
247 runloop.run(); | |
248 }) | |
249 } | |
250 | |
251 // Verifies that generated tokens are unique. | |
252 fn tokens() { | |
253 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
254 let mut vec = Vec::new(); | |
255 run_loop::with_current(|runloop| { | |
256 for _ in 0..10 { | |
257 vec.push(runloop.register(&endpt1, signals!(Signals::None), 0, H
andlerExpectReady {})); | |
258 } | |
259 for i in 0..10 { | |
260 for j in 0..10 { | |
261 if i != j { | |
262 assert!(vec[i] != vec[j]); | |
263 } | |
264 } | |
265 } | |
266 }); | |
267 } | |
268 | |
269 // Verifies that the handler's "on_ready" function is called. | |
270 fn notify_results() { | |
271 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
272 run_loop::with_current(|runloop| { | |
273 let _ = runloop.register(&endpt1, signals!(Signals::Writable), MOJO_
INDEFINITE, HandlerExpectReady {}); | |
274 runloop.run(); | |
275 }); | |
276 } | |
277 | |
278 // Verifies that the handler's "on_timeout" function is called. | |
279 fn notify_timeout() { | |
280 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
281 run_loop::with_current(|runloop| { | |
282 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0, Ha
ndlerExpectTimeout {}); | |
283 runloop.run(); | |
284 }); | |
285 } | |
286 | |
287 // Verifies that the handler's "on_error" function is called. | |
288 fn notify_error() { | |
289 // Drop the first endpoint immediately | |
290 let (_, endpt1) = message_pipe::create(mpflags!(Create::None)).unwrap(); | |
291 run_loop::with_current(|runloop| { | |
292 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0, Ha
ndlerExpectError {}); | |
293 runloop.run(); | |
294 }); | |
295 } | |
296 | |
297 // Verifies that the handler's "on_ready" function is called which only quit
s. | |
298 fn notify_ready_quit() { | |
299 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
300 run_loop::with_current(|runloop| { | |
301 let _ = runloop.register(&endpt1, signals!(Signals::Writable), MOJO_
INDEFINITE, HandlerQuit {}); | |
302 runloop.run(); | |
303 }); | |
304 } | |
305 | |
306 // Tests more complex behavior, i.e. the interaction between two handlers. | |
307 fn register_deregister() { | |
308 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
309 run_loop::with_current(|runloop| { | |
310 let _ = runloop.register(&endpt1, signals!(Signals::Writable), MOJO_
INDEFINITE, HandlerRegister {}); | |
311 runloop.run(); | |
312 }); | |
313 } | |
314 | |
315 // Tests reregistering. | |
316 fn reregister() { | |
317 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
318 run_loop::with_current(|runloop| { | |
319 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0, Ha
ndlerReregister { count: 0 }); | |
320 runloop.run(); | |
321 }); | |
322 } | |
323 | |
324 // Tests nesting run loops by having a handler create a new one. | |
325 fn nesting() { | |
326 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
327 run_loop::with_current(|runloop| { | |
328 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0, Ha
ndlerNesting { count: 0 }); | |
329 runloop.run(); | |
330 }); | |
331 } | |
332 | |
333 // Tests to make sure nesting with the SAME runloop fails. | |
334 #[should_panic] | |
335 fn bad_nesting() { | |
336 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
337 run_loop::with_current(|runloop| { | |
338 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0, Ha
ndlerBadNesting {}); | |
339 runloop.run(); | |
340 }); | |
341 } | |
342 | |
343 // Tests adding a simple task that adds a handler. | |
344 fn simple_task() { | |
345 run_loop::with_current(|runloop| { | |
346 let _ = runloop.post_task(|runloop| { | |
347 let (_, endpt1) = message_pipe::create(mpflags!(Create::None)).u
nwrap(); | |
348 let _ = runloop.register(&endpt1, signals!(Signals::Readable), 0
, HandlerExpectError {}); | |
349 }, 0); | |
350 runloop.run(); | |
351 }); | |
352 } | |
353 | |
354 // Tests using a handler that adds a bunch of tasks. | |
355 fn handler_tasks() { | |
356 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
357 let r = Rc::new(Cell::new(0)); | |
358 run_loop::with_current(|runloop| { | |
359 let _ = runloop.register(&endpt1, signals!(Signals::Writable), 0, Ha
ndlerTasks { count: r.clone() }); | |
360 runloop.run(); | |
361 assert!((*r).get() >= 11); | |
362 }); | |
363 } | |
364 | |
365 // Tests using a handler that adds a bunch of tasks. | |
366 fn nested_tasks() { | |
367 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
368 let r = Rc::new(Cell::new(0)); | |
369 run_loop::with_current(|runloop| { | |
370 let _ = runloop.register(&endpt1, signals!(Signals::Writable), 0, Ne
stedTasks { count: r.clone(), quitter: false }); | |
371 runloop.run(); | |
372 assert!((*r).get() >= 10); | |
373 }); | |
374 } | |
375 | |
376 // Tests using a handler that adds a bunch of tasks. | |
377 fn nested_tasks_quit() { | |
378 let (_endpt0, endpt1) = message_pipe::create(mpflags!(Create::None)).unw
rap(); | |
379 let r = Rc::new(Cell::new(0)); | |
380 run_loop::with_current(|runloop| { | |
381 let _ = runloop.register(&endpt1, signals!(Signals::Writable), 0, Ne
stedTasks { count: r.clone(), quitter: true }); | |
382 runloop.run(); | |
383 assert!((*r).get() >= 10); | |
384 }); | |
385 } | |
386 } | |
OLD | NEW |