Skip to content

Commit cc090fc

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

File tree

13 files changed

+125
-7
lines changed

13 files changed

+125
-7
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

include/pybind11/pybind11.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ class cpp_function : public function {
222222

223223
/* Dispatch code which converts function arguments and performs the actual function call */
224224
rec->impl = [](function_call &call) -> handle {
225-
cast_in args_converter;
225+
cast_in args_converter{};
226226

227227
/* Try to cast the function arguments into the C++ domain */
228228
if (!args_converter.load_args(call)) {

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)
@@ -488,6 +493,9 @@ foreach(target ${test_targets})
488493
endforeach()
489494
endif()
490495
endif()
496+
if(SKBUILD)
497+
install(TARGETS ${target} LIBRARY DESTINATION .)
498+
endif()
491499
endforeach()
492500

493501
# 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,8 +1,13 @@
1+
import sys
2+
13
import pytest
24

35
asyncio = pytest.importorskip("asyncio")
46
m = pytest.importorskip("pybind11_tests.async_module")
57

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

712
@pytest.fixture()
813
def event_loop():

tests/test_callbacks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import time
23
from threading import Thread
34

@@ -151,6 +152,7 @@ def test_python_builtins():
151152
assert m.test_sum_builtin(sum, []) == 0
152153

153154

155+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
154156
def test_async_callbacks():
155157
# serves as state for async callback
156158
class Item:
@@ -174,6 +176,7 @@ def gen_f():
174176
assert sum(res) == sum(x + 3 for x in work)
175177

176178

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

tests/test_embed/test_interpreter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import sys
22

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

512

tests/test_embed/test_trampoline.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
import sys
2+
3+
import pytest
4+
5+
if sys.platform.startswith("emscripten"):
6+
pytest.skip(
7+
"Test not implemented from single wheel on Pyodide", allow_module_level=True
8+
)
9+
110
import trampoline_module
211

312

tests/test_exceptions.py

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

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

tests/test_gil_scoped.py

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

7171

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

7778

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

8385

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

8992

93+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
9094
def test_cross_module_gil_nested_pybind11_acquired():
9195
"""Makes sure that the GIL can be nested acquired/acquired by another module
9296
from a GIL-acquired state using pybind11 locking logic."""
@@ -101,6 +105,7 @@ def test_nested_acquire():
101105
assert m.test_nested_acquire(0xAB) == "171"
102106

103107

108+
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
104109
def test_multi_acquire_release_cross_module():
105110
for bits in range(16 * 8):
106111
internals_ids = m.test_multi_acquire_release_cross_module(bits)
@@ -202,7 +207,7 @@ def _run_in_threads(test_fn, num_threads, parallel):
202207
thread.join()
203208

204209

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

214219

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

224229

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

234239

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

0 commit comments

Comments
 (0)