summaryrefslogtreecommitdiff
path: root/setuptools/_distutils/tests/test_spawn.py
blob: d2a898ed3f61ed61fb78a20de33cebeaf9088fb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Tests for distutils.spawn."""
import os
import stat
import sys
import unittest.mock as mock

from test.support import unix_shell

from . import py38compat as os_helper

from distutils.spawn import find_executable
from distutils.spawn import spawn
from distutils.errors import DistutilsExecError
from distutils.tests import support
import pytest


class TestSpawn(support.TempdirManager, support.LoggingSilencer):
    @pytest.mark.skipif("os.name not in ('nt', 'posix')")
    def test_spawn(self):
        tmpdir = self.mkdtemp()

        # creating something executable
        # through the shell that returns 1
        if sys.platform != 'win32':
            exe = os.path.join(tmpdir, 'foo.sh')
            self.write_file(exe, '#!%s\nexit 1' % unix_shell)
        else:
            exe = os.path.join(tmpdir, 'foo.bat')
            self.write_file(exe, 'exit 1')

        os.chmod(exe, 0o777)
        with pytest.raises(DistutilsExecError):
            spawn([exe])

        # now something that works
        if sys.platform != 'win32':
            exe = os.path.join(tmpdir, 'foo.sh')
            self.write_file(exe, '#!%s\nexit 0' % unix_shell)
        else:
            exe = os.path.join(tmpdir, 'foo.bat')
            self.write_file(exe, 'exit 0')

        os.chmod(exe, 0o777)
        spawn([exe])  # should work without any error

    def test_find_executable(self):
        with os_helper.temp_dir() as tmp_dir:
            # use TESTFN to get a pseudo-unique filename
            program_noeext = os_helper.TESTFN
            # Give the temporary program an ".exe" suffix for all.
            # It's needed on Windows and not harmful on other platforms.
            program = program_noeext + ".exe"

            filename = os.path.join(tmp_dir, program)
            with open(filename, "wb"):
                pass
            os.chmod(filename, stat.S_IXUSR)

            # test path parameter
            rv = find_executable(program, path=tmp_dir)
            assert rv == filename

            if sys.platform == 'win32':
                # test without ".exe" extension
                rv = find_executable(program_noeext, path=tmp_dir)
                assert rv == filename

            # test find in the current directory
            with os_helper.change_cwd(tmp_dir):
                rv = find_executable(program)
                assert rv == program

            # test non-existent program
            dont_exist_program = "dontexist_" + program
            rv = find_executable(dont_exist_program, path=tmp_dir)
            assert rv is None

            # PATH='': no match, except in the current directory
            with os_helper.EnvironmentVarGuard() as env:
                env['PATH'] = ''
                with mock.patch(
                    'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
                ), mock.patch('distutils.spawn.os.defpath', tmp_dir):
                    rv = find_executable(program)
                    assert rv is None

                    # look in current directory
                    with os_helper.change_cwd(tmp_dir):
                        rv = find_executable(program)
                        assert rv == program

            # PATH=':': explicitly looks in the current directory
            with os_helper.EnvironmentVarGuard() as env:
                env['PATH'] = os.pathsep
                with mock.patch(
                    'distutils.spawn.os.confstr', return_value='', create=True
                ), mock.patch('distutils.spawn.os.defpath', ''):
                    rv = find_executable(program)
                    assert rv is None

                    # look in current directory
                    with os_helper.change_cwd(tmp_dir):
                        rv = find_executable(program)
                        assert rv == program

            # missing PATH: test os.confstr("CS_PATH") and os.defpath
            with os_helper.EnvironmentVarGuard() as env:
                env.pop('PATH', None)

                # without confstr
                with mock.patch(
                    'distutils.spawn.os.confstr', side_effect=ValueError, create=True
                ), mock.patch('distutils.spawn.os.defpath', tmp_dir):
                    rv = find_executable(program)
                    assert rv == filename

                # with confstr
                with mock.patch(
                    'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
                ), mock.patch('distutils.spawn.os.defpath', ''):
                    rv = find_executable(program)
                    assert rv == filename

    def test_spawn_missing_exe(self):
        with pytest.raises(DistutilsExecError) as ctx:
            spawn(['does-not-exist'])
        assert "command 'does-not-exist' failed" in str(ctx.value)