Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 141 additions & 14 deletions dnn-providers/cmake/Tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ endfunction()
# - RPATH settings for relocatable test executables
# - Installation rules for test binaries
# - CTest registration
# YAML-driven category labels when DNN_PROVIDER_TEST_CATEGORY_YAMLS is set,
# - YAML-driven category labels when DNN_PROVIDER_CTEST_CATEGORIES_YAML is set,
# otherwise legacy labels such as unit_test/integration_test
#
# APPEND_FUNCTION_SUFFIX - Legacy grouping name retained by add_unit_test_target/add_integration_test_target
Expand Down Expand Up @@ -338,25 +338,18 @@ function(_add_test_target_internal APPEND_FUNCTION_SUFFIX TARGET WORKING_DIR)
endif()
set(_MERGED_TEST_ENVIRONMENT ${TEST_ENVIRONMENT} ${ARG_ENVIRONMENT})

# YAML-driven categorization (apply_test_category_labels(), keyed off
# DNN_PROVIDER_TEST_CATEGORY_YAMLS) generates its own tiered suites after this
# function returns; registering the raw, unfiltered ${TARGET} test here would
# just duplicate the *_full_suite entry with zero labels (never selectable via
# `ctest -L`, always run by a bare `ctest`).
#
# Providers with a pre-registered external CTest-name suite also set
# DNN_PROVIDER_CTEST_CATEGORIES_YAML for apply_ctest_category_labels(), but every
# existing caller (miopen-provider, hipblaslt-provider, hip-kernel-provider) folds
# that same YAML path into DNN_PROVIDER_TEST_CATEGORY_YAMLS too, so checking only
# the latter covers both GTest-filter-only projects (integration-tests) and
# providers with an external CTest-name YAML.
# YAML-driven categorization (currently miopen-provider only) generates
# its own tiered suites via apply_test_category_labels() after this
# function returns; registering the raw, unfiltered ${TARGET} test here
# would just duplicate the *_full_suite entry with zero labels (never
# selectable via `ctest -L`, always run by a bare `ctest`).
#
# Callers cannot set properties on ${TARGET} below since it was never
# registered as a CTest test in this mode -- publish the merged
# environment instead so the caller can forward it explicitly to
# whichever suites apply_test_category_labels()/apply_ctest_category_labels()
# actually creates.
if(DNN_PROVIDER_TEST_CATEGORY_YAMLS)
if(DNN_PROVIDER_CTEST_CATEGORIES_YAML)
set(${TARGET}_TEST_ENVIRONMENT "${_MERGED_TEST_ENVIRONMENT}" PARENT_SCOPE)
return()
endif()
Expand Down Expand Up @@ -422,6 +415,132 @@ function(add_integration_test_target TARGET WORKING_DIR)
endif()
endfunction()

# ~~~
# Adds a tiered test target with Smoke/Standard/Comprehensive/Full ctest entries.
#
# Use this instead of add_unit_test_target() for test binaries that use GTest
# prefix-based tier filtering (INSTANTIATE_TEST_SUITE_P with Smoke/Standard/
# Comprehensive/Full prefixes). Creates four ctest entries with appropriate
# exclusion/inclusion filters, cumulative labels, and per-tier timeouts.
# The smoke-only entry is accumulated for install staging so TheRock CI
# (which runs bare ctest with no -L filter) only executes quick tests.
#
# Usage:
# add_tiered_test_target(TARGET WORKING_DIR
# [SMOKE_TIMEOUT seconds] # default 600
# [STANDARD_TIMEOUT seconds] # default 1800
# [COMPREHENSIVE_TIMEOUT seconds] # default 3600
# [FULL_TIMEOUT seconds]) # default 7200
# ~~~
function(add_tiered_test_target TARGET WORKING_DIR)
cmake_parse_arguments(ARG ""
"SMOKE_TIMEOUT;STANDARD_TIMEOUT;COMPREHENSIVE_TIMEOUT;FULL_TIMEOUT" "" ${ARGN})

