Skip to content

Commit 7140586

Browse files
committed
tests: run on pyodide (#4745)
* tests: run on pyodide Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * ci: use cibuildwheel for pyodide test Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * tests: revert changes to test_embed Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> --------- Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
1 parent 1eb2e2c commit 7140586

File tree

10 files changed

+86
-6
lines changed

10 files changed

+86
-6
lines changed

.github/workflows/emscripten.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: WASM
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
branches:
7+
- master
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
build-wasm-emscripten:
15+
name: Pyodide wheel
16+
runs-on: ubuntu-22.04
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
submodules: true
21+
fetch-depth: 0
22+
23+
- uses: pypa/cibuildwheel@v2.19
24+
env:
25+
PYODIDE_BUILD_EXPORTS: whole_archive
26+
CFLAGS: -fexceptions
27+
LDFLAGS: -fexceptions
28+
with:
29+
package-dir: tests
30+
only: cp312-pyodide_wasm32

tests/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,12 @@ set(PYBIND11_TEST_FILTER
8888
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
8989
# We're being loaded directly, i.e. not via add_subdirectory, so make this
9090
# work as its own project and load the pybind11Config to get the tools we need
91-
find_package(pybind11 REQUIRED CONFIG)
91+
92+
if(SKBUILD)
93+
add_subdirectory(.. pybind11_src)
94+
else()
95+
find_package(pybind11 REQUIRED CONFIG)
96+
endif()
9297
endif()
9398

9499
if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
@@ -489,6 +494,9 @@ foreach(target ${test_targets})
489494
endforeach()
490495
endif()
491496
endif()
497+
if(SKBUILD)
498+
install(TARGETS ${target} LIBRARY DESTINATION .)
499+
endif()
492500
endforeach()
493501

494502
# Provide nice organisation in IDEs

tests/pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Warning: this is currently used for pyodide, and is not a general out-of-tree
2+
# builder for the tests (yet). Specifically, wheels can't be built from SDists.
3+
4+
[build-system]
5+
requires = ["scikit-build-core"]
6+
build-backend = "scikit_build_core.build"
7+
8+
[project]
9+
name = "pybind11_tests"
10+
version = "0.0.1"
11+
dependencies = ["pytest", "pytest-timeout", "numpy", "scipy"]
12+
13+
[tool.scikit-build.cmake.define]
14+
PYBIND11_FINDPYTHON = true
15+
16+
[tool.cibuildwheel]
17+
test-command = "pytest -o timeout=0 -p no:cacheprovider {project}/tests/test_*.py"

tests/test_async.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
from __future__ import annotations
22

3+
import sys
4+
35
import pytest
46

57
asyncio = pytest.importorskip("asyncio")
68
m = pytest.importorskip("pybind11_tests.async_module")
79

10+
if sys.platform.startswith("emscripten"):
11+
pytest.skip("Can't run a new event_loop in pyodide", allow_module_level=True)
12+
813

914
@pytest.fixture()
1015
def event_loop():

tests/test_callbacks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import sys
34
import time
45
from threading import Thread
56

@@ -153,6 +154,7 @@ def test_python_builtins():
153154
assert m.test_sum_builtin(sum, []) == 0
154155

155156

157+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
156158
def test_async_callbacks():
157159
# serves as state for async callback
158160
class Item:
@@ -176,6 +178,7 @@ def gen_f():
176178
assert sum(res) == sum(x + 3 for x in work)
177179

178180

181+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
179182
def test_async_async_callbacks():
180183
t = Thread(target=test_async_callbacks)
181184
t.start()

tests/test_exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def test_cross_module_exceptions(msg):
7575

7676
# TODO: FIXME
7777
@pytest.mark.xfail(
78-
"env.MACOS and (env.PYPY or pybind11_tests.compiler_info.startswith('Homebrew Clang'))",
78+
"env.MACOS and (env.PYPY or pybind11_tests.compiler_info.startswith('Homebrew Clang')) or sys.platform.startswith('emscripten')",
7979
raises=RuntimeError,
8080
reason="See Issue #2847, PR #2999, PR #4324",
8181
)

tests/test_gil_scoped.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,24 +71,28 @@ def test_cross_module_gil_inner_pybind11_acquired():
7171
m.test_cross_module_gil_inner_pybind11_acquired()
7272

7373

74+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
7475
def test_cross_module_gil_nested_custom_released():
7576
"""Makes sure that the GIL can be nested acquired/released by another module
7677
from a GIL-released state using custom locking logic."""
7778
m.test_cross_module_gil_nested_custom_released()
7879

7980

81+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
8082
def test_cross_module_gil_nested_custom_acquired():
8183
"""Makes sure that the GIL can be nested acquired/acquired by another module
8284
from a GIL-acquired state using custom locking logic."""
8385
m.test_cross_module_gil_nested_custom_acquired()
8486

8587

88+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
8689
def test_cross_module_gil_nested_pybind11_released():
8790
"""Makes sure that the GIL can be nested acquired/released by another module
8891
from a GIL-released state using pybind11 locking logic."""
8992
m.test_cross_module_gil_nested_pybind11_released()
9093

9194

95+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
9296
def test_cross_module_gil_nested_pybind11_acquired():
9397
"""Makes sure that the GIL can be nested acquired/acquired by another module
9498
from a GIL-acquired state using pybind11 locking logic."""
@@ -103,6 +107,7 @@ def test_nested_acquire():
103107
assert m.test_nested_acquire(0xAB) == "171"
104108

105109

110+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
106111
def test_multi_acquire_release_cross_module():
107112
for bits in range(16 * 8):
108113
internals_ids = m.test_multi_acquire_release_cross_module(bits)
@@ -204,7 +209,7 @@ def _run_in_threads(test_fn, num_threads, parallel):
204209
thread.join()
205210

206211

207-
# TODO: FIXME, sometimes returns -11 (segfault) instead of 0 on macOS Python 3.9
212+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
208213
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
209214
def test_run_in_process_one_thread(test_fn):
210215
"""Makes sure there is no GIL deadlock when running in a thread.
@@ -214,7 +219,7 @@ def test_run_in_process_one_thread(test_fn):
214219
assert _run_in_process(_run_in_threads, test_fn, num_threads=1, parallel=False) == 0
215220

216221

217-
# TODO: FIXME on macOS Python 3.9
222+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
218223
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
219224
def test_run_in_process_multiple_threads_parallel(test_fn):
220225
"""Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
@@ -224,7 +229,7 @@ def test_run_in_process_multiple_threads_parallel(test_fn):
224229
assert _run_in_process(_run_in_threads, test_fn, num_threads=8, parallel=True) == 0
225230

226231

227-
# TODO: FIXME on macOS Python 3.9
232+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
228233
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
229234
def test_run_in_process_multiple_threads_sequential(test_fn):
230235
"""Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
@@ -234,7 +239,7 @@ def test_run_in_process_multiple_threads_sequential(test_fn):
234239
assert _run_in_process(_run_in_threads, test_fn, num_threads=8, parallel=False) == 0
235240

236241

237-
# TODO: FIXME on macOS Python 3.9
242+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
238243
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
239244
def test_run_in_process_direct(test_fn):
240245
"""Makes sure there is no GIL deadlock when using processes.

tests/test_iostream.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
from __future__ import annotations
22

3+
import sys
34
from contextlib import redirect_stderr, redirect_stdout
45
from io import StringIO
56

7+
import pytest
8+
69
from pybind11_tests import iostream as m
710

811

@@ -270,6 +273,7 @@ def test_redirect_both(capfd):
270273
assert stream2.getvalue() == msg2
271274

272275

276+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
273277
def test_threading():
274278
with m.ostream_redirect(stdout=True, stderr=False):
275279
# start some threads

tests/test_thread.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from __future__ import annotations
22

3+
import sys
34
import threading
45

6+
import pytest
7+
58
from pybind11_tests import thread as m
69

710

@@ -24,6 +27,7 @@ def join(self):
2427
raise self.e
2528

2629

30+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
2731
def test_implicit_conversion():
2832
a = Thread(m.test)
2933
b = Thread(m.test)
@@ -34,6 +38,7 @@ def test_implicit_conversion():
3438
x.join()
3539

3640

41+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
3742
def test_implicit_conversion_no_gil():
3843
a = Thread(m.test_no_gil)
3944
b = Thread(m.test_no_gil)

tests/test_virtual_functions.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import sys
4+
35
import pytest
46

57
import env # noqa: F401
@@ -435,6 +437,7 @@ def lucky_number(self):
435437
assert obj.say_everything() == "BT -7"
436438

437439

440+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
438441
def test_issue_1454():
439442
# Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
440443
m.test_gil()

0 commit comments

Comments
 (0)