]> granicus.if.org Git - python/commitdiff
bpo-31158: Fix nondeterministic read in test_pty (#3808)
authorCornelius Diekmann <c.diekmann@googlemail.com>
Mon, 2 Oct 2017 09:39:55 +0000 (11:39 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Mon, 2 Oct 2017 09:39:55 +0000 (02:39 -0700)
* bpo-31158: Fix nondeterministic read in test_pty

* Reuse existing readline implementation from io.

Thx to @pitrou

* Updated comment

Ideally, this commit is fixuped into the previous commit. Since there is
already a comment on github, I won't rebase.

Lib/test/test_pty.py

index f283e1930b7ebc45c49c60f14ff31bed0ec81456..3b448569a2ffcb969a24613455eb93bd9f62a352 100644 (file)
@@ -10,6 +10,7 @@ import sys
 import select
 import signal
 import socket
+import io # readline
 import unittest
 
 TEST_STRING_1 = b"I wish to buy a fish license.\n"
@@ -23,6 +24,16 @@ else:
         pass
 
 
+# Note that os.read() is nondeterministic so we need to be very careful
+# to make the test suite deterministic.  A normal call to os.read() may
+# give us less than expected.
+#
+# Beware, on my Linux system, if I put 'foo\n' into a terminal fd, I get
+# back 'foo\r\n' at the other end.  The behavior depends on the termios
+# setting.  The newline translation may be OS-specific.  To make the
+# test suite deterministic and OS-independent, the functions _readline
+# and normalize_output can be used.
+
 def normalize_output(data):
     # Some operating systems do conversions on newline.  We could possibly fix
     # that by doing the appropriate termios.tcsetattr()s.  I couldn't figure out
@@ -43,6 +54,12 @@ def normalize_output(data):
 
     return data
 
+def _readline(fd):
+    """Read one line.  May block forever if no newline is read."""
+    reader = io.FileIO(fd, mode='rb', closefd=False)
+    return reader.readline()
+
+
 
 # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
 # because pty code is not too portable.
@@ -94,14 +111,14 @@ class PtyTest(unittest.TestCase):
 
         debug("Writing to slave_fd")
         os.write(slave_fd, TEST_STRING_1)
-        s1 = os.read(master_fd, 1024)
+        s1 = _readline(master_fd)
         self.assertEqual(b'I wish to buy a fish license.\n',
                          normalize_output(s1))
 
         debug("Writing chunked output")
         os.write(slave_fd, TEST_STRING_2[:5])
         os.write(slave_fd, TEST_STRING_2[5:])
-        s2 = os.read(master_fd, 1024)
+        s2 = _readline(master_fd)
         self.assertEqual(b'For my pet fish, Eric.\n', normalize_output(s2))
 
         os.close(slave_fd)