# Default timeouts
if(NOT ARG_SMOKE_TIMEOUT)
set(ARG_SMOKE_TIMEOUT 600)
endif()
if(NOT ARG_STANDARD_TIMEOUT)
set(ARG_STANDARD_TIMEOUT 1800)
endif()
if(NOT ARG_COMPREHENSIVE_TIMEOUT)
set(ARG_COMPREHENSIVE_TIMEOUT 3600)
endif()
if(NOT ARG_FULL_TIMEOUT)
set(ARG_FULL_TIMEOUT 7200)
endif()

set(TARGET_EXE "${TARGET}${CMAKE_EXECUTABLE_SUFFIX}")

message(STATUS "Adding tiered test target: ${TARGET} -> ${TARGET_EXE}")

# -- Infra setup (same as _add_test_target_internal, without the unfiltered add_test) --
set(CHECK_DEPENDS_GLOBAL ${CHECK_DEPENDS_GLOBAL} ${TARGET}
CACHE INTERNAL "Accumulated global dependencies for test name validation" FORCE)
set(CHECK_EXECUTABLE_PATHS_GLOBAL ${CHECK_EXECUTABLE_PATHS_GLOBAL}
"${CMAKE_INSTALL_BINDIR}/${TARGET_EXE}"
CACHE INTERNAL "Accumulated global check executable paths" FORCE)

