CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
165 lines
4.9 KiB
Python
165 lines
4.9 KiB
Python
"""Public-API surface tests for rocshmem4py.
|
|
|
|
These tests assert that the *public Python API* of ``rocshmem4py`` (built with
|
|
the nanobind backend) is complete and stable: the module name, function names,
|
|
argument behavior, and return types must not change. This is the contract
|
|
consumers depend on, independent of the C++ binding framework.
|
|
|
|
They are torch-free and single-PE safe, so they run in any CI environment.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
import rocshmem4py
|
|
import _rocshmem4py
|
|
|
|
|
|
# Host-facing symbols that must be importable and callable from the compiled
|
|
# extension. Mirrors __init__.py:_HOST_API_BINDINGS.
|
|
_REQUIRED_EXT_CALLABLES = (
|
|
"rocshmem_init",
|
|
"rocshmem_finalize",
|
|
"rocshmem_hipmodule_init",
|
|
"rocshmem_my_pe",
|
|
"rocshmem_n_pes",
|
|
"rocshmem_team_my_pe",
|
|
"rocshmem_team_n_pes",
|
|
"rocshmem_malloc",
|
|
"rocshmem_free",
|
|
"rocshmem_calloc",
|
|
"rocshmem_align",
|
|
"rocshmem_buffer_register",
|
|
"rocshmem_buffer_unregister",
|
|
"rocshmem_buffer_unregister_all",
|
|
"rocshmem_ptr",
|
|
"rocshmem_barrier_all",
|
|
"rocshmem_barrier",
|
|
"rocshmem_barrier_all_on_stream",
|
|
"rocshmem_barrier_on_stream",
|
|
"rocshmem_fence",
|
|
"rocshmem_quiet",
|
|
"rocshmem_get_uniqueid",
|
|
"rocshmem_init_attr",
|
|
"rocshmem_putmem",
|
|
"rocshmem_getmem",
|
|
"rocshmem_putmem_nbi",
|
|
"rocshmem_getmem_nbi",
|
|
"rocshmem_putmem_on_stream",
|
|
"rocshmem_getmem_on_stream",
|
|
"rocshmem_putmem_signal_on_stream",
|
|
"rocshmem_signal_wait_until_on_stream",
|
|
"rocshmem_team_split_strided",
|
|
"rocshmem_team_destroy",
|
|
"rocshmem_team_translate_pe",
|
|
"rocshmem_sync_all",
|
|
"rocshmem_team_sync",
|
|
"rocshmem_sync_all_on_stream",
|
|
"rocshmem_team_sync_on_stream",
|
|
"rocshmem_alltoallmem_on_stream",
|
|
"rocshmem_broadcastmem_on_stream",
|
|
"rocshmem_query_thread",
|
|
"rocshmem_global_exit",
|
|
"rocshmem_dump_stats",
|
|
"rocshmem_reset_stats",
|
|
"rocshmem_get_device_ctx",
|
|
"hip_device_synchronize",
|
|
)
|
|
|
|
_REQUIRED_CONSTANTS = (
|
|
"ROCSHMEM_SUCCESS",
|
|
"ROCSHMEM_SIGNAL_SET",
|
|
"ROCSHMEM_SIGNAL_ADD",
|
|
"ROCSHMEM_CMP_EQ",
|
|
"ROCSHMEM_CMP_NE",
|
|
"ROCSHMEM_CMP_GT",
|
|
"ROCSHMEM_CMP_GE",
|
|
"ROCSHMEM_CMP_LT",
|
|
"ROCSHMEM_CMP_LE",
|
|
)
|
|
|
|
|
|
def test_module_name_is_stable():
|
|
# The compiled extension must keep the same import name so the wheel
|
|
# import path is unchanged.
|
|
assert _rocshmem4py.__name__ == "_rocshmem4py"
|
|
assert rocshmem4py.__version__ is not None
|
|
|
|
|
|
def test_required_callables_present():
|
|
for name in _REQUIRED_EXT_CALLABLES:
|
|
assert hasattr(_rocshmem4py, name), f"_rocshmem4py missing {name}"
|
|
assert callable(getattr(_rocshmem4py, name)), f"{name} not callable"
|
|
|
|
|
|
def test_required_constants_are_ints():
|
|
for name in _REQUIRED_CONSTANTS:
|
|
val = getattr(_rocshmem4py, name)
|
|
assert isinstance(val, int), f"{name} must be int, got {type(val)}"
|
|
|
|
|
|
def test_constant_values():
|
|
assert rocshmem4py.ROCSHMEM_SUCCESS == 0
|
|
assert rocshmem4py.ROCSHMEM_TEAM_WORLD == 0
|
|
assert rocshmem4py.ROCSHMEM_TEAM_INVALID == -1
|
|
assert rocshmem4py.ROCSHMEM_SIGNAL_SET == 0
|
|
assert rocshmem4py.ROCSHMEM_SIGNAL_ADD == 1
|
|
|
|
|
|
def test_pe_queries_return_ints():
|
|
my_pe = rocshmem4py.rocshmem_my_pe()
|
|
n_pes = rocshmem4py.rocshmem_n_pes()
|
|
assert isinstance(my_pe, int) and isinstance(n_pes, int)
|
|
assert 0 <= my_pe < n_pes
|
|
|
|
|
|
def test_pointer_apis_return_ints():
|
|
ptr = rocshmem4py.rocshmem_malloc(1024)
|
|
try:
|
|
assert isinstance(ptr, int) and ptr > 0
|
|
remote = rocshmem4py.rocshmem_ptr(ptr, rocshmem4py.rocshmem_my_pe())
|
|
assert isinstance(remote, int)
|
|
finally:
|
|
rocshmem4py.rocshmem_free(ptr)
|
|
|
|
|
|
def test_uniqueid_returns_bytes():
|
|
# get_uniqueid round-trips a fixed-size binary blob through nb::bytes;
|
|
# the exact length must be preserved.
|
|
uid = rocshmem4py.rocshmem_get_uniqueid()
|
|
assert isinstance(uid, bytes)
|
|
assert len(uid) > 0
|
|
# Stable length across calls (the blob is a fixed-size struct).
|
|
assert len(rocshmem4py.rocshmem_get_uniqueid()) == len(uid)
|
|
|
|
|
|
def test_team_config_attribute_roundtrip():
|
|
cfg = rocshmem4py.TeamConfig()
|
|
cfg.num_contexts = 4
|
|
assert cfg.num_contexts == 4
|
|
cfg.num_contexts = 0
|
|
assert cfg.num_contexts == 0
|
|
|
|
|
|
def test_capsule_buffer_api():
|
|
# SymmetricBuffer exposes the raw device pointer and the
|
|
# __cuda_array_interface__ protocol.
|
|
buf = rocshmem4py.SymmetricBuffer(512)
|
|
try:
|
|
assert isinstance(buf.ptr, int) and buf.ptr > 0
|
|
cai = buf.__cuda_array_interface__
|
|
assert cai["data"] == (buf.ptr, False)
|
|
assert cai["version"] == 3
|
|
finally:
|
|
buf.free()
|
|
|
|
|
|
def test_public_surface_matches_init_all():
|
|
# The high-level package surface (__all__) is independent of the binding
|
|
# framework; verify the documented names are all resolvable.
|
|
for name in rocshmem4py.__all__:
|
|
assert hasattr(rocshmem4py, name), f"rocshmem4py.__all__ lists missing {name}"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|