def test_forwarding(self): loop = self.make_event_loop() pipe_read, pipe_write, forwarder = self._make_forwarded_pipe(loop) self.assertTrue(loop.will_block()) self.assertEquals(poll_fd(pipe_read), 0) os.write(pipe_write.fileno(), "hello world") loop.once_safely() # read iteration loop.once_safely() # write iteration self.assertEquals(poll_fd(pipe_read), select.POLLIN) self.assertEquals(os.read(pipe_read.fileno(), 1000), "hello world")
def test_writing_end_of_stream_with_data_buffered(self): loop = self.make_event_loop() pipe_read, pipe_write = stream.make_pipe() writer = stream.FDBufferedWriter(loop, pipe_write) del pipe_write writer.write("hello") writer.end_of_stream() loop.once_safely() self.assertEquals(poll_fd(pipe_read), select.POLLHUP | select.POLLIN) self.assertEquals(os.read(pipe_read.fileno(), 100), "hello") self.assertEquals(poll_fd(pipe_read), select.POLLHUP) self.assertEquals(os.read(pipe_read.fileno(), 100), "")
def test_closing_on_read_end(self): loop = self.make_event_loop() pipe_read, pipe_write, forwarder = self._make_forwarded_pipe(loop) self.assertTrue(loop.will_block()) self.assertEquals(poll_fd(pipe_read), 0) os.write(pipe_write.fileno(), "hello world") del pipe_write loop.once_safely() # read iteration loop.once_safely() # write iteration self.assertEquals(poll_fd(pipe_read), select.POLLHUP | select.POLLIN) self.assertEquals(os.read(pipe_read.fileno(), 1000), "hello world") self.assertEquals(poll_fd(pipe_read), select.POLLHUP) self.assertEquals(os.read(pipe_read.fileno(), 1000), "") self.assertFalse(loop.is_listening())
def _connection_dropped(self, sock): # AF_UNIX sockets set POLLHUP when the other end has been # closed, but AF_INET sockets do not set POLLHUP. Both set # POLLIN and return an EOF condition from read(). if poll_fd(sock) & select.POLLIN: return len(os.read(sock.fileno(), 100)) == 0 return False
def test_forwarding_to_unwritable_fd(self): loop = self.make_event_loop() pipe_read, pipe_write = stream.make_pipe() forwarder = stream.FDForwarder(loop, pipe_read, open("/dev/null", "r")) del pipe_read loop.once_safely() self.assertEquals(poll_fd(pipe_write), select.POLLERR | select.POLLOUT)
def test_poll_annoying_behaviour(self): pipe_read, pipe_write = stream.make_pipe() # It would be more useful if poll() returned POLLIN and # POLLOUT for unreadable and unwritable FDs respectively, # indicating that read() and write() would not block. # We do not rely on the behaviour tested here; in fact, we # work around it. self.assertEquals(poll_fd(pipe_read) & select.POLLOUT, 0) self.assertEquals(poll_fd(pipe_write) & select.POLLIN, 0) # However, select() behaves more usefully: read_fds, write_fds, except_fds = select.select( [], [open(os.devnull, "r")], [], 0) self.assertEquals(len(write_fds), 1) read_fds, write_fds, except_fds = select.select( [open(os.devnull, "w")], [], [], 0) self.assertEquals(len(read_fds), 1)
def find_pipe_buffer_size(): # The size of a pipe's buffer is 64k on Linux, but let's not # assume that. pipe_read, pipe_write = stream.make_pipe() fcntl.fcntl(pipe_write.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) data = "x" * 4096 written = 0 while poll_fd(pipe_write) & select.POLLOUT != 0: written += os.write(pipe_write.fileno(), data) return written
def test_flow_control(self): # Usually with pipes, a writer cannot keep writing while the # reader is not reading. Check that forwarding preserves # that. big_limit = find_pipe_buffer_size() * 10 loop = self.make_event_loop() pipe_read, pipe_write, forwarder = self._make_forwarded_pipe(loop) fcntl.fcntl(pipe_write.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) data = "x" * 4096 written = 0 while poll_fd(pipe_write) & select.POLLOUT != 0: assert written < big_limit written += os.write(pipe_write.fileno(), data) loop.run_awhile() assert written > 0 # Reading should allow more data to be written. We have to # read at least PIPE_BUF bytes, otherwise poll() will not # report the pipe as writable to the FDForwarder. os.read(pipe_read.fileno(), 4096) self.assertEquals(poll_fd(pipe_write), 0) loop.run_awhile() self.assertEquals(poll_fd(pipe_write), select.POLLOUT)
def test_writing_to_full_buffer(self): # Checks that the writer does not write when the FD's buffer # is full, and checks that it does not block. loop = self.make_event_loop() pipe_read, pipe_write = stream.make_pipe() writer = stream.FDBufferedWriter(loop, pipe_write) bufferfuls = 5 size = find_pipe_buffer_size() * bufferfuls writer.write("x" * size) loop.once_safely() # Nothing is reading pipe_read, so writer should still have # unwritten data. assert writer.buffered_size() > 0 assert writer.buffered_size() < size # But reading should allow the backlog to clear. for i in range(bufferfuls): self.assertEquals(poll_fd(pipe_read), select.POLLIN) os.read(pipe_read.fileno(), size) loop.run_awhile() self.assertEquals(writer.buffered_size(), 0)
def read_pending(self): while (self._fd is not None and poll_fd(self._fd) & select.POLLIN != 0): self._read_some_data(1000)
def example(name, fd): flags = poll_fd(fd) output.append("%-30s %s" % (decode_poll_flags(flags), name))