1"""Tests for distutils.spawn.""" 2import os 3import stat 4import sys 5import unittest.mock 6from test.support import run_unittest, unix_shell, requires_subprocess 7from test.support import os_helper 8 9from distutils.spawn import find_executable 10from distutils.spawn import spawn 11from distutils.errors import DistutilsExecError 12from distutils.tests import support 13 14 15@requires_subprocess() 16class SpawnTestCase(support.TempdirManager, 17 support.LoggingSilencer, 18 unittest.TestCase): 19 20 @unittest.skipUnless(os.name in ('nt', 'posix'), 21 'Runs only under posix or nt') 22 def test_spawn(self): 23 tmpdir = self.mkdtemp() 24 25 # creating something executable 26 # through the shell that returns 1 27 if sys.platform != 'win32': 28 exe = os.path.join(tmpdir, 'foo.sh') 29 self.write_file(exe, '#!%s\nexit 1' % unix_shell) 30 else: 31 exe = os.path.join(tmpdir, 'foo.bat') 32 self.write_file(exe, 'exit 1') 33 34 os.chmod(exe, 0o777) 35 self.assertRaises(DistutilsExecError, spawn, [exe]) 36 37 # now something that works 38 if sys.platform != 'win32': 39 exe = os.path.join(tmpdir, 'foo.sh') 40 self.write_file(exe, '#!%s\nexit 0' % unix_shell) 41 else: 42 exe = os.path.join(tmpdir, 'foo.bat') 43 self.write_file(exe, 'exit 0') 44 45 os.chmod(exe, 0o777) 46 spawn([exe]) # should work without any error 47 48 def test_find_executable(self): 49 with os_helper.temp_dir() as tmp_dir: 50 # use TESTFN to get a pseudo-unique filename 51 program_noeext = os_helper.TESTFN 52 # Give the temporary program an ".exe" suffix for all. 53 # It's needed on Windows and not harmful on other platforms. 54 program = program_noeext + ".exe" 55 56 filename = os.path.join(tmp_dir, program) 57 with open(filename, "wb"): 58 pass 59 os.chmod(filename, stat.S_IXUSR) 60 61 # test path parameter 62 rv = find_executable(program, path=tmp_dir) 63 self.assertEqual(rv, filename) 64 65 if sys.platform == 'win32': 66 # test without ".exe" extension 67 rv = find_executable(program_noeext, path=tmp_dir) 68 self.assertEqual(rv, filename) 69 70 # test find in the current directory 71 with os_helper.change_cwd(tmp_dir): 72 rv = find_executable(program) 73 self.assertEqual(rv, program) 74 75 # test non-existent program 76 dont_exist_program = "dontexist_" + program 77 rv = find_executable(dont_exist_program , path=tmp_dir) 78 self.assertIsNone(rv) 79 80 # PATH='': no match, except in the current directory 81 with os_helper.EnvironmentVarGuard() as env: 82 env['PATH'] = '' 83 with unittest.mock.patch('distutils.spawn.os.confstr', 84 return_value=tmp_dir, create=True), \ 85 unittest.mock.patch('distutils.spawn.os.defpath', 86 tmp_dir): 87 rv = find_executable(program) 88 self.assertIsNone(rv) 89 90 # look in current directory 91 with os_helper.change_cwd(tmp_dir): 92 rv = find_executable(program) 93 self.assertEqual(rv, program) 94 95 # PATH=':': explicitly looks in the current directory 96 with os_helper.EnvironmentVarGuard() as env: 97 env['PATH'] = os.pathsep 98 with unittest.mock.patch('distutils.spawn.os.confstr', 99 return_value='', create=True), \ 100 unittest.mock.patch('distutils.spawn.os.defpath', ''): 101 rv = find_executable(program) 102 self.assertIsNone(rv) 103 104 # look in current directory 105 with os_helper.change_cwd(tmp_dir): 106 rv = find_executable(program) 107 self.assertEqual(rv, program) 108 109 # missing PATH: test os.confstr("CS_PATH") and os.defpath 110 with os_helper.EnvironmentVarGuard() as env: 111 env.pop('PATH', None) 112 113 # without confstr 114 with unittest.mock.patch('distutils.spawn.os.confstr', 115 side_effect=ValueError, 116 create=True), \ 117 unittest.mock.patch('distutils.spawn.os.defpath', 118 tmp_dir): 119 rv = find_executable(program) 120 self.assertEqual(rv, filename) 121 122 # with confstr 123 with unittest.mock.patch('distutils.spawn.os.confstr', 124 return_value=tmp_dir, create=True), \ 125 unittest.mock.patch('distutils.spawn.os.defpath', ''): 126 rv = find_executable(program) 127 self.assertEqual(rv, filename) 128 129 def test_spawn_missing_exe(self): 130 with self.assertRaises(DistutilsExecError) as ctx: 131 spawn(['does-not-exist']) 132 self.assertIn("command 'does-not-exist' failed", str(ctx.exception)) 133 134 135def test_suite(): 136 return unittest.TestLoader().loadTestsFromTestCase(SpawnTestCase) 137 138if __name__ == "__main__": 139 run_unittest(test_suite()) 140