Files
TheRock/rocm-systems/shared/ctest/README.md
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

9.7 KiB

ROCm Systems CTest Integration Architecture

This directory contains the shared CTest integration files for organizing and executing tests across ROCm system projects using YAML-based test categorization.

Directory Structure

shared/ctest/
├── README.md                      # This file - architecture documentation
├── TestCategories.cmake           # CMake module for test category integration
└── parse_ctest_categories.py      # Python parser for YAML to CMake conversion

Files:

Architecture Overview

The CTest integration provides a label-based system for organizing pre-existing CTest tests into tiered categories. Unlike gtest-filter approaches used in rocm-libraries that create new test targets, this system applies CTest LABELS to tests already registered via add_test(), enabling flexible filtering with ctest -L.

Core Components

1. test_categories.yaml (Project-specific)

Located in each project's test directory (e.g., projects/rocprofiler-compute/tests/test_categories.yaml).

Defines test organization:

  • Test categories with tiered label inheritance
  • Per-category exclusions
  • Custom labels per category
  • Timeout settings

2. parse_ctest_categories.py (Shared)

Python script that:

  • Parses YAML configuration files
  • Applies tiered label inheritance (quick → standard → comprehensive → full)(so that a test added for quick category will be executed for other categories as well)
  • Supports exact test name matching and CMake regex patterns
  • Supports matching tests by existing labels (test_labels)
  • Generates CMake set_property() code to apply labels
  • Deduplicates labels across all tests
  • Optionally appends generated code to an install-time test file

3. TestCategories.cmake (Shared)

CMake module providing:

  • apply_ctest_category_labels() function for projects
  • Python3 interpreter detection
  • Input validation and error handling
  • Optional install_test_file parameter for install-time label support

Execution Flow

flowchart TD
    A[Project CMakeLists.txt] -->|"add_test() calls<br/>define tests"| B[Tests Registered in CTest]
    A -->|include| C[TestCategories.cmake]
    A -->|call| D["apply_ctest_category_labels(yaml)"]

    C -->|find_package| E[Python3]
    D -->|execute_process| F[parse_ctest_categories.py]

    F -->|read| G[test_categories.yaml]
    F -->|apply| H[Tiered Label Inheritance]
    F -->|generate| I["CMake set_property() Code"]

    I -->|"file(WRITE)"| J["build/test_categories.cmake"]
    J -->|include| K["Labels Applied to Existing Tests"]

    B --> K
    K -->|"ctest -L quick"| L[Run Quick Tests]
    K -->|"ctest -L comprehensive"| M[Run Comprehensive Tests]

    style A fill:#e1f5ff,color:#000
    style F fill:#fff4e1,color:#000
    style J fill:#e8f5e9,color:#000
    style K fill:#f3e5f5,color:#000

Tiered Label Inheritance

Categories follow a tiered inheritance model where lower tiers automatically include higher-tier labels:

Category Labels Applied
quick quick, standard, comprehensive, full
standard standard, comprehensive, full
comprehensive comprehensive, full
full full

This means a test in the quick category is also included when running ctest -L standard, ctest -L comprehensive, or ctest -L full. Any custom labels defined in the YAML are appended after the tier labels.

YAML Configuration Format

Basic Structure

test_categories:
  category_name:
    description: "Human-readable description"
    test_patterns:
      - test_exact_name        # Exact CTest test name
      - test_regex.*pattern    # CMake regex pattern (auto-detected)
    test_labels:
      - "existing_label"       # Match tests that already have this label
    exclude:
      - test_to_exclude        # Applied with "{category}_exclude" label
    labels:
      - "custom_label"         # Additional labels beyond tier labels

general_exclude:
  exclude_section_name:
    test_patterns:
      - test_to_exclude
    labels:
      - "exclude_label"

execution_settings:
  default_timeout: 300
  timeout_multiplier: 1
  category_timeouts:
    quick: 300
    standard: 1800
    comprehensive: 7200

Example (rocprofiler-compute)

