summaryrefslogtreecommitdiffstats
path: root/Lib/distutils/tests/test_spawn.py
blob: f9ae69ef86b3dae9bdbf182052db38c7a414f1c3 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""Tests for distutils.spawn."""
import os
import stat
import sys
import unittest
from unittest import mock
from test.support import run_unittest, unix_shell
from test import support as test_support

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

class SpawnTestCase(support.TempdirManager,
                    support.LoggingSilencer,
                    unittest.TestCase):

    def test_nt_quote_args(self):

        for (args, wanted) in ((['with space', 'nospace'],
                                ['"with space"', 'nospace']),
                               (['nochange', 'nospace'],
                                ['nochange', 'nospace'])):
            res = _nt_quote_args(args)
            self.assertEqual(res, wanted)


    @unittest.skipUnless(os.name in ('nt', 'posix'),
                         'Runs only under posix or nt')
    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)
        self.assertRaises(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 test_support.temp_dir() as tmp_dir:
            # use TESTFN to get a pseudo-unique filename
            program_noeext = test_support.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)
            self.assertEqual(rv, filename)

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

            # test find in the current directory
            with test_support.change_cwd(tmp_dir):
                rv = find_executable(program)
                self.assertEqual(rv, program)

            # test non-existent program
            dont_exist_program = "dontexist_" + program
            rv = find_executable(dont_exist_program , path=tmp_dir)
            self.assertIsNone(rv)

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

                    # look in current directory
                    with test_support.change_cwd(tmp_dir):
                        rv = find_executable(program)
                        self.assertEqual(rv, program)

            # PATH=':': explicitly looks in the current directory
            with test_support.EnvironmentVarGuard() as env:
                env['PATH'] = os.pathsep
                with unittest.mock.patch('distutils.spawn.os.confstr',
                                         return_value='', create=True), \
                     unittest.mock.patch('distutils.spawn.os.defpath', ''):
                    rv = find_executable(program)
                    self.assertIsNone(rv)

                    # look in current directory
                    with test_support.change_cwd(tmp_dir):
                        rv = find_executable(program)
                        self.assertEqual(rv, program)

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

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

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


def test_suite():
    return unittest.makeSuite(SpawnTestCase)

if __name__ == "__main__":
    run_unittest(test_suite())