diff options
Diffstat (limited to 'Lib/test/test_posix.py')
-rw-r--r-- | Lib/test/test_posix.py | 190 |
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() |