Skip to content

Commit dcfd733

Browse files
committed
issue #549: remove Linux-specific assumptions from create_child_test
Some stat fields are implementation-specific, little value even testing them on Linux
1 parent 395b03a commit dcfd733

File tree

1 file changed

+48
-13
lines changed

1 file changed

+48
-13
lines changed

tests/create_child_test.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,46 @@
1515
import 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+
1828
def 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

223258
class 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

Comments
 (0)