def test_get_new_hub(self): # When the hub is closed, get_hub() should return a new one. hub = gruvi.get_hub() hub.close() hub.switch() hub2 = gruvi.get_hub() self.assertIsNot(hub, hub2)
def thread_get(nfibers, count): fibers = [] for i in range(nfibers): fibers.append(gruvi.spawn(get_queue, count)) for fib in fibers: fib.join() gruvi.get_hub().close()
def test_remove(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(arg=0): def _callback(fd, events): cbargs.append((fd, events, arg)) called.set() return _callback h1 = mp.add_callback(READABLE, callback(0)) check_mpoll(mp) h2 = mp.add_callback(READABLE, callback(1)) check_mpoll(mp) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 0), (fd, READABLE, 1)]) del cbargs[:] called.clear() mp.remove_callback(h1) check_mpoll(mp) called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 1)]) mp.remove_callback(h2) check_mpoll(mp) mp.close() check_mpoll(mp) s1.close() s2.close()
def test_multiple(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(arg=0): def _callback(fd, events): cbargs.append((fd, events, arg)) called.set() return _callback mp.add_callback(READABLE, callback(0)) check_mpoll(mp) mp.add_callback(READABLE, callback(1)) check_mpoll(mp) mp.add_callback(WRITABLE, callback(2)) check_mpoll(mp) mp.add_callback(WRITABLE, callback(3)) check_mpoll(mp) called.wait(0.1) self.assertEqual(cbargs, [(fd, WRITABLE, 2), (fd, WRITABLE, 3)]) del cbargs[:] called.clear() s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 0), (fd, READABLE, 1), (fd, WRITABLE, 2), (fd, WRITABLE, 3)]) self.assertEqual(s2.recv(10), b'x') mp.close() check_mpoll(mp) s1.close() s2.close()
def test_update(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s1, s2 = socketpair() fd = s2.fileno() handle = poll.add_callback(fd, WRITABLE, callback) self.assertIsNotNone(handle) called.wait(0.1) self.assertEqual(cbargs, [(fd, WRITABLE)]) del cbargs[:] called.clear() poll.update_callback(fd, handle, READABLE | WRITABLE) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE | WRITABLE)]) del cbargs[:] called.clear() poll.close() s1.close() s2.close()
def test_close(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() h1 = mp.add_callback(READABLE, callback) h2 = mp.add_callback(READABLE, callback) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE), (fd, READABLE)]) del cbargs[:] called.clear() mp.close() called.wait(0.01) self.assertEqual(cbargs, []) self.assertRaises(RuntimeError, mp.add_callback, READABLE, callback) self.assertRaises(RuntimeError, mp.remove_callback, h1) self.assertRaises(RuntimeError, mp.remove_callback, h2) self.assertRaises(RuntimeError, mp.update_callback, h1, WRITABLE) self.assertRaises(RuntimeError, mp.update_callback, h2, WRITABLE) s1.close() s2.close()
def test_remove(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(arg=0): def _callback(fd, events): cbargs.append((fd, events, arg)) called.set() return _callback h1 = mp.add_callback(READABLE, callback(0)) check_mpoll(mp) h2 = mp.add_callback(READABLE, callback(1)) check_mpoll(mp) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 0), (fd, READABLE, 1)]) del cbargs[:]; called.clear() mp.remove_callback(h1) check_mpoll(mp) called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 1)]) mp.remove_callback(h2) check_mpoll(mp) mp.close() check_mpoll(mp) s1.close(); s2.close()
def test_call(self): # Calling a switch_back instance should cause hub.switch() to return # with an (args, kwargs) tuple. hub = gruvi.get_hub() with gruvi.switch_back() as switcher: hub.run_callback(lambda: switcher('foo', bar='baz')) self.assertEqual(hub.switch(), (('foo', ), {'bar': 'baz'}))
def thread_sleep(): hub = gruvi.get_hub() gruvi.sleep(0) refs.append(weakref.ref(hub)) refs.append(weakref.ref(hub.loop)) hub.close() hub.switch()
def test_multiple(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(arg=0): def _callback(fd, events): cbargs.append((fd, events, arg)) called.set() return _callback mp.add_callback(READABLE, callback(0)) check_mpoll(mp) mp.add_callback(READABLE, callback(1)) check_mpoll(mp) mp.add_callback(WRITABLE, callback(2)) check_mpoll(mp) mp.add_callback(WRITABLE, callback(3)) check_mpoll(mp) called.wait(0.1) self.assertEqual(cbargs, [(fd, WRITABLE, 2), (fd, WRITABLE, 3)]) del cbargs[:]; called.clear() s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE, 0), (fd, READABLE, 1), (fd, WRITABLE, 2), (fd, WRITABLE, 3)]) self.assertEqual(s2.recv(10), b'x') mp.close() check_mpoll(mp) s1.close(); s2.close()
def test_basic(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) check_mpoll(mp) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() mp.add_callback(READABLE, callback) check_mpoll(mp) called.wait(0.01) self.assertEqual(cbargs, []) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE)]) self.assertEqual(s2.recv(10), b'x') del cbargs[:] called.clear() called.wait(0.01) self.assertEqual(cbargs, []) mp.close() check_mpoll(mp) s1.close() s2.close()
def test_call(self): # Calling a switch_back instance should cause hub.switch() to return # with an (args, kwargs) tuple. hub = gruvi.get_hub() with gruvi.switch_back() as switcher: hub.run_callback(lambda: switcher('foo', bar='baz')) self.assertEqual(hub.switch(), (('foo',), {'bar': 'baz'}))
def tearDown(self): # Some paranoia checks to make me feel better before calling # shutil.rmtree().. assert '/..' not in self.__tmpdir and '\\..' not in self.__tmpdir assert os.stat(self.__tmpdir).st_ino == self.__tmpinode try: shutil.rmtree(self.__tmpdir) except OSError: # On Windows a WindowsError is raised when files are # still open (WindowsError inherits from OSError). pass self.__tmpdir = None self.__tmpinode = None # Check that no active handles remain. This would mess with other tests. hub = gruvi.get_hub() active = [] for handle in hub.loop.handles: if not handle.closed and not getattr(handle, '_system_handle', False): active.append(handle) for handle in active: print('closing active handle {0!r}'.format(handle)) handle.close() if active: raise RuntimeError('test leaked {0} active handles'.format( len(active)))
def test_update(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() h1 = mp.add_callback(READABLE, callback) check_mpoll(mp) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE)]) del cbargs[:]; called.clear() mp.update_callback(h1, READABLE|WRITABLE) check_mpoll(mp) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE|WRITABLE)]) del cbargs[:]; called.clear() mp.update_callback(h1, WRITABLE) check_mpoll(mp) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, WRITABLE)]) del cbargs[:]; called.clear() mp.update_callback(h1, 0) check_mpoll(mp) s1.send(b'x') called.wait(0.01) self.assertEqual(cbargs, []) mp.close() check_mpoll(mp) s1.close(); s2.close()
def test_throw(self): # An exception thrown with the throw() method of a switch_back instance # should cause hub.switch to raise that exception. hub = gruvi.get_hub() with gruvi.switch_back() as switcher: hub.run_callback(lambda: switcher.throw(ValueError('foo'))) exc = self.assertRaises(ValueError, hub.switch) self.assertEqual(exc.args[0], 'foo')
def teardown(self): # Close all handlers so that we don't run out of file handlers when # running the entire suite. Also this prevents stray handles from # changing the behavior of a subsequent Hub.switch(). hub = gruvi.get_hub() def close_handle(h): try: h.close() except pyuv.error.UVError: pass hub.loop.walk(close_handle)
def test_sleep(self): # Test that sleep() works hub = gruvi.get_hub() # use hub.now() as there's slight rounding errors with time.time() t0 = hub.loop.now() gruvi.sleep(0.01) t1 = hub.loop.now() self.assertGreaterEqual(t1 - t0, 10) t0 = hub.loop.now() gruvi.sleep(0.1) t1 = hub.loop.now() self.assertGreaterEqual(t1 - t0, 100)
def test_sleep(self): # Test that sleep() works hub = gruvi.get_hub() # use hub.now() as there's slight rounding errors with time.time() t0 = hub.loop.now() gruvi.sleep(0.01) t1 = hub.loop.now() self.assertGreaterEqual(t1-t0, 10) t0 = hub.loop.now() gruvi.sleep(0.1) t1 = hub.loop.now() self.assertGreaterEqual(t1-t0, 100)
def test_sigint(self): # The Hub should exit on CTRL-C (SIGINT). # On windows, sending SIGINT kills all processes attached to a console, # including the test driver. if sys.platform.startswith('win'): raise SkipTest('test skipped on Windows') def send_sigint(): time.sleep(0.01) os.kill(os.getpid(), signal.SIGINT) t1 = threading.Thread(target=send_sigint) t1.start() hub = gruvi.get_hub() hub.switch() self.assertFalse(hub.is_alive()) t1.join()
def test_send_random(self): server = JsonRpcServer(echo_app) server.listen(('127.0.0.1', 0)) addr = server.transport.getsockname() hub = gruvi.get_hub() client = StreamClient() client.connect(addr) try: while True: chunk = os.urandom(1024) client.write(chunk) except pyuv.error.TCPError as e: error = e assert error.args[0] in (pyuv.errno.UV_ECONNRESET, pyuv.errno.UV_EPIPE, pyuv.errno.UV_ECANCELED)
def test_close(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s1, s2 = socketpair() fd = s2.fileno() handle = poll.add_callback(fd, READABLE, callback) self.assertIsNotNone(handle) s1.send(b'x') poll.close() called.wait(0.01) self.assertEqual(cbargs, []) self.assertRaises(RuntimeError, poll.add_callback, fd, READABLE, callback) self.assertRaises(RuntimeError, poll.remove_callback, fd, handle) self.assertRaises(RuntimeError, poll.update_callback, fd, handle, WRITABLE) s1.close(); s2.close()
def test_multiple_fds(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s11, s12 = socketpair() fd1 = s12.fileno() poll.add_callback(fd1, READABLE, callback) s21, s22 = socketpair() fd2 = s22.fileno() poll.add_callback(fd2, READABLE, callback) s11.send(b'x') s21.send(b'x') called.wait() self.assertEqual(cbargs, [(fd1, READABLE), (fd2, READABLE)]) poll.close() s11.close(); s12.close() s21.close(); s22.close()
def test_debug(self): if not __debug__: return s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) def callback(fd, events): pass mp.add_callback(0, callback) mp.add_callback(READABLE, callback) mp.add_callback(WRITABLE, callback) mp.add_callback(READABLE|WRITABLE, callback) check(mp) with capture_stdio() as (out, err): dump(mp) lines = out.readlines() self.assertGreater(len(lines), 0) self.assertEqual(err.read(), '') mp.close() s1.close(); s2.close()
def test_switch_hub_only(self): # Ensure that only the hub may switch to or throw into a fiber. ready = [] exceptions = [] def worker(): ready.append(gruvi.current_fiber()) try: gruvi.sleep(0.1) except Exception as e: exceptions.append(e) fiber = gruvi.Fiber(worker) self.assertRaises(RuntimeError, fiber.switch) self.assertRaises(RuntimeError, fiber.throw, None) hub = gruvi.get_hub() hub.run_callback(fiber.switch) gruvi.sleep(0) self.assertEqual(ready, [fiber]) error = RuntimeError('foo') hub.run_callback(fiber.throw, RuntimeError, error) gruvi.sleep(0) self.assertEqual(exceptions, [error])
def test_update(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s1, s2 = socketpair() fd = s2.fileno() handle = poll.add_callback(fd, WRITABLE, callback) self.assertIsNotNone(handle) called.wait(0.1) self.assertEqual(cbargs, [(fd, WRITABLE)]) del cbargs[:]; called.clear() poll.update_callback(fd, handle, READABLE|WRITABLE) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE|WRITABLE)]) del cbargs[:]; called.clear() poll.close() s1.close(); s2.close()
def test_switch_hub_only(self): # Ensure that only the hub may switch to or throw into a fiber. ready = [] exceptions = [] def worker(): ready.append(gruvi.current_fiber()) try: gruvi.sleep(0.1) except Exception as e: exceptions.append(e) fiber = gruvi.Fiber(worker) self.assertRaises(RuntimeError, fiber.switch) self.assertRaises(RuntimeError, fiber.throw) hub = gruvi.get_hub() hub.run_callback(fiber.switch) gruvi.sleep(0) self.assertEqual(ready, [fiber]) error = RuntimeError('foo') hub.run_callback(fiber.throw, RuntimeError, error) gruvi.sleep(0) self.assertEqual(exceptions, [error])
def test_close(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() h1 = mp.add_callback(READABLE, callback) h2 = mp.add_callback(READABLE, callback) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE), (fd, READABLE)]) del cbargs[:]; called.clear() mp.close() called.wait(0.01) self.assertEqual(cbargs, []) self.assertRaises(RuntimeError, mp.add_callback, READABLE, callback) self.assertRaises(RuntimeError, mp.remove_callback, h1) self.assertRaises(RuntimeError, mp.remove_callback, h2) self.assertRaises(RuntimeError, mp.update_callback, h1, WRITABLE) self.assertRaises(RuntimeError, mp.update_callback, h2, WRITABLE) s1.close(); s2.close()
def test_close(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s1, s2 = socketpair() fd = s2.fileno() handle = poll.add_callback(fd, READABLE, callback) self.assertIsNotNone(handle) s1.send(b'x') poll.close() called.wait(0.01) self.assertEqual(cbargs, []) self.assertRaises(RuntimeError, poll.add_callback, fd, READABLE, callback) self.assertRaises(RuntimeError, poll.remove_callback, fd, handle) self.assertRaises(RuntimeError, poll.update_callback, fd, handle, WRITABLE) s1.close() s2.close()
def tearDown(self): # Some paranoia checks to make me feel better before calling # shutil.rmtree().. assert '/..' not in self.__tmpdir and '\\..' not in self.__tmpdir assert os.stat(self.__tmpdir).st_ino == self.__tmpinode try: shutil.rmtree(self.__tmpdir) except OSError: # On Windows a WindowsError is raised when files are # still open (WindowsError inherits from OSError). pass self.__tmpdir = None self.__tmpinode = None # Check that no active handles remain. This would mess with other tests. hub = gruvi.get_hub() active = [] for handle in hub.loop.handles: if not handle.closed and not getattr(handle, '_system_handle', False): active.append(handle) for handle in active: print('closing active handle {0!r}'.format(handle)) handle.close() if active: raise RuntimeError('test leaked {0} active handles'.format(len(active)))
def test_basic(self): s1, s2 = socketpair() fd = s2.fileno() mp = MultiPoll(get_hub().loop, fd) check(mp) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() mp.add_callback(READABLE, callback) check(mp) called.wait(0.01) self.assertEqual(cbargs, []) s1.send(b'x') called.wait(0.1) self.assertEqual(cbargs, [(fd, READABLE)]) self.assertEqual(s2.recv(10), b'x') del cbargs[:]; called.clear() called.wait(0.01) self.assertEqual(cbargs, []) mp.close() check(mp) s1.close(); s2.close()
def test_multiple_fds(self): poll = Poller(get_hub().loop) cbargs = [] called = Event() def callback(fd, events): cbargs.append((fd, events)) called.set() s11, s12 = socketpair() fd1 = s12.fileno() poll.add_callback(fd1, READABLE, callback) s21, s22 = socketpair() fd2 = s22.fileno() poll.add_callback(fd2, READABLE, callback) s11.send(b'x') s21.send(b'x') called.wait() self.assertEqual(cbargs, [(fd1, READABLE), (fd2, READABLE)]) poll.close() s11.close() s12.close() s21.close() s22.close()
# Gruvi example program: an echo server, using a Protocol import gruvi class EchoProtocol(gruvi.Protocol): def connection_made(self, transport): super(EchoProtocol, self).connection_made(transport) peer = transport.get_extra_info('peername') print('New connection from {0}'.format(gruvi.saddr(peer))) def data_received(self, data): self._transport.write(data) def eof_received(self): print('Connection lost') server = gruvi.create_server(EchoProtocol, ('localhost', 0)) for addr in server.addresses: print('Listen on {0}'.format(gruvi.saddr(addr))) try: gruvi.get_hub().switch() except KeyboardInterrupt: print('Exiting on CTRL-C')
stdout.connect(TTY(sys.stdout)) def read_stdin(): while True: buf = stdin.read(4096) if not buf: logger.debug('Got EOF on stdin') client.shutdown() break client.write(buf) def read_network(): while True: buf = client.read(4096) if not buf: logger.debug('Connection closed by peer') break stdout.write(buf) hub.parent.switch() stdin_reader = gruvi.Greenlet(read_stdin) stdin_reader.start() network_reader = gruvi.Greenlet(read_network) network_reader.start() hub = get_hub() print('Press CTRL-C to quit (CTRL-D to send EOF)', file=sys.stderr) hub.switch(interrupt=True)
def test_timeout(self): # A timeout in a switch_back instance should cause hub.switch() to # raise a Timeout exception. hub = gruvi.get_hub() with gruvi.switch_back(0.01): self.assertRaises(gruvi.Timeout, hub.switch)
import logging import argparse from gruvi import get_hub, util from gruvi.stream import StreamServer logging.basicConfig() parser = argparse.ArgumentParser() parser.add_argument('port', type=int) args = parser.parse_args() def echo_handler(stream, protocol, client): peer = client.getpeername() print('Connection from {0}'.format(util.saddr(peer))) while True: buf = stream.read(4096) if not buf: break stream.write(buf) print('Connection closed') server = StreamServer(echo_handler) server.listen(('0.0.0.0', args.port)) hub = get_hub() hub.switch(interrupt=True)