diff options
Diffstat (limited to 'Lib/test/test_io.py')
| -rw-r--r-- | Lib/test/test_io.py | 77 | 
1 files changed, 74 insertions, 3 deletions
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 003a4f3..b9972f3 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -43,6 +43,10 @@ try:      import threading  except ImportError:      threading = None +try: +    import fcntl +except ImportError: +    fcntl = None  __metaclass__ = type  bytes = support.py3k_bytes @@ -228,9 +232,14 @@ class MockNonBlockWriterIO:              except ValueError:                  pass              else: -                self._blocker_char = None -                self._write_stack.append(b[:n]) -                raise self.BlockingIOError(0, "test blocking", n) +                if n > 0: +                    # write data up to the first blocker +                    self._write_stack.append(b[:n]) +                    return n +                else: +                    # cancel blocker and indicate would block +                    self._blocker_char = None +                    return None          self._write_stack.append(b)          return len(b) @@ -2610,6 +2619,68 @@ class MiscIOTest(unittest.TestCase):          # baseline "io" module.          self._check_abc_inheritance(io) +    @unittest.skipUnless(fcntl, 'fcntl required for this test') +    def test_nonblock_pipe_write_bigbuf(self): +        self._test_nonblock_pipe_write(16*1024) + +    @unittest.skipUnless(fcntl, 'fcntl required for this test') +    def test_nonblock_pipe_write_smallbuf(self): +        self._test_nonblock_pipe_write(1024) + +    def _set_non_blocking(self, fd): +        flags = fcntl.fcntl(fd, fcntl.F_GETFL) +        self.assertNotEqual(flags, -1) +        res = fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) +        self.assertEqual(res, 0) + +    def _test_nonblock_pipe_write(self, bufsize): +        sent = [] +        received = [] +        r, w = os.pipe() +        self._set_non_blocking(r) +        self._set_non_blocking(w) + +        # To exercise all code paths in the C implementation we need +        # to play with buffer sizes.  For instance, if we choose a +        # buffer size less than or equal to _PIPE_BUF (4096 on Linux) +        # then we will never get a partial write of the buffer. +        rf = self.open(r, mode='rb', closefd=True, buffering=bufsize) +        wf = self.open(w, mode='wb', closefd=True, buffering=bufsize) + +        with rf, wf: +            for N in 9999, 73, 7574: +                try: +                    i = 0 +                    while True: +                        msg = bytes([i % 26 + 97]) * N +                        sent.append(msg) +                        wf.write(msg) +                        i += 1 + +                except self.BlockingIOError as e: +                    self.assertEqual(e.args[0], errno.EAGAIN) +                    sent[-1] = sent[-1][:e.characters_written] +                    received.append(rf.read()) +                    msg = b'BLOCKED' +                    wf.write(msg) +                    sent.append(msg) + +            while True: +                try: +                    wf.flush() +                    break +                except self.BlockingIOError as e: +                    self.assertEqual(e.args[0], errno.EAGAIN) +                    self.assertEqual(e.characters_written, 0) +                    received.append(rf.read()) + +            received += iter(rf.read, None) + +        sent, received = b''.join(sent), b''.join(received) +        self.assertTrue(sent == received) +        self.assertTrue(wf.closed) +        self.assertTrue(rf.closed) +  class CMiscIOTest(MiscIOTest):      io = io  | 
