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