summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_posix.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_posix.py')
-rw-r--r--Lib/test/test_posix.py190
1 files changed, 119 insertions, 71 deletions
diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
index d7e512c..79fc3c2 100644
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -1489,10 +1489,10 @@ class PosixGroupsTester(unittest.TestCase):
self.assertListEqual(groups, posix.getgroups())
-@unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn")
-class TestPosixSpawn(unittest.TestCase):
- # Program which does nothing and exit with status 0 (success)
+class _PosixSpawnMixin:
+ # Program which does nothing and exits with status 0 (success)
NOOP_PROGRAM = (sys.executable, '-I', '-S', '-c', 'pass')
+ spawn_func = None
def python_args(self, *args):
# Disable site module to avoid side effects. For example,
@@ -1511,7 +1511,7 @@ class TestPosixSpawn(unittest.TestCase):
pidfile.write(str(os.getpid()))
"""
args = self.python_args('-c', script)
- pid = posix.posix_spawn(args[0], args, os.environ)
+ pid = self.spawn_func(args[0], args, os.environ)
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
with open(pidfile) as f:
self.assertEqual(f.read(), str(pid))
@@ -1519,9 +1519,9 @@ class TestPosixSpawn(unittest.TestCase):
def test_no_such_executable(self):
no_such_executable = 'no_such_executable'
try:
- pid = posix.posix_spawn(no_such_executable,
- [no_such_executable],
- os.environ)
+ pid = self.spawn_func(no_such_executable,
+ [no_such_executable],
+ os.environ)
except FileNotFoundError as exc:
self.assertEqual(exc.filename, no_such_executable)
else:
@@ -1538,14 +1538,14 @@ class TestPosixSpawn(unittest.TestCase):
envfile.write(os.environ['foo'])
"""
args = self.python_args('-c', script)
- pid = posix.posix_spawn(args[0], args,
- {**os.environ, 'foo': 'bar'})
+ pid = self.spawn_func(args[0], args,
+ {**os.environ, 'foo': 'bar'})
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
with open(envfile) as f:
self.assertEqual(f.read(), 'bar')
def test_empty_file_actions(self):
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
self.NOOP_PROGRAM[0],
self.NOOP_PROGRAM,
os.environ,
@@ -1554,7 +1554,7 @@ class TestPosixSpawn(unittest.TestCase):
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
def test_resetids_explicit_default(self):
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', 'pass'],
os.environ,
@@ -1563,7 +1563,7 @@ class TestPosixSpawn(unittest.TestCase):
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
def test_resetids(self):
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', 'pass'],
os.environ,
@@ -1573,12 +1573,12 @@ class TestPosixSpawn(unittest.TestCase):
def test_resetids_wrong_type(self):
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, resetids=None)
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, resetids=None)
def test_setpgroup(self):
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', 'pass'],
os.environ,
@@ -1588,9 +1588,9 @@ class TestPosixSpawn(unittest.TestCase):
def test_setpgroup_wrong_type(self):
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setpgroup="023")
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setpgroup="023")
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
'need signal.pthread_sigmask()')
@@ -1599,7 +1599,7 @@ class TestPosixSpawn(unittest.TestCase):
import signal
signal.raise_signal(signal.SIGUSR1)""")
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', code],
os.environ,
@@ -1609,18 +1609,18 @@ class TestPosixSpawn(unittest.TestCase):
def test_setsigmask_wrong_type(self):
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigmask=34)
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigmask=34)
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigmask=["j"])
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigmask=["j"])
with self.assertRaises(ValueError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigmask=[signal.NSIG,
- signal.NSIG+1])
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigmask=[signal.NSIG,
+ signal.NSIG+1])
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
'need signal.pthread_sigmask()')
@@ -1630,7 +1630,7 @@ class TestPosixSpawn(unittest.TestCase):
import signal
signal.raise_signal(signal.SIGUSR1)""")
try:
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', code],
os.environ,
@@ -1646,17 +1646,17 @@ class TestPosixSpawn(unittest.TestCase):
def test_setsigdef_wrong_type(self):
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigdef=34)
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigdef=34)
with self.assertRaises(TypeError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigdef=["j"])
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigdef=["j"])
with self.assertRaises(ValueError):
- posix.posix_spawn(sys.executable,
- [sys.executable, "-c", "pass"],
- os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
+ self.spawn_func(sys.executable,
+ [sys.executable, "-c", "pass"],
+ os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
@requires_sched
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
@@ -1670,7 +1670,7 @@ class TestPosixSpawn(unittest.TestCase):
sys.exit(101)
if os.sched_getparam(0).sched_priority != {priority}:
sys.exit(102)""")
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', code],
os.environ,
@@ -1690,7 +1690,7 @@ class TestPosixSpawn(unittest.TestCase):
sys.exit(101)
if os.sched_getparam(0).sched_priority != {priority}:
sys.exit(102)""")
- pid = posix.posix_spawn(
+ pid = self.spawn_func(
sys.executable,
[sys.executable, '-c', code],
os.environ,
@@ -1704,40 +1704,40 @@ class TestPosixSpawn(unittest.TestCase):
(os.POSIX_SPAWN_CLOSE, 0),
(os.POSIX_SPAWN_DUP2, 1, 4),
]
- pid = posix.posix_spawn(self.NOOP_PROGRAM[0],
- self.NOOP_PROGRAM,
- os.environ,
- file_actions=file_actions)
+ pid = self.spawn_func(self.NOOP_PROGRAM[0],
+ self.NOOP_PROGRAM,
+ os.environ,
+ file_actions=file_actions)
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
def test_bad_file_actions(self):
args = self.NOOP_PROGRAM
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[None])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[None])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[()])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[()])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(None,)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(None,)])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(12345,)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(12345,)])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(os.POSIX_SPAWN_CLOSE,)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(os.POSIX_SPAWN_CLOSE,)])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(os.POSIX_SPAWN_CLOSE, 1, 2)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(os.POSIX_SPAWN_CLOSE, 1, 2)])
with self.assertRaises(TypeError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(os.POSIX_SPAWN_CLOSE, None)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(os.POSIX_SPAWN_CLOSE, None)])
with self.assertRaises(ValueError):
- posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(os.POSIX_SPAWN_OPEN,
- 3, __file__ + '\0',
- os.O_RDONLY, 0)])
+ self.spawn_func(args[0], args, os.environ,
+ file_actions=[(os.POSIX_SPAWN_OPEN,
+ 3, __file__ + '\0',
+ os.O_RDONLY, 0)])
def test_open_file(self):
outfile = support.TESTFN
@@ -1752,8 +1752,8 @@ class TestPosixSpawn(unittest.TestCase):
stat.S_IRUSR | stat.S_IWUSR),
]
args = self.python_args('-c', script)
- pid = posix.posix_spawn(args[0], args, os.environ,
- file_actions=file_actions)
+ pid = self.spawn_func(args[0], args, os.environ,
+ file_actions=file_actions)
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
with open(outfile) as f:
self.assertEqual(f.read(), 'hello')
@@ -1770,8 +1770,8 @@ class TestPosixSpawn(unittest.TestCase):
closefile.write('is closed %d' % e.errno)
"""
args = self.python_args('-c', script)
- pid = posix.posix_spawn(args[0], args, os.environ,
- file_actions=[(os.POSIX_SPAWN_CLOSE, 0),])
+ pid = self.spawn_func(args[0], args, os.environ,
+ file_actions=[(os.POSIX_SPAWN_CLOSE, 0)])
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
with open(closefile) as f:
self.assertEqual(f.read(), 'is closed %d' % errno.EBADF)
@@ -1788,16 +1788,64 @@ class TestPosixSpawn(unittest.TestCase):
(os.POSIX_SPAWN_DUP2, childfile.fileno(), 1),
]
args = self.python_args('-c', script)
- pid = posix.posix_spawn(args[0], args, os.environ,
- file_actions=file_actions)
+ pid = self.spawn_func(args[0], args, os.environ,
+ file_actions=file_actions)
self.assertEqual(os.waitpid(pid, 0), (pid, 0))
with open(dupfile) as f:
self.assertEqual(f.read(), 'hello')
+@unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn")
+class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin):
+ spawn_func = getattr(posix, 'posix_spawn', None)
+
+
+@unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp")
+class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
+ spawn_func = getattr(posix, 'posix_spawnp', None)
+
+ @support.skip_unless_symlink
+ def test_posix_spawnp(self):
+ # Use a symlink to create a program in its own temporary directory
+ temp_dir = tempfile.mkdtemp()
+ self.addCleanup(support.rmtree, temp_dir)
+
+ program = 'posix_spawnp_test_program.exe'
+ program_fullpath = os.path.join(temp_dir, program)
+ os.symlink(sys.executable, program_fullpath)
+
+ try:
+ path = os.pathsep.join((temp_dir, os.environ['PATH']))
+ except KeyError:
+ path = temp_dir # PATH is not set
+
+ spawn_args = (program, '-I', '-S', '-c', 'pass')
+ code = textwrap.dedent("""
+ import os
+ args = %a
+ pid = os.posix_spawnp(args[0], args, os.environ)
+ pid2, status = os.waitpid(pid, 0)
+ if pid2 != pid:
+ raise Exception(f"pid {pid2} != {pid}")
+ if status != 0:
+ raise Exception(f"status {status} != 0")
+ """ % (spawn_args,))
+
+ # Use a subprocess to test os.posix_spawnp() with a modified PATH
+ # environment variable: posix_spawnp() uses the current environment
+ # to locate the program, not its environment argument.
+ args = ('-c', code)
+ assert_python_ok(*args, PATH=path)
+
+
def test_main():
try:
- support.run_unittest(PosixTester, PosixGroupsTester, TestPosixSpawn)
+ support.run_unittest(
+ PosixTester,
+ PosixGroupsTester,
+ TestPosixSpawn,
+ TestPosixSpawnP,
+ )
finally:
support.reap_children()