def once():
            synchronizer = ThreadSynchronizer()
            try:
                reactor = IOEventReactor(log_channel=chan)
                assert not reactor._event_loop_thread
                assert not reactor._poller
                assert not reactor.running
                assert reactor._reactor_state == REACTOR_STOPPED
                reactor.start()

                event_log = []
                def handle_event(reactor, fd, eventmask, timestamp):
                    event_log.append((reactor, fd, eventmask))
                    if fd is synchronizer.event_pipe.fileno():
                        synchronizer.sync_from_reactor_thread()
                    if eventmask & META_READ_EV:
                        chan.debug('read event (reactor state=%i)'%reactor._reactor_state)
                        return False
                    elif eventmask & META_WRITE_EV:
                        chan.debug(
                            'write event (reactor state=%i)'%reactor._reactor_state)
                    elif eventmask & META_DISCONNECTED_EV:
                        chan.debug(
                            'disconnected (reactor state=%i)'%reactor._reactor_state)
                        return True
                    elif eventmask == META_REACTOR_SHUTDOWN_EV:
                        chan.debug(
                            'shutdown event (reactor state=%i)'%reactor._reactor_state)
                        return True
                    else:
                        chan.error(
                            'unknown event (reactor state=%i)'%reactor._reactor_state)
                        return True
                reactor.register_handler(synchronizer.event_pipe, handle_event)
                #

                synchronizer.sync_from_main()
                assert len(event_log) == 1
                x = 15
                for _i in xrange(x):
                    synchronizer.sync_from_main()

                assert len(event_log) == x+1, len(event_log)

                assert reactor._reactor_state in (REACTOR_POLLING, REACTOR_DISPATCHING)
                assert reactor.running
                synchronizer.sync_from_main()
                assert reactor._reactor_state in (REACTOR_POLLING, REACTOR_DISPATCHING)
                for _reactor, fd, eventmask in event_log:
                    assert _reactor is reactor
                    assert fd is synchronizer.event_pipe.fileno()
                    assert eventmask is POLLIN
            finally:
                synchronizer.sync_from_main(callback=lambda : reactor.stop())
                assert reactor._reactor_state == REACTOR_STOPPED
                assert event_log[-1][-1] == META_REACTOR_SHUTDOWN_EV
def test_with_abstract_handler():
    reactor = IOEventReactor()
    handler = AbstractIOEventHandler()

    assert not reactor.running
    assert handler.event_count == 0
    assert handler.last_event_time == 0

    @raises(NotImplementedError)
    def test_abstract_meth(meth, *args, **kws):
        meth(*args, **kws)

    for i, event in enumerate((POLLIN, POLLPRI,
                               POLLOUT,
                               POLLHUP, POLLNVAL, POLLERR,
                               (POLLHUP | POLLNVAL),
                               )):
        args = dict(reactor=None, fd=1, eventmask=event, timestamp=1)
        test_abstract_meth(handler, **args) # __call__ alias
        test_abstract_meth(handler.handle_event, **args)
        assert handler.event_count == (i+1)*2
        assert handler.last_event_time

    test_abstract_meth(handler._handle_read_event, 0)
    test_abstract_meth(handler._handle_write_event, 0)
    test_abstract_meth(handler._close_descriptor, 0)

    for fd in xrange(1, 10):
        handler._register_fd_with_reactor(fd=fd, reactor=reactor)
        assert reactor.get_handler(fd) == handler
        reactor.unregister(fd) # this is raising and handling
                               # exceptions internally, as the reactor
                               # hasn't been started
        try:
            reactor.get_handler(fd)
        except KeyError:
            pass

    for fd in xrange(1, 10):
        handler._register_fd_with_reactor(fd=fd, reactor=reactor)
    reactor._cull_any_bad_descriptors()