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
156 lines
5.8 KiB
Python
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)")
|