1515import testlib
1616
1717
18+ def _osx_mode (n ):
19+ """
20+ fstat(2) on UNIX sockets on OSX return different mode bits depending on
21+ which side is being inspected, so zero those bits for comparison.
22+ """
23+ if sys .platform == 'darwin' :
24+ n &= ~ int ('0777' , 8 )
25+ return n
26+
27+
1828def run_fd_check (func , fd , mode , on_start = None ):
29+ """
30+ Run ``tests/data/fd_check.py`` using `func`. The subprocess writes
31+ information about the `fd` it received to a temporary file.
32+
33+ :param func:
34+ Function like `create_child()` used to start child.
35+ :param fd:
36+ FD child should read/write from, and report information about.
37+ :param mode:
38+ "read" or "write", depending on whether the FD is readable or writeable
39+ from the perspective of the child. If "read", `on_start()` should write
40+ "TEST" to it and the child reads "TEST" from it, otherwise `on_start()`
41+ should read "TEST" from it and the child writes "TEST" to it.
42+ :param on_start:
43+ Function invoked as `on_start(proc)`
44+ :returns:
45+ Tuple of `(proc, info, on_start_result)`, where:
46+
47+ * `proc`: the :class:`mitogen.parent.Process` returned by `func`.
48+ * `info`: dict containing information returned by the child:
49+ * `buf`: "TEST" that was read in "read" mode
50+ * `flags`: :attr:`fcntl.F_GETFL` flags for `fd`
51+ * `st_mode`: st_mode field from :func:`os.fstat`
52+ * `st_dev`: st_dev field from :func:`os.fstat`
53+ * `st_ino`: st_ino field from :func:`os.fstat`
54+ * `ttyname`: :func:`os.ttyname` invoked on `fd`.
55+ * `controlling_tty`: :func:os.ttyname` invoked on ``/dev/tty``
56+ from within the child.
57+ """
1958 tf = tempfile .NamedTemporaryFile ()
2059 args = [
2160 sys .executable ,
@@ -61,7 +100,7 @@ def test_stdin(self):
61100 st = os .fstat (proc .stdin .fileno ())
62101 self .assertTrue (stat .S_ISSOCK (st .st_mode ))
63102 self .assertEquals (st .st_dev , info ['st_dev' ])
64- self .assertEquals (st .st_mode , info ['st_mode' ])
103+ self .assertEquals (st .st_mode , _osx_mode ( info ['st_mode' ]) )
65104 flags = fcntl .fcntl (proc .stdin .fileno (), fcntl .F_GETFL )
66105 self .assertTrue (flags & os .O_RDWR )
67106 self .assertTrue (info ['buf' ], 'TEST' )
@@ -75,7 +114,7 @@ def test_stdout(self):
75114 st = os .fstat (proc .stdout .fileno ())
76115 self .assertTrue (stat .S_ISSOCK (st .st_mode ))
77116 self .assertEquals (st .st_dev , info ['st_dev' ])
78- self .assertEquals (st .st_mode , info ['st_mode' ])
117+ self .assertEquals (st .st_mode , _osx_mode ( info ['st_mode' ]) )
79118 flags = fcntl .fcntl (proc .stdout .fileno (), fcntl .F_GETFL )
80119 self .assertTrue (flags & os .O_RDWR )
81120 self .assertTrue (buf , 'TEST' )
@@ -105,8 +144,6 @@ def test_stderr(self):
105144 self .assertEquals (None , proc .stderr )
106145 st = os .fstat (proc .stdout .fileno ())
107146 self .assertTrue (stat .S_ISSOCK (st .st_mode ))
108- self .assertEquals (st .st_dev , info ['st_dev' ])
109- self .assertEquals (st .st_mode , info ['st_mode' ])
110147 flags = fcntl .fcntl (proc .stdout .fileno (), fcntl .F_GETFL )
111148 self .assertTrue (flags & os .O_RDWR )
112149 self .assertTrue (buf , 'TEST' )
@@ -145,13 +182,11 @@ def test_stdin(self):
145182
146183 self .assertTrue (isinstance (info ['ttyname' ],
147184 mitogen .core .UnicodeType ))
148- os .ttyname (proc .stdin .fileno ()) # crashes if not TTY
185+ self . assertTrue ( os .isatty (proc .stdin .fileno ()))
149186
150187 flags = fcntl .fcntl (proc .stdin .fileno (), fcntl .F_GETFL )
151188 self .assertTrue (flags & os .O_RDWR )
152189 self .assertTrue (info ['flags' ] & os .O_RDWR )
153-
154- self .assertNotEquals (st .st_dev , info ['st_dev' ])
155190 self .assertTrue (info ['buf' ], 'TEST' )
156191
157192 def test_stdout (self ):
@@ -164,17 +199,18 @@ def test_stdout(self):
164199
165200 self .assertTrue (isinstance (info ['ttyname' ],
166201 mitogen .core .UnicodeType ))
167- os .ttyname (proc .stdout .fileno ()) # crashes if wrong
202+ self . assertTrue ( os .isatty (proc .stdout .fileno ()))
168203
169204 flags = fcntl .fcntl (proc .stdout .fileno (), fcntl .F_GETFL )
170205 self .assertTrue (flags & os .O_RDWR )
171206 self .assertTrue (info ['flags' ] & os .O_RDWR )
172207
173- self .assertNotEquals (st .st_dev , info ['st_dev' ])
174208 self .assertTrue (flags & os .O_RDWR )
175209 self .assertTrue (buf , 'TEST' )
176210
177211 def test_stderr (self ):
212+ # proc.stderr is None in the parent since there is no separate stderr
213+ # stream. In the child, FD 2/stderr is connected to the TTY.
178214 proc , info , buf = run_fd_check (self .func , 2 , 'write' ,
179215 lambda proc : wait_read (proc .stdout , 4 ))
180216
@@ -184,13 +220,12 @@ def test_stderr(self):
184220
185221 self .assertTrue (isinstance (info ['ttyname' ],
186222 mitogen .core .UnicodeType ))
187- os .ttyname (proc .stdin .fileno ()) # crashes if not TTY
223+ self . assertTrue ( os .isatty (proc .stdout .fileno ()))
188224
189225 flags = fcntl .fcntl (proc .stdout .fileno (), fcntl .F_GETFL )
190226 self .assertTrue (flags & os .O_RDWR )
191227 self .assertTrue (info ['flags' ] & os .O_RDWR )
192228
193- self .assertNotEquals (st .st_dev , info ['st_dev' ])
194229 self .assertTrue (flags & os .O_RDWR )
195230 self .assertTrue (buf , 'TEST' )
196231
@@ -222,6 +257,7 @@ def test_dev_tty_open_succeeds(self):
222257
223258class StderrDiagTtyMixin (object ):
224259 def test_stderr (self ):
260+ # proc.stderr is the PTY master, FD 2 in the child is the PTY slave
225261 proc , info , buf = run_fd_check (self .func , 2 , 'write' ,
226262 lambda proc : wait_read (proc .stderr , 4 ))
227263
@@ -231,13 +267,12 @@ def test_stderr(self):
231267
232268 self .assertTrue (isinstance (info ['ttyname' ],
233269 mitogen .core .UnicodeType ))
234- os .ttyname (proc .stderr .fileno ()) # crashes if wrong
270+ self . assertTrue ( os .isatty (proc .stderr .fileno ()))
235271
236272 flags = fcntl .fcntl (proc .stderr .fileno (), fcntl .F_GETFL )
237273 self .assertTrue (flags & os .O_RDWR )
238274 self .assertTrue (info ['flags' ] & os .O_RDWR )
239275
240- self .assertNotEquals (st .st_dev , info ['st_dev' ])
241276 self .assertTrue (flags & os .O_RDWR )
242277 self .assertTrue (buf , 'TEST' )
243278
0 commit comments