aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_msvc.py
blob: eca831996adcb07f05560581fe4285cdb29392d3 (about) (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
import os
import sys
import sysconfig
import threading
import unittest.mock as mock
from distutils.errors import DistutilsPlatformError
from distutils.tests import support
from distutils.util import get_platform

import pytest

from .. import msvc

needs_winreg = pytest.mark.skipif('not hasattr(msvc, "winreg")')


class Testmsvccompiler(support.TempdirManager):
    def test_no_compiler(self, monkeypatch):
        # makes sure query_vcvarsall raises
        # a DistutilsPlatformError if the compiler
        # is not found
        def _find_vcvarsall(plat_spec):
            return None, None

        monkeypatch.setattr(msvc, '_find_vcvarsall', _find_vcvarsall)

        with pytest.raises(DistutilsPlatformError):
            msvc._get_vc_env(
                'wont find this version',
            )

    @pytest.mark.skipif(
        not sysconfig.get_platform().startswith("win"),
        reason="Only run test for non-mingw Windows platforms",
    )
    @pytest.mark.parametrize(
        "plat_name, expected",
        [
            ("win-arm64", "win-arm64"),
            ("win-amd64", "win-amd64"),
            (None, get_platform()),
        ],
    )
    def test_cross_platform_compilation_paths(self, monkeypatch, plat_name, expected):
        """
        Ensure a specified target platform is passed to _get_vcvars_spec.
        """
        compiler = msvc.Compiler()

        def _get_vcvars_spec(host_platform, platform):
            assert platform == expected

        monkeypatch.setattr(msvc, '_get_vcvars_spec', _get_vcvars_spec)
        compiler.initialize(plat_name)

    @needs_winreg
    def test_get_vc_env_unicode(self):
        test_var = 'ṰḖṤṪ┅ṼẨṜ'
        test_value = '₃⁴₅'

        # Ensure we don't early exit from _get_vc_env
        old_distutils_use_sdk = os.environ.pop('DISTUTILS_USE_SDK', None)
        os.environ[test_var] = test_value
        try:
            env = msvc._get_vc_env('x86')
            assert test_var.lower() in env
            assert test_value == env[test_var.lower()]
        finally:
            os.environ.pop(test_var)
            if old_distutils_use_sdk:
                os.environ['DISTUTILS_USE_SDK'] = old_distutils_use_sdk

    @needs_winreg
    @pytest.mark.parametrize('ver', (2015, 2017))
    def test_get_vc(self, ver):
        # This function cannot be mocked, so pass if VC is found
        # and skip otherwise.
        lookup = getattr(msvc, f'_find_vc{ver}')
        expected_version = {2015: 14, 2017: 15}[ver]
        version, path = lookup()
        if not version:
            pytest.skip(f"VS {ver} is not installed")
        assert version >= expected_version
        assert os.path.isdir(path)


class CheckThread(threading.Thread):
    exc_info = None

    def run(self):
        try:
            super().run()
        except Exception:
            self.exc_info = sys.exc_info()

    def __bool__(self):
        return not self.exc_info


class TestSpawn:
    def test_concurrent_safe(self):
        """
        Concurrent calls to spawn should have consistent results.
        """
        compiler = msvc.Compiler()
        compiler._paths = "expected"
        inner_cmd = 'import os; assert os.environ["PATH"] == "expected"'
        command = [sys.executable, '-c', inner_cmd]

        threads = [
            CheckThread(target=compiler.spawn, args=[command]) for n in range(100)
        ]
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()
        assert all(threads)

    def test_concurrent_safe_fallback(self):
        """
        If CCompiler.spawn has been monkey-patched without support
        for an env, it should still execute.
        """
        from distutils import ccompiler

        compiler = msvc.Compiler()
        compiler._paths = "expected"

        def CCompiler_spawn(self, cmd):
            "A spawn without an env argument."
            assert os.environ["PATH"] == "expected"

        with mock.patch.object(ccompiler.CCompiler, 'spawn', CCompiler_spawn):
            compiler.spawn(["n/a"])

        assert os.environ.get("PATH") != "expected"