Files
TheRock/rocm-systems/projects/rccl/test/ir-device/tests/test_ir_device.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

156 lines
5.8 KiB
Python

# *************************************************************************
# * Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved.
# *
# * See LICENSE.txt for license information
# ************************************************************************
"""Functional tests for librccl_device.bc, driven through the GoogleTest
binaries built from bindings/ir/test/IR_test.cpp (single process) and
bindings/ir/test/IR_gin_mpi_test.cpp (multi-rank, under mpirun).
Each pytest case runs a binary restricted to a single --gtest_filter so
failures map cleanly to the underlying device API. Outcomes are mapped by
`_summarize_gtest` so the pytest result mirrors what GoogleTest actually did:
* any failure / non-zero exit -> pytest FAILED
* at least one real pass -> pytest PASSED
* clean run where every case SKIPPED -> pytest SKIPPED (with the reason)
That last rule matters for the GIN/composite cases: when the host lacks the
hardware/runtime to actually exercise a barrier (e.g. <2 GPUs, or no cuMem /
symmetric-memory support), GoogleTest SKIPs and exits 0 — without this mapping
those would misleadingly show as PASSED.
"""
import re
import pytest
def _summarize_gtest(proc, log, what):
"""Translate a GoogleTest binary run into a pytest outcome.
Reads the captured log so we can tell a genuine pass from a run in which
every selected case was SKIPPED (both exit 0).
"""
try:
with open(log) as fh:
text = fh.read()
except OSError:
text = ""
if proc.returncode != 0 or "[ FAILED ]" in text:
raise AssertionError(f"{what} failed, see {log}")
def _count(pattern):
m = re.search(pattern, text)
return int(m.group(1)) if m else 0
passed = _count(r"\[ PASSED \] (\d+) test")
skipped = _count(r"\[ SKIPPED \] (\d+) test")
# Nothing passed but something skipped -> surface a real pytest SKIP with
# the GoogleTest skip reason (the line printed right after ": Skipped").
if passed == 0 and skipped > 0:
m = re.search(r": Skipped\s*\n([^\[]+)", text)
reason = " ".join(m.group(1).split()) if m else "all cases skipped"
pytest.skip(f"{what}: {reason} (see {log})")
@pytest.mark.ir_device
@pytest.mark.peer_pointer
def test_get_peer_pointer_team(run_gtest):
"""[A] ncclGetPeerPointerTeam — 20 pointer-arithmetic cases."""
proc, log = run_gtest("IRDeviceTest.A_GetPeerPointerTeam",
"ir_peer_pointer.log")
_summarize_gtest(proc, log, "ncclGetPeerPointerTeam")
@pytest.mark.ir_device
@pytest.mark.coop
def test_coop_init_and_accessors(run_gtest):
"""[B1-B5] ncclCoopAnyInit* + ncclCoopSize/ThreadRank/NumThreads."""
proc, log = run_gtest(
"IRDeviceTest.B1_*:IRDeviceTest.B2_*:IRDeviceTest.B3*:"
"IRDeviceTest.B4*:IRDeviceTest.B5_*",
"ir_coop_init.log",
)
_summarize_gtest(proc, log, "ncclCoopAny init/accessors")
@pytest.mark.ir_device
@pytest.mark.coop
def test_coop_sync(run_gtest):
"""[B6] ncclCoopSync — all five coop types complete."""
proc, log = run_gtest("IRDeviceTest.B6_CoopSync", "ir_coop_sync.log")
_summarize_gtest(proc, log, "ncclCoopSync")
@pytest.mark.ir_device
@pytest.mark.lsa_barrier
def test_lsa_barrier_session(run_gtest):
"""[B7] ncclLsaBarrierSession structural check (+ runtime cases skipped)."""
proc, log = run_gtest("IRDeviceTest.B7*", "ir_lsa_barrier.log")
_summarize_gtest(proc, log, "ncclLsaBarrierSession")
@pytest.mark.ir_device
@pytest.mark.gin_barrier
@pytest.mark.composite_barrier
def test_bucket_c_symbols_linkable(run_gtest):
"""[C0] All four bucket-C thunks resolve/export from librccl_device.bc.
Takes the device address of ncclGinBarrierSession{Init,Sync} and
ncclBarrierSession{Init,Sync}; a missing/renamed/internalized export
fails the device link or yields a null address. No live resources needed.
"""
proc, log = run_gtest("IRDeviceTest.C0_BucketCSymbolsLinkable",
"ir_bucket_c_symbols.log")
_summarize_gtest(proc, log, "bucket C symbol link coverage")
@pytest.mark.ir_device
@pytest.mark.gin_barrier
def test_gin_barrier_session(run_gtest):
"""[C1] ncclGinBarrierSession structural check (+ runtime case skipped)."""
proc, log = run_gtest("IRDeviceTest.C1*", "ir_gin_barrier.log")
_summarize_gtest(proc, log, "ncclGinBarrierSession")
@pytest.mark.ir_device
@pytest.mark.composite_barrier
def test_composite_barrier_session(run_gtest):
"""[C2] composite ncclBarrierSession structural check (+ runtime skipped)."""
proc, log = run_gtest("IRDeviceTest.C2*", "ir_composite_barrier.log")
_summarize_gtest(proc, log, "ncclBarrierSession")
@pytest.mark.ir_device
@pytest.mark.gin_barrier
@pytest.mark.mpi
def test_gin_barrier_session_functional_mpi(run_gin_mpi_gtest):
"""[C1 functional] ncclGinBarrierSession{Init,Sync} over a live 2-rank GIN
rail barrier, under `mpirun -np 2`.
Reports SKIPPED (not PASSED) when the host can't actually run it — e.g.
fewer than 2 GPUs, or no cuMem/symmetric-memory support.
"""
proc, log = run_gin_mpi_gtest(
"IRGinBarrierMPITest.C1_GinBarrierSession_TwoRanks",
"ir_gin_barrier_mpi.log",
)
_summarize_gtest(proc, log, "GIN barrier functional (2-rank)")
@pytest.mark.ir_device
@pytest.mark.composite_barrier
@pytest.mark.mpi
def test_composite_barrier_session_functional_mpi(run_gin_mpi_gtest):
"""[C2 functional] composite ncclBarrierSession{Init,Sync} (inner LSA +
outer GIN) over a live 2-rank comm. Same skip semantics as the GIN case.
"""
proc, log = run_gin_mpi_gtest(
"IRGinBarrierMPITest.C2_CompositeBarrierSession_TwoRanks",
"ir_composite_barrier_mpi.log",
)
_summarize_gtest(proc, log, "composite barrier functional (2-rank)")