예제 #1
0
 def test_forwarding_from_unreadable_fd(self):
     loop = self.make_event_loop()
     pipe_read, pipe_write = stream.make_pipe()
     forwarder = stream.FDForwarder(loop, open("/dev/null", "w"), pipe_write)
     del pipe_write
     loop.once_safely()
     self.assertEquals(os.read(pipe_read.fileno(), 1000), "")
예제 #2
0
 def test_fds_are_freed(self):
     pipe_read, pipe_write = stream.make_pipe()
     fd = pipe_read.fileno()
     fcntl.fcntl(fd, fcntl.F_GETFL)
     del pipe_read
     self.assertRaises(IOError,
                       lambda: fcntl.fcntl(fd, fcntl.F_GETFL))
예제 #3
0
 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)
예제 #4
0
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
예제 #5
0
 def test_writing_to_closed_pipe(self):
     loop = self.make_event_loop()
     pipe_read, pipe_write = stream.make_pipe()
     writer = stream.FDBufferedWriter(loop, pipe_write)
     writer.write("hello")
     del pipe_read
     self.assertEquals(writer.is_finished_writing(), False)
     loop.once_safely()
     self.assertEquals(writer.is_finished_writing(), True)
     self.assertFalse(loop.is_listening())
예제 #6
0
 def test_writing(self):
     loop = self.make_event_loop()
     pipe_read, pipe_write = stream.make_pipe()
     writer = stream.FDBufferedWriter(loop, pipe_write)
     self.assertEquals(writer.buffered_size(), 0)
     writer.write("hello")
     self.assertEquals(writer.buffered_size(), 5)
     loop.once_safely()
     # Should have written all of buffer to the pipe now
     self.assertEquals(writer.buffered_size(), 0)
예제 #7
0
 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), "")
예제 #8
0
 def test_fd_flags_not_changed(self):
     loop = self.make_event_loop()
     pipe_read, pipe_write = stream.make_pipe()
     def check_flags():
         flags = fcntl.fcntl(pipe_write.fileno(), fcntl.F_GETFL)
         self.assertEquals(flags, os.O_WRONLY)
     check_flags()
     writer = stream.FDBufferedWriter(loop, pipe_write)
     check_flags()
     writer.write("hello")
     loop.once_safely()
     # If FDBufferedWriter sets O_NONBLOCK, it should do so only
     # temporarily, because it could confuse other processes that
     # share the FD.  Changing the flags temporarily is still not
     # ideal though.
     check_flags()
예제 #9
0
 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)
예제 #10
0
 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)
예제 #11
0
    def test_on_finished_callback(self):
        got = []
        def on_finished():
            got.append("finish")

        loop = self.make_event_loop()
        pipe_read, pipe_write = stream.make_pipe()
        writer = stream.FDBufferedWriter(loop, pipe_write,
                                         on_unwritable=on_finished)
        writer.write("hello")
        loop.once_safely()
        self.assertEquals(writer.buffered_size(), 0)
        # Writer is not finished merely because it has no data buffered.
        self.assertEquals(got, [])
        writer.write("world")
        writer.end_of_stream()
        # Nor is the writer finished because end_of_stream() has been called.
        self.assertEquals(got, [])
        loop.once_safely()
        # Writer is finished once end_of_stream() has been called and
        # either all buffered data has been written or an error was
        # reached.
        self.assertEquals(got, ["finish"])
예제 #12
0
def get_poll_flag_table():
    output = []
    pipe_size = find_pipe_buffer_size()

    def example(name, fd):
        flags = poll_fd(fd)
        output.append("%-30s %s" % (decode_poll_flags(flags), name))

    class Wrapper(object):
        def __init__(self, fd):
            self._fd = fd
        def fileno(self):
            return self._fd

    def unwrap(fd):
        return os.dup(fd.fileno())

    def unwrap_pair((fd1, fd2)):
        return unwrap(fd1), unwrap(fd2)

    def pair_pending_data(pair, size):
        read_fd, write_fd = pair
        os.write(write_fd.fileno(), "x" * size)
        return pair

    def example_pair(name, maker, i):
        fd_pair = unwrap_pair(maker())
        fd = fd_pair[i]
        example(name, Wrapper(fd))
        os.close(fd_pair[1 - i])
        example(name + " (other closed)", Wrapper(fd))
        os.close(fd_pair[i])

    def shutdown(pair, shut_type):
        # The socket is not necessarily AF_UNIX but the socket module
        # shouldn't actually use those arguments.
        sock = socket.fromfd(pair[1].fileno(),
                             socket.AF_UNIX, socket.SOCK_STREAM)
        sock.shutdown(shut_type)
        return pair

    def example_socket(name, maker):
        example_pair(name, maker, 0)
        example_pair(name + " (SHUT_RD)",
                     lambda: shutdown(maker(), socket.SHUT_RD), 0)
        example_pair(name + " (SHUT_WR)",
                     lambda: shutdown(maker(), socket.SHUT_WR), 0)
        example_pair(name + " (SHUT_RDWR)",
                     lambda: shutdown(maker(), socket.SHUT_RDWR), 0)

    def make_pty():
        fd1, fd2 = os.openpty()
        return stream.WrappedFD(fd1), stream.WrappedFD(fd2)

    def make_pty_eof():
        fd1, fd2 = make_pty()
        # Send Ctrl-D, the console EOF character
        os.write(fd1.fileno(), chr(4))
        return fd1, fd2

    for side, name in [(0, "read"), (1, "write")]:
        example_pair(
            "pipe: %s" % name,
            lambda: stream.make_pipe(), side)
        example_pair(
            "pipe: %s, pending data" % name,
            lambda: pair_pending_data(stream.make_pipe(), pipe_size), side)
    example_socket("socket: Unix", stream.socketpair)
    example_socket("socket: TCP", plash.comms.cap_test.tcp_socketpair)
    example_pair("tty master", make_pty, 0)
    example_pair("tty slave", make_pty, 1)
    example_pair("tty slave (send Ctrl-D)", make_pty_eof, 1)
    example("/dev/null: write", open("/dev/null", "w"))
    example("/dev/null: read", open("/dev/null", "r"))
    example("file: write", open("/tmp/file", "w"))
    example("file: read", open("/tmp/file", "r"))
    return output
예제 #13
0
 def _make_forwarded_pipe(self, loop):
     pipe_read2, pipe_write = stream.make_pipe()
     pipe_read, pipe_write2 = stream.make_pipe()
     forwarder = stream.FDForwarder(loop, pipe_read2, pipe_write2)
     return pipe_read, pipe_write, forwarder
예제 #14
0
 def test_pipes(self):
     pipe_read, pipe_write = stream.make_pipe()
     self.assertTrue(stream.fd_is_readable(pipe_read))
     self.assertFalse(stream.fd_is_writable(pipe_read))
     self.assertFalse(stream.fd_is_readable(pipe_write))
     self.assertTrue(stream.fd_is_writable(pipe_write))