Files
TheRock/rocm-systems/projects/rocshmem/python/tests/test_api_compat.py
T
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

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"])