Derive a PtyReaderTestCase from PipeReaderTestCase. This test is expected to
authorZac Medico <zmedico@gentoo.org>
Sat, 12 Jul 2008 07:32:55 +0000 (07:32 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 12 Jul 2008 07:32:55 +0000 (07:32 -0000)
fail on some operating systems such as Darwin that do not support poll() on
pty devices.

svn path=/main/trunk/; revision=11023

pym/_emerge/__init__.py
pym/portage/tests/process/test_poll.py

index 6f975449abcca4f00a99448eb8612d9605960a6c..b111157eacc95cd2b5f809131d183db2d783ddcb 100644 (file)
@@ -1594,6 +1594,8 @@ class PipeReader(AsynchronousTask):
        __slots__ = ("input_files", "scheduler",) + \
                ("pid", "registered", "_reg_ids", "_read_data")
 
+       _bufsize = 4096
+
        def _start(self):
                self._reg_ids = set()
                self._read_data = []
@@ -1628,8 +1630,16 @@ class PipeReader(AsynchronousTask):
                for f in files.itervalues():
                        if fd == f.fileno():
                                break
-               self._read_data.append(f.read())
-               if not self._read_data[-1]:
+
+               buf = array.array('B')
+               try:
+                       buf.fromfile(f, self._bufsize)
+               except EOFError:
+                       pass
+
+               if buf:
+                       self._read_data.append(buf.tostring())
+               else:
                        for f in files.values():
                                f.close()
                        self.registered = False
index 45c0ad03e45959885e7ad608cce202ee1c4d0168..e8de967f7e7a0db0f9161ccf8371a5cce4222f3f 100644 (file)
@@ -3,10 +3,20 @@
 # $Id: test_spawn.py 8474 2007-11-09 03:35:38Z zmedico $
 
 import errno, os, sys
+import fcntl
+import termios
+import portage
+from portage.output import get_term_size, set_term_size
 from portage.tests import TestCase
 from _emerge import PipeReader, SpawnProcess, TaskScheduler
 
-class PollTestCase(TestCase):
+class PipeReaderTestCase(TestCase):
+
+       def _create_pipe(self):
+               return os.pipe()
+
+       def _assertEqual(self, test_string, consumer_value):
+               self.assertEqual(test_string, consumer_value)
 
        def testPipeReader(self):
                """
@@ -17,7 +27,7 @@ class PollTestCase(TestCase):
 
                test_string = 2 * "blah blah blah\n"
 
-               master_fd, slave_fd = os.pipe()
+               master_fd, slave_fd = self._create_pipe()
                master_file = os.fdopen(master_fd, 'r')
 
                task_scheduler = TaskScheduler(max_jobs=2)
@@ -40,4 +50,43 @@ class PollTestCase(TestCase):
                producer.addStartListener(producer_start_cb)
                task_scheduler.run()
 
-               self.assertEqual(test_string, consumer.getvalue())
+               self._assertEqual(test_string, consumer.getvalue())
+
+class PtyReaderTestCase(PipeReaderTestCase):
+
+       def _assertEqual(self, test_string, consumer_value):
+               if test_string != consumer_value:
+                       # This test is expected to fail on some operating systems
+                       # such as Darwin that do not support poll() on pty devices.
+                       self.todo = True
+               self.assertEqual(test_string, consumer_value)
+
+       def _create_pipe(self):
+               got_pty = False
+
+               if portage._disable_openpty:
+                       master_fd, slave_fd = os.pipe()
+               else:
+                       from pty import openpty
+                       try:
+                               master_fd, slave_fd = openpty()
+                               got_pty = True
+                       except EnvironmentError, e:
+                               portage._disable_openpty = True
+                               portage.writemsg("openpty failed: '%s'\n" % str(e),
+                                       noiselevel=-1)
+                               del e
+                               master_fd, slave_fd = os.pipe()
+
+               if got_pty:
+                       # Disable post-processing of output since otherwise weird
+                       # things like \n -> \r\n transformations may occur.
+                       mode = termios.tcgetattr(slave_fd)
+                       mode[1] &= ~termios.OPOST
+                       termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
+
+               if got_pty and sys.stdout.isatty():
+                       rows, columns = get_term_size()
+                       set_term_size(rows, columns, slave_fd)
+
+               return (master_fd, slave_fd)