Skip to content

Commit 4c8b771

Browse files
legendecascclauss
andauthored
test: add windows integration test (#335)
Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 496bb0f commit 4c8b771

6 files changed

Lines changed: 99 additions & 42 deletions

File tree

.github/workflows/python_tests.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# TODO: Enable os: windows-latest
21
# TODO: Enable pytest --doctest-modules
32

43
name: Python_tests
@@ -14,11 +13,15 @@ jobs:
1413
fail-fast: false
1514
max-parallel: 5
1615
matrix:
17-
os: [macos-15-intel, macos-latest, ubuntu-latest] # , windows-latest]
16+
os: [macos-15-intel, macos-latest, ubuntu-latest, windows-latest]
1817
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
1918
include:
2019
- os: macos-26
2120
python-version: 3.x
21+
- os: ubuntu-24.04-arm # Ubuntu on ARM
22+
python-version: "3.14"
23+
- os: windows-11-arm # Windows on ARM
24+
python-version: "3.14"
2225
steps:
2326
- uses: actions/checkout@v6
2427
- name: Set up Python ${{ matrix.python-version }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,7 @@ static
144144

145145
test/fixtures/out
146146
*.actual
147+
*.sln
148+
*.vcproj
149+
!test/fixtures/expected-win32/**/*.sln
150+
!test/fixtures/expected-win32/**/*.vcproj

pylib/gyp/generator/ninja_test.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,36 @@
1111
from pathlib import Path
1212

1313
from gyp.generator import ninja
14+
from gyp.MSVSVersion import SelectVisualStudioVersion
15+
16+
17+
def _has_visual_studio():
18+
"""Check if Visual Studio can be detected by gyp's registry-based detection."""
19+
if not sys.platform.startswith("win"):
20+
return False
21+
try:
22+
SelectVisualStudioVersion("auto", allow_fallback=False)
23+
return True
24+
except ValueError:
25+
return False
1426

1527

1628
class TestPrefixesAndSuffixes(unittest.TestCase):
29+
@unittest.skipUnless(
30+
_has_visual_studio(),
31+
"requires Windows with a Visual Studio installation detected via the registry",
32+
)
1733
def test_BinaryNamesWindows(self):
18-
# These cannot run on non-Windows as they require a VS installation to
19-
# correctly handle variable expansion.
20-
if sys.platform.startswith("win"):
21-
writer = ninja.NinjaWriter(
22-
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
23-
)
24-
spec = {"target_name": "wee"}
25-
self.assertTrue(
26-
writer.ComputeOutputFileName(spec, "executable").endswith(".exe")
27-
)
28-
self.assertTrue(
29-
writer.ComputeOutputFileName(spec, "shared_library").endswith(".dll")
30-
)
31-
self.assertTrue(
32-
writer.ComputeOutputFileName(spec, "static_library").endswith(".lib")
33-
)
34+
writer = ninja.NinjaWriter(
35+
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
36+
)
37+
spec = {"target_name": "wee"}
38+
for key, ext in {
39+
"executable": ".exe",
40+
"shared_library": ".dll",
41+
"static_library": ".lib",
42+
}:
43+
self.assertTrue(writer.ComputeOutputFileName(spec, key).endswith(ext))
3444

3545
def test_BinaryNamesLinux(self):
3646
writer = ninja.NinjaWriter(
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Microsoft Visual Studio Solution File, Format Version 9.00
2+
# Visual Studio 2005
3+
Project("{*}") = "test", "test.vcproj", "{*}"
4+
EndProject
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Default|Win32 = Default|Win32
8+
EndGlobalSection
9+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
10+
{*}.Default|Win32.ActiveCfg = Default|Win32
11+
{*}.Default|Win32.Build.0 = Default|Win32
12+
EndGlobalSection
13+
GlobalSection(SolutionProperties) = preSolution
14+
HideSolutionNode = FALSE
15+
EndGlobalSection
16+
EndGlobal
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<?xml version="1.0" encoding="Windows-1252"?><VisualStudioProject Keyword="Win32Proj" Name="test" ProjectGUID="{*}" ProjectType="Visual C++" RootNamespace="test" Version="8.00"><Platforms><Platform Name="Win32"/></Platforms><ToolFiles/><Configurations><Configuration ConfigurationType="1" IntermediateDirectory="$(ConfigurationName)\obj\$(ProjectName)\" Name="Default|Win32" OutputDirectory="$(SolutionDir)$(ConfigurationName)\"><Tool AdditionalDependencies="$(NOINHERIT)" AdditionalLibraryDirectories="mylib" Name="VCLinkerTool" OutputFile="$(OutDir)\$(ProjectName).exe"/><Tool AdditionalIncludeDirectories="include" Name="VCCLCompilerTool" ProgramDataBaseFileName="$(IntDir)$(ProjectName)\vc80.pdb"/><Tool AdditionalIncludeDirectories="include" Name="VCResourceCompilerTool"/></Configuration></Configurations><References/><Files><File RelativePath="test.cc"/><File RelativePath="integration.gyp"/></Files><Globals/></VisualStudioProject>

test/integration_test.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,56 @@
55
import os
66
import re
77
import shutil
8+
import sys
89
import unittest
910

1011
import gyp
1112

1213
fixture_dir = os.path.join(os.path.dirname(__file__), "fixtures")
1314
gyp_file = os.path.join(os.path.dirname(__file__), "fixtures/integration.gyp")
1415

15-
supported_sysnames = {"darwin", "linux"}
16-
sysname = os.uname().sysname.lower()
16+
if sys.platform == "win32":
17+
sysname = sys.platform
18+
else:
19+
sysname = os.uname().sysname.lower()
1720
expected_dir = os.path.join(fixture_dir, f"expected-{sysname}")
1821

1922

20-
class TestGyp(unittest.TestCase):
21-
def setUp(self) -> None:
22-
if sysname not in supported_sysnames:
23-
self.skipTest(f"Unsupported system: {sysname}")
24-
shutil.rmtree(os.path.join(fixture_dir, "out"), ignore_errors=True)
23+
def assert_file(test, actual, expected) -> None:
24+
actual_filepath = os.path.join(fixture_dir, actual)
25+
expected_filepath = os.path.join(expected_dir, expected)
26+
27+
with open(expected_filepath) as in_file:
28+
in_bytes = in_file.read()
29+
in_bytes = in_bytes.strip()
30+
expected_bytes = re.escape(in_bytes)
31+
expected_bytes = expected_bytes.replace("\\*", ".*")
32+
expected_re = re.compile(expected_bytes)
2533

26-
def assert_file(self, actual, expected) -> None:
27-
actual_filepath = os.path.join(fixture_dir, actual)
28-
expected_filepath = os.path.join(expected_dir, expected)
34+
with open(actual_filepath) as in_file:
35+
actual_bytes = in_file.read()
36+
actual_bytes = actual_bytes.strip()
2937

30-
with open(expected_filepath) as in_file:
31-
expected_bytes = re.escape(in_file.read())
32-
expected_bytes = expected_bytes.replace("\\*", ".*")
33-
expected_re = re.compile(expected_bytes)
38+
try:
39+
test.assertRegex(actual_bytes, expected_re)
40+
except Exception:
41+
shutil.copyfile(actual_filepath, f"{expected_filepath}.actual")
42+
raise
3443

35-
with open(actual_filepath) as in_file:
36-
actual_bytes = in_file.read()
3744

38-
try:
39-
self.assertRegex(actual_bytes, expected_re)
40-
except Exception:
41-
shutil.copyfile(actual_filepath, f"{expected_filepath}.actual")
42-
raise
45+
class TestGypUnix(unittest.TestCase):
46+
supported_sysnames = {"darwin", "linux"}
47+
48+
def setUp(self) -> None:
49+
if sysname not in TestGypUnix.supported_sysnames:
50+
self.skipTest(f"Unsupported system: {sysname}")
51+
shutil.rmtree(os.path.join(fixture_dir, "out"), ignore_errors=True)
4352

4453
def test_ninja(self) -> None:
4554
rc = gyp.main(["-f", "ninja", "--depth", fixture_dir, gyp_file])
4655
assert rc == 0
4756

48-
self.assert_file("out/Default/obj/test.ninja", "ninja/test.ninja")
57+
assert_file(self, "out/Default/obj/test.ninja", "ninja/test.ninja")
4958

5059
def test_make(self) -> None:
5160
rc = gyp.main(
@@ -61,10 +70,24 @@ def test_make(self) -> None:
6170
)
6271
assert rc == 0
6372

64-
self.assert_file("out/test.target.mk", "make/test.target.mk")
73+
assert_file(self, "out/test.target.mk", "make/test.target.mk")
6574

6675
def test_cmake(self) -> None:
6776
rc = gyp.main(["-f", "cmake", "--depth", fixture_dir, gyp_file])
6877
assert rc == 0
6978

70-
self.assert_file("out/Default/CMakeLists.txt", "cmake/CMakeLists.txt")
79+
assert_file(self, "out/Default/CMakeLists.txt", "cmake/CMakeLists.txt")
80+
81+
82+
class TestGypWindows(unittest.TestCase):
83+
def setUp(self) -> None:
84+
if sys.platform != "win32":
85+
self.skipTest("Windows-only test")
86+
shutil.rmtree(os.path.join(fixture_dir, "out"), ignore_errors=True)
87+
88+
def test_msvs(self) -> None:
89+
rc = gyp.main(["-f", "msvs", "--depth", fixture_dir, gyp_file])
90+
assert rc == 0
91+
92+
assert_file(self, "test.vcproj", "msvs/test.vcproj")
93+
assert_file(self, "integration.sln", "msvs/integration.sln")

0 commit comments

Comments
 (0)