set_target_properties(${TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}"
INSTALL_RPATH
"\$ORIGIN/../${CMAKE_INSTALL_LIBDIR};\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/hipdnn_plugins/engines"
INSTALL_RPATH_USE_LINK_PATH TRUE
BUILD_RPATH_USE_ORIGIN TRUE)
install(TARGETS ${TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

# On Windows, stage the shadowed ROCm DLLs before this test binary is built so a
# partial build + manual ctest doesn't load the stale System32 amd_comgr.dll.
if(TARGET stage_shadowed_rocm_dlls)
add_dependencies(${TARGET} stage_shadowed_rocm_dlls)
endif()

# -- Four ctest entries with cumulative labels --
# Each tier gets a FAIL_REGULAR_EXPRESSION guard. GTest prints "Running 0
# tests from 0 test suites" and exits 0 when no tests match a filter — the
# guard turns that silent pass into a ctest failure so accidentally empty
# tiers are caught early. If a tier is intentionally empty, add a single
# INSTANTIATE_TEST_SUITE_P with a minimal case rather than removing the guard.
set(_no_tests_re "Running 0 tests from 0 test suites")

# Smoke: catch-all exclusion (everything not Standard/Comprehensive/Full).
# The "unit_test" label is intentional — smoke tests are quick enough to
# run in the unit-check target alongside real unit tests.
add_test(NAME ${TARGET}_quick
COMMAND ${TARGET} --gtest_filter=-Standard*:Comprehensive*:Full*
WORKING_DIRECTORY ${WORKING_DIR})
set_tests_properties(${TARGET}_quick PROPERTIES
LABELS "quick;standard;comprehensive;full;unit_test" TIMEOUT ${ARG_SMOKE_TIMEOUT}
FAIL_REGULAR_EXPRESSION "${_no_tests_re}")

add_test(NAME ${TARGET}_standard
COMMAND ${TARGET} --gtest_filter=Standard*
WORKING_DIRECTORY ${WORKING_DIR})
set_tests_properties(${TARGET}_standard PROPERTIES
LABELS "standard;comprehensive;full;slow" TIMEOUT ${ARG_STANDARD_TIMEOUT}
FAIL_REGULAR_EXPRESSION "${_no_tests_re}")

add_test(NAME ${TARGET}_comprehensive
COMMAND ${TARGET} --gtest_filter=Comprehensive*
WORKING_DIRECTORY ${WORKING_DIR})
set_tests_properties(${TARGET}_comprehensive PROPERTIES
LABELS "comprehensive;full;slow" TIMEOUT ${ARG_COMPREHENSIVE_TIMEOUT}
FAIL_REGULAR_EXPRESSION "${_no_tests_re}")

add_test(NAME ${TARGET}_full
COMMAND ${TARGET} --gtest_filter=Full*
WORKING_DIRECTORY ${WORKING_DIR})
set_tests_properties(${TARGET}_full PROPERTIES
LABELS "full;slow" TIMEOUT ${ARG_FULL_TIMEOUT}
FAIL_REGULAR_EXPRESSION "${_no_tests_re}")

if(TEST_ENVIRONMENT)
set_tests_properties(
${TARGET}_quick ${TARGET}_standard ${TARGET}_comprehensive ${TARGET}_full
PROPERTIES ENVIRONMENT "${TEST_ENVIRONMENT}")
endif()
# PATH prepends (Windows ASAN runtime / ROCm / build DLL dirs) via ENVIRONMENT_MODIFICATION so
# the runtime PATH is extended, not replaced.
if(TEST_ENVIRONMENT_MODIFICATION)
set_tests_properties(
${TARGET}_quick ${TARGET}_standard ${TARGET}_comprehensive ${TARGET}_full
PROPERTIES ENVIRONMENT_MODIFICATION "${TEST_ENVIRONMENT_MODIFICATION}")
endif()
# Clear the build-local MIOpen cache before these tests run (ASAN builds only). See the
# hipdnn_clear_miopen_test_cache fixture above.
if(HIPDNN_TEST_MIOPEN_CACHE_DIR)
set_tests_properties(
${TARGET}_quick ${TARGET}_standard ${TARGET}_comprehensive ${TARGET}_full
PROPERTIES FIXTURES_REQUIRED hipdnn_clear_miopen_test_cache)
endif()

# -- Install staging: smoke only --
# Accumulated in a global property so install_integration_tests_ctest_files()
# can emit all tiered entries automatically.
set_property(GLOBAL APPEND_STRING PROPERTY TIERED_TEST_INSTALL_STAGING
"add_test(${TARGET}_quick \"../${TARGET_EXE}\" --gtest_filter=-Standard*:Comprehensive*:Full*)\nset_tests_properties(${TARGET}_quick PROPERTIES LABELS \"quick\" TIMEOUT ${ARG_SMOKE_TIMEOUT})\n")
endfunction() # add_tiered_test_target

# Install CTest configuration files for direct test execution. This should be called once at the end
# of the main CMakeLists.txt after all tests are registered.
#
Expand Down Expand Up @@ -451,6 +570,14 @@ function(install_provider_ctest_files INSTALL_SUBDIR)
file(APPEND "${INSTALLED_CTEST_FILE}" "add_test(${test_target} \"../${test_target}\")\n")
endforeach()

# Append tiered test entries (smoke tier only for CI).
# These are accumulated by add_tiered_test_target() calls.
get_property(_tiered_staging GLOBAL PROPERTY TIERED_TEST_INSTALL_STAGING)
if(_tiered_staging)
file(APPEND "${INSTALLED_CTEST_FILE}" "\n# Tiered test entries (smoke tier only for CI)\n")
file(APPEND "${INSTALLED_CTEST_FILE}" "${_tiered_staging}")
endif()

# Append external integration test entries (cross-provider suite).
# These are accumulated by add_external_integration_test_target() calls
# that pass INSTALL_SUBDIR matching the value passed here.
Expand Down
67 changes: 14 additions & 53 deletions dnn-providers/integration-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,6 @@ clang_tidy_check(${INTEGRATION_TESTS_EXE})
# (see dnn-providers/miopen-provider) which runs this binary against a specific
# engine and selects tests via that provider's test_categories_integration.yaml.

set(HIPDNN_IT_GTEST_CATEGORIES_YAML "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml")
set(HIPDNN_IT_YAML_CATEGORIZATION_ENABLED FALSE)
if(EXISTS "${HIPDNN_IT_GTEST_CATEGORIES_YAML}"
AND EXISTS "${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake")
include("${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake")
set(DNN_PROVIDER_TEST_CATEGORY_YAMLS "${HIPDNN_IT_GTEST_CATEGORIES_YAML}")
set(HIPDNN_IT_YAML_CATEGORIZATION_ENABLED TRUE)
message(STATUS "hipdnn-integration-tests: YAML-based CTest categorization enabled")
else()
message(STATUS "hipdnn-integration-tests: shared/ctest or test_categories.yaml not found, using legacy CTest labels")
endif()

add_subdirectory(gpu-ref)
add_subdirectory(tests)

Expand All @@ -189,47 +177,20 @@ add_subdirectory(tests)
# using add_*_test_target()
finalize_test_targets("${PROJECT_NAME}")

if(HIPDNN_IT_YAML_CATEGORIZATION_ENABLED)
enable_testing()
set(HIPDNN_IT_CTEST_INSTALL_FILE "${CMAKE_CURRENT_BINARY_DIR}/install_CTestTestfile.cmake")
file(WRITE "${HIPDNN_IT_CTEST_INSTALL_FILE}"
"# Autogenerated CTestTestfile for installed hipdnn-integration-tests categories.\n"
"# Tests use relative paths to work in the installed tree.\n")

# The GTest binaries land in CMAKE_BINARY_DIR/bin only once built (RUNTIME_OUTPUT_DIRECTORY,
# Tests.cmake:_add_test_target_internal), but apply_test_category_labels() validates the
# working directory at configure time -- create it up front so a from-scratch configure
# doesn't fail validation before anything has been built.
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")

# No FIXTURES_REQUIRED/hipdnn_clear_miopen_test_cache here: neither
# hipdnn_integration_tests_unit_tests nor hipdnn_gpu_ref_tests link against or
# invoke MIOpen (they exercise the hipDNN backend and the from-scratch GPU
# reference implementation directly), so the ASAN-only MIOpen-cache-clear
# fixture miopen-provider/hipblaslt-provider wire up does not apply here.
foreach(_it_target hipdnn_integration_tests_unit_tests hipdnn_gpu_ref_tests)
apply_test_category_labels(
${_it_target}
"${HIPDNN_IT_GTEST_CATEGORIES_YAML}"
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}"
"${HIPDNN_IT_CTEST_INSTALL_FILE}"
ENVIRONMENT ${TEST_ENVIRONMENT}
ENVIRONMENT_MODIFICATION ${TEST_ENVIRONMENT_MODIFICATION}
)
endforeach()

# Standalone: install the generated (category-labeled) CTestTestfile so
# `ctest -L quick|standard|...` works from the installed tree.
if(NOT ROCM_LIBS_SUPERBUILD)
install(FILES "${HIPDNN_IT_CTEST_INSTALL_FILE}"
DESTINATION "${CMAKE_INSTALL_BINDIR}/hipdnn_integration_tests_ctest"
RENAME "CTestTestfile.cmake")
endif()
else()
# For standalone builds we need to install the ctest files
if(NOT ROCM_LIBS_SUPERBUILD)
install_provider_ctest_files("hipdnn_integration_tests_ctest")
endif()
# Optional YAML-driven CTest categorization. Guarded so standalone / sparse
# checkouts without shared/ctest still build (falls back to unlabeled install).
set(_HIPDNN_IT_TEST_CATEGORIES_YAML "")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml"
AND EXISTS "${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake")
include("${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake")
set(_HIPDNN_IT_TEST_CATEGORIES_YAML "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml")
endif()

