Skip to content

Commit 4e811a4

Browse files
committed
tests: run on pyodide
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
1 parent 895e657 commit 4e811a4

File tree

12 files changed

+124
-6
lines changed

12 files changed

+124
-6
lines changed

.github/workflows/emscripten.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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@v3
19+
with:
20+
submodules: true
21+
fetch-depth: 0
22+
23+
- uses: actions/setup-python@v4
24+
with:
25+
python-version: "3.11"
26+
27+
- name: Install pyodide-build
28+
run: pip install pyodide-build==0.23.4
29+
30+
- name: Compute emsdk version
31+
id: compute-emsdk-version
32+
run: |
33+
# Prepare xbuild environment (side-effect)
34+
pyodide config list
35+
# Save EMSDK version
36+
EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
37+
echo "emsdk-version=$EMSCRIPTEN_VERSION" >> $GITHUB_OUTPUT
38+
39+
- uses: mymindstorm/setup-emsdk@v12
40+
with:
41+
version: ${{ steps.compute-emsdk-version.outputs.emsdk-version }}
42+
actions-cache-folder: emsdk-cache
43+
44+
- name: Build
45+
run: PYODIDE_BUILD_EXPORTS=whole_archive CFLAGS=-fexceptions LDFLAGS=-fexceptions pyodide build
46+
working-directory: tests
47+
48+
- uses: actions/setup-node@v3
49+
with:
50+
node-version: 18
51+
52+
- name: Set up Pyodide virtual environment
53+
run: |
54+
pyodide venv .venv-pyodide
55+
.venv-pyodide/bin/pip install $(echo -n tests/dist/*.whl)
56+
57+
- name: Test
58+
run: .venv-pyodide/bin/pytest -o timeout=0 tests/test_*.py

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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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[pyproject]"]
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"]

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_embed/test_interpreter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
import sys
44

5+
import pytest
6+
7+
if sys.platform.startswith("emscripten"):
8+
pytest.skip(
9+
"Test not implemented from single wheel on Pyodide", allow_module_level=True
10+
)
11+
512
from widget_module import Widget
613

714

tests/test_embed/test_trampoline.py

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

3+
import sys
4+
5+
import pytest
6+
7+
if sys.platform.startswith("emscripten"):
8+
pytest.skip(
9+
"Test not implemented from single wheel on Pyodide", allow_module_level=True
10+
)
11+
312
import trampoline_module
413

514

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

0 commit comments

Comments
 (0)