# ROCm Libraries CTest Integration Architecture This directory contains the shared CTest integration files for organizing and executing tests across ROCm library 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_test_categories.py # Python parser for YAML to CMake conversion ``` **Files:** - [TestCategories.cmake](./TestCategories.cmake) - CMake module with `apply_test_category_labels()` function - [parse_test_categories.py](./parse_test_categories.py) - Python parser for YAML to CMake conversion ## Architecture Overview The CTest integration provides a flexible, maintainable system for organizing tests into categories with support for platform-specific and GPU-specific test exclusions. ### **Core Components** #### 1. **test_categories.yaml** (Project-specific) Located in each project's test directory (e.g., `projects/miopen/test/gtest/test_categories.yaml`). Defines test organization: - Test categories with patterns and labels - Test exclusions - Timeout settings per category #### 2. **parse_test_categories.py** (Shared) Python script that: - Parses YAML configuration files - Detects runtime environment (OS, GPU architecture) - Builds gtest filter strings with positive and negative patterns (default), or emits commands to run an **rtest** driver when **`--use-rtest-driver`** is passed - Generates CMake test registration code with proper exclusion syntax #### 3. **TestCategories.cmake** (Shared) CMake module providing: - `apply_test_category_labels()` function for projects - Python interpreter detection - Error handling and fallback mechanisms ## Execution Flow ```mermaid flowchart TD A[Project CMakeLists.txt] -->|include| B[TestCategories.cmake] A -->|call| C[apply_test_category_labels
target, yaml, workdir] B -->|find_package| D[Python3] C -->|execute_process| E[parse_test_categories.py] E -->|read| F[test_categories.yaml] E -->|detect| G[OS & GPU Architecture] E -->|build| H[Filter Strings
positive-negative] E -->|generate| I[CMake Code] I -->|write to| J[Generated CMake
build/test_categories.cmake] J -->|add_test| K[Test Registration] J -->|set_tests_properties| L[Labels & Timeouts] K --> M[CTest Execution] L --> M M -->|ctest -L category -LE ex_gpu| N[Run without gpu exclusions] M -->|ctest -L category -L ex_gpu_gfx1150| O[Run on Specific GPU with exclusions] style A fill:#e1f5ff,color:#000 style E fill:#fff4e1,color:#000 style J fill:#e8f5e9,color:#000 style M fill:#f3e5f5,color:#000 ``` ## YAML Configuration Format ### **Basic Structure** ```yaml test_categories: category_name: description: "Human-readable description" test_patterns: - "*pattern1*" - "*pattern2*" exclude: - "*pattern_to_exclude*" exclude_windows: - "*linux_only_tests*" exclude_linux: - "*windows_only_tests*" labels: - "quick" - "label2" exclude_gpu: # Common pattern definitions using YAML anchors for reusability common_patterns: &common_patterns - "*pattern1*" - "*pattern2*" - "*pattern3*" exclude_gpu_gfx11X: test_patterns: *common_patterns # Reuse common patterns labels: - "quick" - "standard" - "comprehensive" - "full" - "ex_gpu_gfx11X" exclude_gpu_gfx1150: test_patterns: - "*specific_pattern*" labels: - "quick" - "ex_gpu_gfx1150" execution_settings: default_timeout: 300 timeout_multiplier: 1 # Multiplier for all timeouts (1, 1.5, 1.75, 2, etc.) # environment: { VAR1: "val1", VAR2: "val2" } # optional; applied to all category tests category_timeouts: quick: 300 standard: 1800 ``` **Timeout Configuration:** - `default_timeout`: Base timeout for categories not explicitly listed (in seconds) - `timeout_multiplier`: Global multiplier applied to all timeouts (default: 1) - Use values like `1.5`, `1.75`, `2` to extend timeouts where needed - `category_timeouts`: Timeouts for specific categories (before multiplier is applied) **Environment (optional):** Under `execution_settings`, an `environment` map sets env vars for all category tests (e.g. `OPENBLAS_NUM_THREADS`, `OMP_NUM_THREADS`). Keys and values are strings; they are passed to CTest as `ENVIRONMENT "VAR1=val1;VAR2=val2"`. **Test YAML (optional, per-category):** A category may set `test_yaml` to a basename (e.g. `rocblas_smoke.yaml`). For direct gtest invocations, the parser injects `--yaml ` **before** `--gtest_filter=...`. A category may define `test_yaml` only, `test_patterns` only, or both. When `--use-rtest-driver` is enabled, the project's rtest XML must still define matching `--yaml` / filter behavior for `ctest_` suites. **Extra arguments (optional, per-category):** A category may set `extra_args` to a list (or single string) of additional command-line arguments that the parser appends to the test command after `--gtest_filter=...` (or after `--yaml` when no filter is used). Useful for projects whose test binary accepts runtime flags beyond gtest filtering (for example, a flag to select a reduced subset of tests, or to scale a sampling/iteration parameter). Each entry is shell-quoted with `shlex.quote`, so values with spaces or shell metacharacters are preserved as a single argument by CTest. ```yaml test_categories: quick: test_yaml: rocblas_smoke.yaml test_patterns: - "*quick*" exclude: - "*strided*" extra_args: # appended after --gtest_filter (or after --yaml) - "--quick-subset" labels: - "quick" standard: test_patterns: - "*" exclude: - "*excluded_pattern*" extra_args: # multi-token args are passed verbatim - "--sample-probability" - "0.02" labels: - "standard" ``` `extra_args` flow through identically to category tests and to GPU-exclusion test variants, in both the build-tree CTest definitions and the install-tree `CTestTestfile.cmake`. ### **Enhanced Structure (Optional Fields)** All fields below are **optional** and can be added incrementally. Teams can use them for richer test documentation and enable future capabilities like AI-assisted test selection: ```yaml test_categories: category_name: # Required fields (same as base) description: "Human-readable description" test_patterns: - "*pattern1*" - "*pattern2*" labels: - "label1" - "label2" # Optional enhancement fields - add only if useful for your project notes: | Human-readable context about when to run these tests. Can include historical context, gotchas, or guidance for developers and AI tools. source_coverage: - "library/src/file.cpp" - "library/src/module.cpp:function_name" api_coverage: - "apiFunction1" - "apiFunction2" feature_tags: - "performance-critical" - "numerical-stability" dependencies: - "other_category" # Metadata for related categories (not enforced by parser; for documentation/tooling) # Standard fields (from base) exclude: - "*always_exclude*" exclude_windows: - "*linux_only*" exclude_linux: - "*windows_only*" # Optional: Top-level context for AI/LLM tools llm_context: code_to_test_mapping_guidelines: | Guidance for AI tools on how to map code changes to test categories. Projects can use this for AI-assisted test selection. execution_settings: default_timeout: 300 category_timeouts: category_name: 600 ``` **Optional Field Descriptions:** | Field | Purpose | Example Use | |-------|---------|-------------| | `notes` | Free-form text for context and documentation | "Run when epilogue changes. See bug #8765 for history" | | `source_coverage` | Source files/functions tested by this category | `["library/src/gemm.cpp:matmul_kernel"]` | | `api_coverage` | API functions tested by this category | `["hipblasLtMatmul", "hipblasLtMatmulAlgo"]` | | `feature_tags` | Semantic tags for classification and filtering | `["performance-critical", "mixed-precision"]` | | `dependencies` | Related test categories (documentation only) | `["auxiliary"]` - advisory metadata for downstream tooling | | `llm_context` | Top-level guidance for AI-assisted workflows | Instructions for AI tools on test selection logic | **Key Points:** - All enhancement fields are **optional** - teams can ignore them entirely ✅ - Projects can adopt incrementally: start with just `notes`, add more later ✅ - **Parser does NOT process these fields** - they are for documentation and downstream tooling only ✅ - Parser gracefully ignores unknown fields - no code changes needed ✅ - Enables richer test documentation and future AI-assisted workflows ✅ ### **GPU Exclusion with Hierarchical Matching** GPU-specific exclusions use hierarchical pattern matching with wildcard 'X': **Structure:** - Each `exclude_gpu_gfx*` entry defines patterns to exclude for specific GPU architectures - Patterns can be shared using YAML anchors (`&name`) and aliases (`*name`) - Labels include both category labels and `ex_gpu_*` labels for filtering **Hierarchical Matching:** - Wildcard 'X' matches any remaining characters (e.g., `gfx11X` matches `gfx1100`, `gfx1150`, `gfx1151`) - More specific GPUs inherit exclusions from general patterns: - `gfx1150` matches both `exclude_gpu_gfx11X` and `exclude_gpu_gfx1150` - `gfx1151` matches `exclude_gpu_gfx11X` (inherits from family pattern) **Generated Tests:** - For each GPU exclusion, separate tests are generated per applicable category - Test name format: `{target}-{category}-{gpu_arch}-exclude` - Uses gtest filter syntax: `{positive_patterns}-{category_excludes}:{gpu_exclusion_patterns}` **Usage Examples:** ```bash # On gfx1150 hardware (excludes gfx11X + gfx1150 patterns) ctest -L quick -L ex_gpu_gfx1150 # On gfx950 hardware (excludes only gfx950 patterns) ctest -L standard -L ex_gpu_gfx950 # On generic hardware (exclude all GPU-specific tests) ctest -L quick -LE ex_gpu ``` ### **Category-Level Exclusions** Exclusions are applied using gtest's negative filter syntax (`positive_patterns-negative_patterns`): **How it works:** - All test patterns remain in the category definition - Excluded patterns are added as negative filters after a single `-` separator - Format: `pattern1:pattern2:pattern3-excluded1:excluded2:excluded3` - Gtest runs tests matching positive patterns but excludes those matching negative patterns **Exclusion order:** 1. **Base exclusions** (`exclude`) - Applied to that category 2. **OS-specific exclusions** (`exclude_windows`, `exclude_linux`) - Added based on detected OS at build time 3. **GPU exclusions** (`exclude_gpu`) - Appended for GPU-specific test variants **Example filters:** - **Category test**: `*Fusion*:*Conv*-*DeepBench*:*Slow*` - **GPU exclusion test**: `*Fusion*:*Conv*-*DeepBench*:*Slow*:*gfx942*` This approach maintains all patterns in the YAML configuration while letting gtest handle the filtering at runtime. ### **Implementation Details** The `parse_test_categories.py` script builds filter strings using the following approach: **1. Pattern String Storage** For each category, the script stores: ```python # Read timeout settings base_timeout = timeouts.get(category_name, 300) timeout = int(base_timeout * timeout_multiplier) # Apply global multiplier category_data[category_name] = { "positive_string": "pattern1:pattern2:pattern3", # All test patterns "exclude_string": "neg1:neg2:neg3", # Category + OS exclusions "labels": ["quick", "standard"], "timeout": timeout # Final timeout after multiplier applied } ``` **2. Category Test Generation** ```cmake # Filter format: positive_string-exclude_string add_test( NAME miopen_gtest_standard_suite COMMAND miopen_gtest --gtest_filter="*Fusion*:*Conv*-*DeepBench*:*Slow*" ) ``` **3. GPU Exclusion Test Generation** ```cmake # Filter format: positive_string-exclude_string:gpu_exclude_string add_test( NAME miopen_gtest_standard_gfx1150_suite COMMAND miopen_gtest --gtest_filter="*Fusion*:*Conv*-*DeepBench*:*Slow*:*gfx942*" ) ``` ## Integration Guide This guide walks through integrating the shared YAML-based test categorization into a GTest-based ROCm library project, using MIOpen as the reference implementation. ## Prerequisites - A monolithic GTest binary (single executable containing all tests) - Python 3 which is available in the build environment - The `PyYAML` Python package installed - `ROCM_LIBRARIES_ROOT` set to the repository root in your CMake ## Step 1: Create test_categories.yaml Create a `test_categories.yaml` file in your project's test directory. ### Minimal Example ```yaml test_categories: quick: description: "Fast sanity checks (target: < 5 min)" test_patterns: - "Smoke/*" - "Unit/*" labels: - "quick" - "pre-commit" standard: description: "Core functionality (target: < 30 min)" test_patterns: - "Smoke/*" - "Unit/*" - "*/GPU_Conv*" - "*/GPU_BN*" exclude: - "*SlowTest*" labels: - "standard" - "pr" execution_settings: timeout_multiplier: 1 category_timeouts: quick: 300 standard: 1800 ``` ### Using YAML Anchors to Share Patterns When multiple categories share the same base patterns, use YAML anchors (`&name`) and aliases (`*name`) to avoid duplication: ```yaml # Define once at the top level all_patterns: &all_patterns - "*/GPU_Conv*" - "*/GPU_BN*" - "*/GPU_Reduce*" test_categories: standard: test_patterns: *all_patterns exclude: - "*SlowTest*" labels: - "standard" - "pr" comprehensive: test_patterns: *all_patterns labels: - "comprehensive" - "nightly" ``` ### Adding OS-Specific Exclusions Exclude tests that only work on a specific OS: ```yaml test_categories: standard: test_patterns: - "*TestSuite*" exclude: - "*KnownBroken*" exclude_windows: - "*LinuxOnlyFeature*" exclude_linux: - "*WindowsOnlyFeature*" labels: - "standard" ``` ### Adding GPU-Specific Exclusions Define GPU exclusions with hierarchical matching using a naming convention for `exclude_gpu` keys. In this convention, an `X` suffix in the architecture portion of the key name (for example, `gfx11X`) stands for “all gfx11xx variants”; this is only a key-naming shorthand, not a glob or regex wildcard in `test_patterns`. ```yaml # Shared patterns using YAML anchors gpu_common_patterns: &gpu_common_patterns - "*KnownGPUFailure*" - "*UnsupportedOnGfx11*" exclude_gpu: exclude_gpu_gfx11X: # Applies to all gfx11xx GPUs (gfx1100, gfx1150, gfx1151, etc.) test_patterns: *gpu_common_patterns labels: - "quick" # Must list every category this exclusion applies to - "standard" - "comprehensive" - "full" - "ex_gpu_gfx11X" # Required: ex_gpu_ label for CTest filtering exclude_gpu_gfx1150: # Additional exclusions specific to gfx1150 (on top of gfx11X) test_patterns: - "*Gfx1150SpecificFailure*" labels: - "quick" - "ex_gpu_gfx1150" exclude_gpu_gfx950: test_patterns: - "*Gfx950Issue*" labels: - "quick" - "standard" - "ex_gpu_gfx950" ``` **How hierarchical matching works for the above snippet:** | GPU on machine | Exclusion configs applied | | -------------- | -------------------------------------------- | | gfx1100 | `exclude_gpu_gfx11X` | | gfx1150 | `exclude_gpu_gfx11X` + `exclude_gpu_gfx1150` | | gfx1151 | `exclude_gpu_gfx11X` | | gfx950 | `exclude_gpu_gfx950` | **Important:** The `labels` list in each `exclude_gpu` entry must include every test category that the exclusion applies to. The parser matches these labels against `category_data` keys to determine which categories receive the GPU-specific test variants. ## Step 2: Integrate in CMakeLists.txt ### Enable CTest Ensure `enable_testing()` is called somewhere in your CMake hierarchy before `apply_test_category_labels()`. Without it, `add_test()` calls have no effect and CTest won't discover any tests. This is typically done in the project's test-level `CMakeLists.txt`: ```cmake if(BUILD_TESTING) enable_testing() endif() ``` If your project already calls `enable_testing()` (or uses `include(CTest)`, which calls it internally), no additional change is needed. ### Integration with Install Support For projects that distribute test binaries (for example, via TheRock), generate an install-time CTestTestfile.cmake, so that it can be installed wherever the final test binaries are present. ```cmake set(ROCM_LIBRARIES_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include(${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake) # Create install-time test file set(INSTALL_TEST_FILE "${CMAKE_CURRENT_BINARY_DIR}/install_CTestTestfile.cmake") file(WRITE "${INSTALL_TEST_FILE}" [=[ # Generated test definitions for install-time execution. # Tests use relative paths to the test binary. ]=] ) # Apply categorization (4th argument enables install file generation) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml") apply_test_category_labels( my_project_gtest "${CMAKE_CURRENT_SOURCE_DIR}/test_categories.yaml" "${PROJECT_BINARY_DIR}" "${INSTALL_TEST_FILE}" ) endif() # Install the generated CTestTestfile.cmake alongside the test binary install( FILES "${INSTALL_TEST_FILE}" DESTINATION "${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}" COMPONENT tests RENAME "CTestTestfile.cmake" ) ``` ### Excluding Category Suites from `make check` All YAML-generated tests are named with a `_suite` suffix. If your project has a `check` target that runs `ctest`, the newly generated tests can be excluded to avoid extended run times: ```cmake add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure --verbose -C ${CMAKE_CFG_INTDIR} --exclude-regex ".*_suite" ) ``` ## Step 3: Build and Run Tests ```bash # Build with existing build commands for the project cmake -DBUILD_TESTING=ON .. cmake --build . # List all registered tests ctest -N # Run a specific category (no GPU exclusions) ctest -L quick -LE ex_gpu # Run a specific category with GPU-specific exclusions ctest -L quick -L ex_gpu_gfx1150 # Run with verbose output ctest -L standard -L ex_gpu_gfx950 -V ``` ## Generated Test Names The framework generates tests with predictable naming: | Type | Name Format | Example | | -------------- | -------------------------------------- | -------------------------------------- | | Category suite | `{target}_{category}_suite` | `my_project_gtest_quick_suite` | | GPU exclusion | `{target}_{category}_{gpu_arch}_suite` | `my_project_gtest_quick_gfx1150_suite` | ## Generated Labels Each test gets labels that enable flexible CTest filtering: | Test Type | Labels | | -------------- | ------------------------------------------------------------------- | | Category suite | Category labels from YAML (for example, `quick`, `standard`) | | GPU exclusion | Category labels + `ex_gpu_` (for example, `quick`, `ex_gpu_gfx1150`) | ## Function Reference ### `apply_test_category_labels(target_name yaml_file working_dir [install_test_file [resource_group [parser_extra]]])` | Parameter | Required | Description | | ------------------- | -------- | --------------------------------------------------------------------------------------------------- | | `target_name` | Yes | Name of the GTest executable (must not be empty) | | `yaml_file` | Yes | Absolute path to `test_categories.yaml` (must exist) | | `working_dir` | Yes | Working directory for test execution (must be a valid directory) | | `install_test_file` | No | Path to the generated install-time `CTestTestfile.cmake`. Not required for local builds, but | | | | required for install/package workflows (for example, TheRock). | | `resource_group` | No | CTest `RESOURCE_GROUPS` token; when set, suite names include `_` after the target name. | | `parser_extra` | No | Extra argument(s) forwarded to `parse_test_categories.py` (for example `--use-rtest-driver`). | **Validation:** The function validates all inputs before execution and emits `WARNING` messages if any check fails, returning early without generating tests. ### Optional rtest driver (`--use-rtest-driver`) By default, generated CTest suites run the **gtest executable** with `--gtest_filter=...`. If the project passes **`--use-rtest-driver`** as the optional **`parser_extra`** argument to `apply_test_category_labels()`, the parser instead emits commands to run the **rtest** Python driver next to the binary. The driver basename is derived from the CTest name prefix (typically `mylib-test` → `mylib_rtest.py`). The driver is invoked as ` _rtest.py -t ctest_` using a platform-appropriate interpreter on `PATH` at CTest run time (`python3` on Linux/macOS, `python` on Windows—not configure-time `Python3_EXECUTABLE`, which may be absent on CI test nodes). **`--cmake-python3`** may be passed explicitly to the parser to override the install-tree interpreter. PR-style labels are read at rtest run time from the **`GITHUB_PR_LABELS`** environment variable (semicolon-separated, same format as rtest’s `--ci_labels`) when that variable is set and `--ci_labels` was not passed on the command line. CTest **`LABELS`** on the suite are unchanged (for `ctest -L`). The project’s rtest XML must define matching `` entries. GPU-specific exclusion suites still invoke the gtest binary directly. In **rocm-libraries**, only **rocBLAS** enables this via `USE_RTEST_DRIVER` in `projects/rocblas/clients/gtest/CMakeLists.txt`. ## YAML Reference ### `test_categories` (required) ```yaml test_categories: : description: "..." # Optional: human-readable description test_patterns: # Required: gtest filter patterns (positive match) - "..." exclude: # Optional: patterns to exclude from this category - "..." exclude_windows: # Optional: additional exclusions on Windows - "..." exclude_linux: # Optional: additional exclusions on Linux - "..." labels: # Required: CTest labels for filtering - "..." ``` ### `exclude_gpu` (optional) ```yaml exclude_gpu: exclude_gpu_: test_patterns: # Required: patterns to exclude on this GPU - "..." labels: # Required: must include applicable category names - "" # and an ex_gpu_ label - "ex_gpu_" ``` ### `execution_settings` (optional) ```yaml execution_settings: timeout_multiplier: 1 # Global multiplier for all timeouts (default: 1) category_timeouts: : # Per-category timeout (default: 300) ``` ## Checklist - Created `test_categories.yaml` in your project's test directory - At least one category has `test_patterns` and `labels` defined - `ROCM_LIBRARIES_ROOT` is set correctly (points to the monorepo root) - `include(${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake)` added before calling the function - `apply_test_category_labels()` called with the correct test executable name - GPU exclusion `labels` lists include every applicable category name - Each `exclude_gpu_` entry has an `ex_gpu_` label - `ctest -N` shows the expected test suites after building ## Reference Implementation See the MIOpen integration for a complete working example: - **YAML config:** [projects/miopen/test/gtest/test_categories.yaml](../../projects/miopen/test/gtest/test_categories.yaml) - **CMake integration:** [projects/miopen/test/gtest/CMakeLists.txt](../../projects/miopen/test/gtest/CMakeLists.txt) - **Shared module:** [shared/ctest/TestCategories.cmake](./TestCategories.cmake) - **Parser script:** [shared/ctest/parse_test_categories.py](./parse_test_categories.py) ### **Install-time CTestTestfile (TheRock / install tree)** When tests are installed (e.g. into `/opt/rocm/bin/`), the **build-tree** test definitions are not installed. To run CTest from the **installed** location (e.g. on TheRock or any system that only has the install tree), projects can generate an **install-time CTestTestfile** that uses **relative paths** to the test executable. **How it works:** 1. **Project enables it** by passing an optional **4th argument** to `apply_test_category_labels()`: a path to a file (e.g. `install_CTestTestfile.cmake`) that the parser will create or append to. The parser writes `add_test(...)` and `set_tests_properties(...)` lines into that file using a **relative** command (e.g. `"../my_project_gtest"`), so the test binary is found relative to the directory where the file will live after install. 2. **Project installs that file** to a fixed location under the install prefix, typically a **project-specific subdirectory** of the bin dir (e.g. `bin/my_project/`) and renames it to `CTestTestfile.cmake`. The test executable is installed in the parent `bin/` directory, so from `bin/my_project/` the path `../my_project_gtest` correctly points at the installed binary. 3. **TheRock (or any consumer)** runs CTest **from that installed directory** (e.g. `cd /opt/rocm/bin/my_project && ctest -L quick`). CTest reads the local `CTestTestfile.cmake`, runs the tests with the same labels and timeouts as in the build tree, and no build tree is required. **Example (rocBLAS):** - Build: parser writes tests into `install_CTestTestfile.cmake`; CMake installs it as `CTestTestfile.cmake` to `bin/rocblas/`. - CMake: `ROCBLAS_ENABLE_CTEST` (in `projects/rocblas/cmake/build-options.cmake`) defaults to **ON** when `${ROCM_LIBRARIES_ROOT}/shared/ctest/TestCategories.cmake` exists; if **ON**, a missing YAML or shared module is a **configure error** (set to **OFF** to skip categorization). - Install layout: `bin/rocblas-test` (executable) and `bin/rocblas/CTestTestfile.cmake` (test definitions). - Run from install: `cd /opt/rocm/bin/rocblas && ctest -L quick -N` (list) or `ctest -L quick` (run). Projects that use this pattern (e.g. MIOpen, rocBLAS) document it in their Integration entries below; the same approach applies to any project that needs install-tree CTest runs. ## Integrations - **miopen** - [test_categories.yaml](../../projects/miopen/test/gtest/test_categories.yaml) | [CMakeLists.txt](../../projects/miopen/test/gtest/CMakeLists.txt) - **rocblas** - [test_categories.yaml](../../projects/rocblas/clients/gtest/test_categories.yaml) | [CMakeLists.txt](../../projects/rocblas/clients/gtest/CMakeLists.txt)