def testNamedTempFile(self): f = tempfile.NamedTemporaryFile() fd = FD(f.fileno()) # tempfile APIs set cloexec = True for added security fd.set_cloexec(False) self.checkSubprocessFDs([fd], close=False) del f
def testWriteAfterClose(self): r, w = os.pipe() fw = FD(w) fw.close() try: with self.assertRaises(OSError) as ar: fw.write("oops") self.assertEquals(ar.exception.errno, errno.EBADF) finally: FD(r).close()
def testNonblocking(self): r, w = os.pipe() fr = FD(r) try: fr.set_nonblocking() with self.assertRaises(OSError) as ar: fr.read(1) self.assertEquals(ar.exception.errno, errno.EAGAIN) finally: fr.close() FD(w).close()
def testKqueue(self): k = select.kqueue() fd = FD(k) try: self.checkSubprocessFDs([fd], close=False) finally: del k
def testReuse(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1', 0)) host, port = s.getsockname() s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) with self.assertRaises(socket.error): s2.bind(('127.0.0.1', port)) FD(s).socket.set_reuse() with self.assertRaises(socket.error): s2.bind(('127.0.0.1', port)) FD(s2).socket.set_reuse() s2.bind(('127.0.0.1', port))
def testPipeCloseOnExcecute(self): r, w = os.pipe() # Set close on execute on this guy FD(w).set_cloexec() try: # Create a subprocess that prints and blocks waiting for input p = Popen("echo ok; read foo", shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT) try: # Wait for the process to let us know it's alive ready = p.stdout.read(3) self.assertEquals(ready, "ok\n") # Get the list of FDs of the remote process remote_fds = get_open_fds(p.pid) # Make sure the read fd persisted, but the write fd was not. self.assertIn(r, remote_fds) self.assertNotIn(w, remote_fds) # As an added check, make sure the mode flags on the remote # and local process' fds are identical self.assertEquals(FD(r, p.pid).mode, FD(r).mode) # Now send some output to the remote process to unblock it p.stdin.write("ok\n") p.stdin.flush() # Wait for it to shutdown self.assertEquals(p.wait(), 0) finally: # Popen does not close PIPE fds on process shutdown # automatically, even if there's no data in it. Since the # exception context is propagated to the test cases' tearDown, # the popen's pipes will show up as a leak if p.poll() is None: p.kill() self.assertEquals(p.wait(), -9) del p finally: FD(r).close() FD(w).close()
def testNotASocket(self): r, w = os.pipe() try: with self.assertRaises(TypeError): FD(r).socket finally: os.close(r) os.close(w)
def testEquals(self): tf = tempfile.TemporaryFile() fds = self.getNewFDs() self.assertEquals(len(fds), 1) fd = fds[0] self.assertEquals(fd, FD(tf.fileno())) self.assertEquals(fd, tf.fileno()) self.assertNotEquals(fd, object())
def checkSubprocessFDs(self, check_fds, close=True): try: # Create a subprocess that prints and blocks waiting for input p = Popen("echo ok; read foo", shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT) try: # Wait for the process to let us know it's alive ready = p.stdout.read(3) self.assertEquals(ready, "ok\n") # Get the list of FDs of the remote process remote_fds = get_open_fds(p.pid) # Make sure the check_fds persisted and have an identical mode for fd in check_fds: self.assertIn(fd, remote_fds) self.assertEquals(FD(int(fd), p.pid).mode, fd.mode) # Now send some output to the remote process to unblock it p.stdin.write("ok\n") p.stdin.flush() # Wait for it to shutdown self.assertEquals(p.wait(), 0) finally: # Popen does not close PIPE fds on process shutdown # automatically, even if there's no data in it. Since the # exception context is propagated to the test cases' tearDown, # the popen's pipes will show up as a leak if p.poll() is None: p.kill() self.assertEquals(p.wait(), -9) del p finally: if close: for fd in check_fds: fd.close()
def testSocket(self): import socket s = socket.socket() self.checkSubprocessFDs([FD(s.fileno())]) del s
def testEpoll(self): e = select.epoll() fd = FD(e) self.checkSubprocessFDs([fd], close=False) del e
def send(sock, fds): for fd in fds: FD(sock).socket.send_fd(fd)
def recv(sock, n_fds): return FD(sock).socket.recv_fds(n_fds)
def send(sock, fds): FD(sock).socket.send_fds(fds)
def testReadWrite(self): r, w = os.pipe() self.assertEquals(FD(w).write("OK"), 2) self.assertEquals(FD(r).read(2), "OK") FD(r).close() FD(w).close()
def recv(sock, n_fds): result = [] for i in xrange(n_fds): result.append(FD(sock).socket.recv_fd()) return result