# For standalone builds we need to install the ctest files
if(NOT ROCM_LIBS_SUPERBUILD)
install_provider_ctest_files("hipdnn_integration_tests_ctest"
TEST_CATEGORIES_YAML "${_HIPDNN_IT_TEST_CATEGORIES_YAML}"
)
endif()

include(CMakePackageConfigHelpers)
Expand Down
7 changes: 4 additions & 3 deletions dnn-providers/integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,9 @@ tests (via GTest prefixes) and to bundles (via the `{Tier}` path segment).
| Comprehensive | `Comprehensive` | `comprehensive/` | Nightly | 3600s (60 min) |
| Full | `Full` | `full/` | Weekly | 7200s (120 min) |

Timeouts are configured per tier via `category_timeouts` in
[`test_categories.yaml`](test_categories.yaml).
Timeouts can be overridden per binary via `SMOKE_TIMEOUT`, `STANDARD_TIMEOUT`,
`COMPREHENSIVE_TIMEOUT`, and `FULL_TIMEOUT` arguments to
`add_tiered_test_target()`.

### Smoke is a catch-all

Expand Down Expand Up @@ -486,7 +487,7 @@ tests/
Register the test binary in `tests/CMakeLists.txt`:

```cmake
add_integration_test_target(hipdnn_my_new_op_tests ${CMAKE_CURRENT_BINARY_DIR})
add_tiered_test_target(hipdnn_my_new_op_tests ${CMAKE_CURRENT_BINARY_DIR})
```

