Skip to content

Commit 55aa3ba

Browse files
committed
test: add windows integration test
1 parent 496bb0f commit 55aa3ba

6 files changed

Lines changed: 155 additions & 45 deletions

File tree

.github/workflows/python_tests.yml

Lines changed: 57 additions & 5 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,13 @@ 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]
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"
2223
steps:
2324
- uses: actions/checkout@v6
2425
- name: Set up Python ${{ matrix.python-version }}
@@ -32,9 +33,6 @@ jobs:
3233
python -m pip install --upgrade pip
3334
pip install --editable ".[dev]"
3435
- run: ./gyp -V && ./gyp --version && gyp -V && gyp --version
35-
- name: Lint with ruff # See pyproject.toml for settings
36-
uses: astral-sh/ruff-action@v3
37-
- run: ruff format --check --diff
3836
- name: Test with pytest # See pyproject.toml for settings
3937
run: pytest
4038
# - name: Run doctests with pytest
@@ -43,3 +41,57 @@ jobs:
4341
run: |
4442
pipx run --no-cache --spec ./ gyp --help
4543
pipx run --no-cache --spec ./ gyp --version
44+
45+
Python_tests_win:
46+
runs-on: ${{ matrix.os }}
47+
strategy:
48+
fail-fast: false
49+
max-parallel: 5
50+
matrix:
51+
os: [windows-latest]
52+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
53+
include:
54+
- os: windows-11-arm # Windows on ARM
55+
python-version: "3.14"
56+
steps:
57+
- uses: actions/checkout@v6
58+
- name: Set up Python ${{ matrix.python-version }}
59+
uses: actions/setup-python@v6
60+
with:
61+
python-version: ${{ matrix.python-version }}
62+
allow-prereleases: true
63+
- uses: seanmiddleditch/gha-setup-ninja@v6
64+
- name: Install dependencies
65+
run: |
66+
python -m pip install --upgrade pip
67+
pip install --editable ".[dev]"
68+
- run: ./gyp -V && ./gyp --version && gyp -V && gyp --version
69+
- name: Test with pytest # See pyproject.toml for settings
70+
shell: pwsh
71+
run: pytest
72+
- name: Test CLI commands on a pipx install
73+
run: |
74+
pipx run --no-cache --spec ./ gyp --help
75+
pipx run --no-cache --spec ./ gyp --version
76+
77+
Python_lint:
78+
runs-on: ubuntu-latest
79+
strategy:
80+
fail-fast: false
81+
max-parallel: 5
82+
matrix:
83+
python-version: ["3.14"]
84+
steps:
85+
- uses: actions/checkout@v6
86+
- name: Set up Python ${{ matrix.python-version }}
87+
uses: actions/setup-python@v6
88+
with:
89+
python-version: ${{ matrix.python-version }}
90+
allow-prereleases: true
91+
- name: Install dependencies
92+
run: |
93+
python -m pip install --upgrade pip
94+
pip install --editable ".[dev]"
95+
- name: Lint with ruff # See pyproject.toml for settings
96+
uses: astral-sh/ruff-action@v3
97+
- run: ruff format --check --diff

.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: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,38 @@
1313
from gyp.generator import ninja
1414

1515

16+
def _has_visual_studio():
17+
"""Check if Visual Studio can be detected by gyp's registry-based detection."""
18+
if not sys.platform.startswith("win"):
19+
return False
20+
try:
21+
from gyp.MSVSVersion import SelectVisualStudioVersion
22+
23+
SelectVisualStudioVersion("auto", allow_fallback=False)
24+
return True
25+
except ValueError:
26+
return False
27+
28+
1629
class TestPrefixesAndSuffixes(unittest.TestCase):
30+
@unittest.skipUnless(
31+
_has_visual_studio(),
32+
"requires Windows with a Visual Studio installation detected via the registry",
33+
)
1734
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-
)
35+
writer = ninja.NinjaWriter(
36+
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
37+
)
38+
spec = {"target_name": "wee"}
39+
self.assertTrue(
40+
writer.ComputeOutputFileName(spec, "executable").endswith(".exe")
41+
)
42+
self.assertTrue(
43+
writer.ComputeOutputFileName(spec, "shared_library").endswith(".dll")
44+
)
45+
self.assertTrue(
46+
writer.ComputeOutputFileName(spec, "static_library").endswith(".lib")
47+
)
3448

3549
def test_BinaryNamesLinux(self):
3650
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)