test_categories:
  quick:
    description: "Fast sanity checks - Run pre-commit (target: < 5 min)"
    test_patterns:
      - test_autogen_config
      - test_roofline_calc_ai_analyze
      - test_utils
      - test_tui_components
    exclude:
      - test_profile_live_attach_detach
    labels:
      - "quick"
      - "pre-commit"
      - "smoke"

  standard:
    description: "Core functionality - Run on every PR (target: < 30 min)"
    test_patterns:
      - test_autogen_config
      - test_utils
      - test_analyze_workloads
      - test_metric_validation
    exclude:
      - test_profile_live_attach_detach
    labels:
      - "standard"
      - "pr"

  comprehensive:
    description: "Extended testing - Run nightly (target: < 2 hours)"
    test_patterns:
      - test_profile_dispatch
      - test_profile_kernel_execution
      - test_profile_roofline_1
      # ... all tests
    exclude:
      - test_profile_live_attach_detach
    labels:
      - "comprehensive"
      - "nightly"

execution_settings:
  default_timeout: 300
  timeout_multiplier: 1
  category_timeouts:
    quick: 300
    standard: 1800
    comprehensive: 7200

Field Reference

Field Required Description
test_patterns Yes List of CTest test names or CMake regex patterns to match
test_labels No List of existing labels to match — tests carrying any of these labels get the category's labels
exclude No Test names/patterns to tag with {category}_exclude label
labels No Custom labels appended after tier-inherited labels
description No Human-readable description (ignored by parser)

Test Matching

The parser supports two matching strategies, auto-detected per pattern:

Exact match — test name contains no regex metacharacters:

test_patterns:
  - test_utils              # Matches the CTest test named exactly "test_utils"

Generated CMake:

foreach(_test test_utils)
    if(TEST ${_test})
        set_property(TEST ${_test} APPEND PROPERTY LABELS "quick;standard;comprehensive;full")
    endif()
endforeach()

Regex match — test name contains regex metacharacters (.*+?^${}()|[]\):

test_patterns:
  - test_profile_.*         # Matches all tests starting with "test_profile_"

Generated CMake:

get_property(_all_tests DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TESTS)
foreach(_test ${_all_tests})
    if(_test MATCHES "^test_profile_.*$")
        set_property(TEST ${_test} APPEND PROPERTY LABELS "quick;standard;comprehensive;full")
    endif()
endforeach()

Label-Based Matching (test_labels)

In addition to matching by test name, categories can match tests by their existing labels:

test_categories:
  quick:
    test_labels:
      - "unit"              # All tests already labeled "unit" get quick-tier labels
    test_patterns:
      - test_extra_quick

This is useful when tests are already labeled in CMakeLists.txt via set_tests_properties() and you want to include them in a category without listing each name.

General Excludes

The general_exclude section applies labels directly to test patterns without tier inheritance:

general_exclude:
  exclude_flaky:
    test_patterns:
      - test_intermittent_failure
    labels:
      - "flaky"
      - "exclude_flaky"

This can be used with ctest -LE exclude_flaky to skip these tests.

Integration Guide

Step 1: Create test_categories.yaml

Create test_categories.yaml in your project's test directory:

projects/myproject/tests/test_categories.yaml

Step 2: Include in CMakeLists.txt

In your project's CMakeLists.txt, after all add_test() calls:

# Set path to the YAML file
set(_test_categories_yaml "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_categories.yaml")

# Include the shared CTest module
include(${ROCM_SYSTEMS_ROOT}/shared/ctest/TestCategories.cmake)

# Apply category labels to existing tests
if(EXISTS "${_test_categories_yaml}")
    message(STATUS "YAML-based test categorization")
    apply_ctest_category_labels("${_test_categories_yaml}")
else()
    message(STATUS "No test categorization (YAML missing)")
endif()

Important: apply_ctest_category_labels() must be called after all add_test() calls, since it uses if(TEST ...) and get_property(... PROPERTY TESTS) to find existing tests.

Step 3: Build and Test

# Configure
cmake -B build ..

# Run quick sanity checks
ctest --test-dir build -L quick

# Run standard PR tests
ctest --test-dir build -L standard

# Run comprehensive nightly tests
ctest --test-dir build -L comprehensive

# Exclude specific tests
ctest --test-dir build -L quick -LE quick_exclude

# List all tests with their labels
ctest --test-dir build -N --show-only=json-v1

# Verbose output
ctest --test-dir build -L quick -V

Optional: Install-Time Test File

apply_ctest_category_labels() accepts an optional second argument to append the generated label code to a file for install-time use:

apply_ctest_category_labels(
    "${_test_categories_yaml}"
    "${CMAKE_CURRENT_BINARY_DIR}/install_test_labels.cmake"  # appended to this file
)

Integrations