| 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 |