### Step 2 — Shape catalog
Expand Down
87 changes: 24 additions & 63 deletions dnn-providers/integration-tests/test_categories.yaml
Original file line number Diff line number Diff line change
@@ -1,79 +1,40 @@
# Copyright © Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
#
# hipdnn-integration-tests Test Categories Configuration.
# hipdnn-integration-tests Test Categories Configuration (RFC0010).
#
# GTest-filter categories applied to the component's own GTest binaries
# (hipdnn_integration_tests_unit_tests and hipdnn_gpu_ref_tests) via
# apply_test_category_labels(). Each category becomes one CTest suite whose
# --gtest_filter is built from test_patterns/exclude; labels are cumulative so
# `ctest -L standard` runs quick + standard, etc.
# This component registers its tests as pre-registered CTest entries (via
# add_unit_test_target() / add_tiered_test_target()), not as a single GTest
# binary, so categorization uses apply_ctest_category_labels() over the
# installed CTestTestfile.cmake. `test_patterns` here are matched (as
# regex) against CTest test NAMES, not GTest filters.
#
# Tier prefixes: gpu-ref conv tests use "Smoke", RMSNorm uses "Quick", plus
# "Standard"/"Comprehensive"/"Full"; framework unit tests carry no tier prefix
# and are caught by the quick catch-all (everything not Standard/Comprehensive/
# Full). The external hipdnn_integration_tests bundle binary is categorized by
# each provider's test_categories_integration.yaml, not this file.
# The installed CTestTestfile.cmake (bin/hipdnn_integration_tests_ctest/)
# contains:
# - hipdnn_integration_tests_unit_tests (framework unit tests)
# - hipdnn_gpu_ref_tests_quick (GPU reference smoke tier)
#
# The "comprehensive" and "full" tiers are commented out below: the
# corresponding Comprehensive*/Full* GTest cases require ROCm-side (rock)
# changes that haven't landed yet and would fail without them. Uncomment the
# category blocks, their cascading labels in quick/standard, and their
# category_timeouts entries once those changes land.
# The legacy test_hipdnn_integration_tests.py ran `ctest` with no label
# filter, so every installed test executed in all TEST_TYPEs. The `.*`
# pattern in the quick tier reproduces that: every installed test is
# selected by quick (which inherits standard -> comprehensive -> full).

test_categories:
quick:
description: "Smoke/quick GPU reference cases plus all framework unit tests (catch-all: everything not Standard/Comprehensive/Full)"
description: "Framework unit + GPU reference smoke tests (run in all tiers)"
test_patterns:
- "*"
exclude:
- "*DISABLED*"
- "Standard*"
- "Comprehensive*"
- "Full*"
- ".*"
labels:
- "quick"
- "standard"
# - "comprehensive" # disabled: see header comment
# - "full" # disabled: see header comment

standard:
description: "Standard-tier GPU reference cases"
test_patterns:
- "Standard*"
exclude:
- "*DISABLED*"
labels:
- "standard"
# - "comprehensive" # disabled: see header comment
# - "full" # disabled: see header comment
- "slow"

# comprehensive:
# description: "Comprehensive-tier GPU reference cases"
# test_patterns:
# - "Comprehensive*"
# exclude:
# - "*DISABLED*"
# labels:
# - "comprehensive"
# - "full"
# - "slow"

# full:
# description: "Full-tier GPU reference cases"
# test_patterns:
# - "Full*"
# exclude:
# - "*DISABLED*"
# labels:
# - "full"
# - "slow"
- "comprehensive"
- "full"

execution_settings:
default_timeout: 600
default_timeout: 300
timeout_multiplier: 1
category_timeouts:
quick: 600 # 10 minutes (was add_tiered_test_target SMOKE_TIMEOUT default)
standard: 1800 # 30 minutes
# comprehensive: 3600 # 60 minutes (disabled: see header comment)
# full: 7200 # 120 minutes (disabled: see header comment)
quick: 300 # 5 minutes
standard: 2700 # 45 minutes
comprehensive: 25200 # 7 hours
full: 28800 # 8 hours
Loading
Loading