From 3f1ec274653d35c489ef9226368101839c108848 Mon Sep 17 00:00:00 2001 From: Andrey Kasaurov Date: Tue, 25 Nov 2025 02:15:36 -0500 Subject: [PATCH 1/2] Add infrastructure for HIP catch tests; add unit/compiler tests --- External/HIP/CATCH_TESTS_README.md | 634 + External/HIP/CMakeLists.txt | 21 +- External/HIP/HipCatchTests.cmake | 490 + External/HIP/catch/external/Catch2/catch.hpp | 17358 ++++++++++++++++ .../HIP/catch/external/picojson/picojson.h | 1141 + .../HIP/catch/hipTestMain/hip_test_context.cc | 362 + .../catch/hipTestMain/hip_test_features.cc | 159 + External/HIP/catch/hipTestMain/main.cc | 77 + External/HIP/catch/include/cmd_options.hh | 41 + External/HIP/catch/include/hip_test_common.hh | 726 + .../HIP/catch/include/hip_test_context.hh | 197 + .../HIP/catch/include/hip_test_features.hh | 40 + .../HIP/catch/include/hip_test_filesystem.hh | 89 + .../HIP/catch/unit/compiler/hipClassKernel.cc | 172 + .../HIP/catch/unit/compiler/hipClassKernel.h | 220 + External/HIP/catch/unit/compiler/hipSquare.cc | 86 + .../unit/compiler/hipSquareGenericTarget.cc | 120 + 17 files changed, 21931 insertions(+), 2 deletions(-) create mode 100644 External/HIP/CATCH_TESTS_README.md create mode 100644 External/HIP/HipCatchTests.cmake create mode 100644 External/HIP/catch/external/Catch2/catch.hpp create mode 100644 External/HIP/catch/external/picojson/picojson.h create mode 100644 External/HIP/catch/hipTestMain/hip_test_context.cc create mode 100644 External/HIP/catch/hipTestMain/hip_test_features.cc create mode 100644 External/HIP/catch/hipTestMain/main.cc create mode 100644 External/HIP/catch/include/cmd_options.hh create mode 100644 External/HIP/catch/include/hip_test_common.hh create mode 100644 External/HIP/catch/include/hip_test_context.hh create mode 100644 External/HIP/catch/include/hip_test_features.hh create mode 100644 External/HIP/catch/include/hip_test_filesystem.hh create mode 100644 External/HIP/catch/unit/compiler/hipClassKernel.cc create mode 100644 External/HIP/catch/unit/compiler/hipClassKernel.h create mode 100644 External/HIP/catch/unit/compiler/hipSquare.cc create mode 100644 External/HIP/catch/unit/compiler/hipSquareGenericTarget.cc diff --git a/External/HIP/CATCH_TESTS_README.md b/External/HIP/CATCH_TESTS_README.md new file mode 100644 index 0000000000..a1bff09b7e --- /dev/null +++ b/External/HIP/CATCH_TESTS_README.md @@ -0,0 +1,634 @@ +# HIP Catch Tests Integration + +This document describes the self-contained Catch-based test framework for HIP functionality in the LLVM Test Suite. + +## Overview + +The HIP Catch Tests framework provides comprehensive HIP tests using the Catch2 testing framework. The tests are **fully self-contained** within the LLVM Test Suite - no external dependencies are required. The framework includes: + +- **Unit tests**: Core HIP API functionality (memory, streams, events, kernels, compiler features, etc.) +- Support for multiple ROCm versions (per-variant testing) +- Hierarchical test organization (category and subdirectory levels) +- Integration with LLVM's LIT test runner + +Currently included test categories: +- `unit/compiler`: Tests for HIP compiler features (kernels, device code compilation) + +## Requirements + +1. **ROCm installation**: A valid ROCm installation with HIP support + +2. **LLVM Test Suite**: This repository contains all necessary Catch test infrastructure in `External/HIP/catch/` + +3. **clang++**: ROCm's clang++ compiler for building HIP code + +## Quick Start + +### Basic Configuration + +Configure the test suite with Catch tests enabled: + +```bash +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=/path/to/rocm/installation \ + -DTEST_SUITE_EXTERNALS_DIR=/path/to/externals \ + -DAMDGPU_ARCHS=gfx90a \ + -DENABLE_HIP_CATCH_TESTS=ON \ + -DCATCH_TEST_CATEGORIES="unit" \ + -DCMAKE_CXX_COMPILER=/path/to/clang++ \ + -DCMAKE_C_COMPILER=/path/to/clang \ + /path/to/llvm-test-suite +``` + +**Note**: Catch tests are **enabled by default** (`ENABLE_HIP_CATCH_TESTS=ON`) and self-contained in `External/HIP/catch/` - no external dependencies needed. Set `ENABLE_HIP_CATCH_TESTS=OFF` to disable all Catch test targets. + +### Platform Support + +The Catch tests are **platform-agnostic** and support both AMD and NVIDIA GPUs through HIP: + +#### AMD ROCm Backend (Default) + +Use AMD's clang++ compiler directly: + +```bash +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=/opt/rocm \ + -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \ + -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang \ + -DAMDGPU_ARCHS=gfx90a \ + /path/to/llvm-test-suite +``` + +#### NVIDIA CUDA Backend + +Use HIP's `hipcc` wrapper (built with CUDA backend): + +```bash +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=/path/to/hip-cuda \ + -DCMAKE_CXX_COMPILER=/path/to/hip-cuda/bin/hipcc \ + -DCMAKE_C_COMPILER=/path/to/hip-cuda/bin/hipcc \ + -DCUDA_ARCH=sm_75 \ + /path/to/llvm-test-suite +``` + +**Note**: The `hipcc` wrapper automatically handles platform-specific compile and link flags. The same test source code works on both platforms without modification! + +### Build Targets + +After configuration, hierarchical targets are available at three levels: **top-level** (all catch tests), **category-level** (e.g., unit tests), and **subdirectory-level** (e.g., unit/compiler tests). Each level has both **aggregated** (all ROCm variants) and **per-variant** targets. + +#### Top-Level Targets + +Build or run **all** Catch tests across all categories: + +| Target | Description | +|--------|-------------| +| `ninja hip-tests-catch` | Build all Catch tests, all variants | +| `ninja hip-tests-catch-hip-7.2.0` | Build all Catch tests for specific variant | +| `ninja check-hip-catch` | Run all Catch tests, all variants | +| `ninja check-hip-catch-hip-7.2.0` | Run all Catch tests for specific variant | + +#### Category-Level Targets + +Build or run tests for a specific **category** (e.g., `unit`, `stress`): + +| Target | Description | +|--------|-------------| +| `ninja hip-tests-catch-unit` | Build all unit tests, all variants | +| `ninja hip-tests-catch-unit-hip-7.2.0` | Build all unit tests for specific variant | +| `ninja check-hip-catch-unit` | Run all unit tests, all variants | +| `ninja check-hip-catch-unit-hip-7.2.0` | Run all unit tests for specific variant | + +#### Subdirectory-Level Targets + +Build or run tests for a specific **subdirectory** within a category (e.g., `unit/compiler`): + +| Target | Description | +|--------|-------------| +| `ninja hip-tests-catch-unit-compiler` | Build unit/compiler tests, all variants | +| `ninja hip-tests-catch-unit-compiler-hip-7.2.0` | Build unit/compiler tests for specific variant | +| `ninja check-hip-catch-unit-compiler` | Run unit/compiler tests, all variants | +| `ninja check-hip-catch-unit-compiler-hip-7.2.0` | Run unit/compiler tests for specific variant | + +#### Other Targets + +| Target | Description | +|--------|-------------| +| `ninja hip-tests-all` | Build all HIP tests (including Catch tests if enabled) | + +## Configuration Options + +### ENABLE_HIP_CATCH_TESTS + +**Type**: Boolean +**Default**: ON +**Description**: Master switch to enable or disable the entire HIP Catch test framework. When disabled, no Catch test targets are created, and the build only includes simple HIP tests. + +**When ENABLED (default)**: +- All Catch test targets are created (top-level, category-level, subdirectory-level, per-variant) +- Examples: `hip-tests-catch`, `hip-tests-catch-unit`, `hip-tests-catch-unit-compiler` +- `hip-tests-all` includes both simple and catch tests + +**When DISABLED**: +- No Catch test targets are created +- Only simple HIP tests are available +- `hip-tests-all` includes only simple tests +- Faster CMake configuration (no Catch test infrastructure processed) + +Examples: +```bash +# Enable Catch tests (default) +-DENABLE_HIP_CATCH_TESTS=ON + +# Disable Catch tests (only simple tests) +-DENABLE_HIP_CATCH_TESTS=OFF +``` + +**Use cases for disabling**: +- Quick builds when you only need simple HIP tests +- CI environments that don't require comprehensive testing +- Debugging simple test failures without the overhead of Catch tests +- Systems with limited resources where minimal test coverage is acceptable + +### CATCH_TEST_CATEGORIES + +**Type**: Semicolon-separated list +**Default**: "unit" +**Description**: Test categories to include in the build + +Available categories: +- `unit`: Unit tests for core HIP APIs (currently: compiler tests) + +Example: +```bash +# Include unit tests (default and currently only available category) +-DCATCH_TEST_CATEGORIES="unit" +``` + +### CATCH_TEST_SUBDIRS + +**Type**: Semicolon-separated list +**Default**: "" (empty - includes all subdirectories) +**Description**: Specific subdirectories to include within enabled categories. When empty, all subdirectories are automatically discovered and included. + +This option provides fine-grained control over which tests to build. For example, within the `unit` category, you can selectively include only `compiler`, `memory`, and `stream` tests while excluding others. + +Examples: +```bash +# Include only compiler tests from enabled categories +-DCATCH_TEST_SUBDIRS="compiler" + +# Include multiple specific subdirectories +-DCATCH_TEST_SUBDIRS="compiler;memory;stream;kernel" + +# Include all subdirectories (default behavior) +-DCATCH_TEST_SUBDIRS="" +# or simply omit the option +``` + +**Note**: The subdirectory filter applies to all enabled categories. For example, if you set `-DCATCH_TEST_CATEGORIES="unit;stress"` and `-DCATCH_TEST_SUBDIRS="compiler"`, the framework will include: +- `catch/unit/compiler` (if it exists) +- `catch/stress/compiler` (if it exists) + +Available subdirectories in the `unit` category include: +- `compiler` - Compiler-specific tests +- `memory` - Memory management tests +- `stream` - Stream management tests +- `event` - Event handling tests +- `kernel` - Kernel execution tests +- `device` - Device management tests +- `math` - Math operations tests +- And 40+ more subdirectories... + +### HIP_CATCH_TEST_TIMEOUT + +**Type**: Integer (seconds) +**Default**: 60 +**Description**: Timeout for individual Catch tests + +```bash +-DHIP_CATCH_TEST_TIMEOUT=120 +``` + +## Example Configurations + +### Example 1: Basic Unit Tests Only + +```bash +#!/bin/bash + +export CLANG_DIR=/opt/rocm-7.2.0/llvm +export ROCM_PATH=/opt/rocm-7.2.0 +export AMDGPU_ARCHS=gfx90a + +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=${ROCM_PATH} \ + -DTEST_SUITE_EXTERNALS_DIR=${ROCM_PATH} \ + -DAMDGPU_ARCHS=${AMDGPU_ARCHS} \ + -DCMAKE_CXX_COMPILER="${CLANG_DIR}/bin/clang++" \ + -DCMAKE_C_COMPILER="${CLANG_DIR}/bin/clang" \ + -DCATCH_TEST_CATEGORIES="unit" \ + /path/to/llvm-test-suite +``` + +### Example 2: Selective Subdirectory Testing + +Build only specific subdirectories (e.g., compiler tests): + +```bash +#!/bin/bash + +export CLANG_DIR=/opt/rocm-7.2.0/llvm +export ROCM_PATH=/opt/rocm-7.2.0 +export AMDGPU_ARCHS=gfx90a + +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=${ROCM_PATH} \ + -DTEST_SUITE_EXTERNALS_DIR=${ROCM_PATH} \ + -DAMDGPU_ARCHS=${AMDGPU_ARCHS} \ + -DCMAKE_CXX_COMPILER="${CLANG_DIR}/bin/clang++" \ + -DCMAKE_C_COMPILER="${CLANG_DIR}/bin/clang" \ + -DCATCH_TEST_CATEGORIES="unit" \ + -DCATCH_TEST_SUBDIRS="compiler" \ + /path/to/llvm-test-suite + +# Build compiler tests +ninja hip-tests-catch-unit-compiler + +# Run compiler tests +ninja check-hip-catch-unit-compiler +``` + +### Example 3: Comprehensive Testing + +```bash +#!/bin/bash + +export CLANG_DIR=/opt/rocm-7.2.0/llvm +export EXTERNAL_DIR=/opt/rocm-7.2.0 +export AMDGPU_ARCHS=gfx90a +export TEST_SUITE_DIR=/path/to/llvm-test-suite + +cd /path/to/build-llvm-test-suite + +PATH=${CLANG_DIR}/bin:$PATH \ +CXX=clang++ \ +CC=clang \ +cmake -G Ninja \ + -DTEST_SUITE_EXTERNALS_DIR=${EXTERNAL_DIR} \ + -DTEST_SUITE_HIP_ROOT=${EXTERNAL_DIR} \ + -DAMDGPU_ARCHS=${AMDGPU_ARCHS} \ + -DCMAKE_CXX_COMPILER="${CLANG_DIR}/bin/clang++" \ + -DCMAKE_C_COMPILER="${CLANG_DIR}/bin/clang" \ + -DCATCH_TEST_CATEGORIES="unit" \ + ${TEST_SUITE_DIR} + +# Build all tests +ninja hip-tests-all + +# Run simple tests +ninja check-hip-simple + +# Run Catch tests at different levels +ninja check-hip-catch # All catch tests +ninja check-hip-catch-unit # All unit tests +ninja check-hip-catch-unit-compiler # Only unit/compiler tests +``` + +### Example 4: Simple Tests Only (Catch Tests Disabled) + +For quick builds or when you only need simple HIP tests: + +```bash +#!/bin/bash + +export CLANG_DIR=/opt/rocm-7.2.0/llvm +export ROCM_PATH=/opt/rocm-7.2.0 +export AMDGPU_ARCHS=gfx90a + +cmake -G Ninja \ + -DTEST_SUITE_HIP_ROOT=${ROCM_PATH} \ + -DTEST_SUITE_EXTERNALS_DIR=${ROCM_PATH} \ + -DAMDGPU_ARCHS=${AMDGPU_ARCHS} \ + -DCMAKE_CXX_COMPILER="${CLANG_DIR}/bin/clang++" \ + -DCMAKE_C_COMPILER="${CLANG_DIR}/bin/clang" \ + -DENABLE_HIP_CATCH_TESTS=OFF \ + /path/to/llvm-test-suite + +# With Catch tests disabled, only simple test targets available +ninja hip-tests-all # Build all simple tests +ninja check-hip-simple # Run all simple tests +ninja hip-tests-simple-hip-7.2.0 # Build simple tests for specific variant +ninja check-hip-simple-hip-7.2.0 # Run simple tests for specific variant + +# Catch test targets are NOT created (will error if you try to use them) +# ninja hip-tests-catch # ERROR: target not found +# ninja check-hip-catch-unit # ERROR: target not found +``` + +## Target Hierarchy + +The framework creates a three-level hierarchical structure for organizing and running tests (when `ENABLE_HIP_CATCH_TESTS=ON`, which is the default): + +**Note**: When `ENABLE_HIP_CATCH_TESTS=OFF`, NO Catch test targets are created at all. Only simple HIP test targets are available. + +### Hierarchy Levels + +``` +Level 1: Top-Level (ALL catch tests) +├── hip-tests-catch (all categories, all variants) +├── hip-tests-catch-hip-7.2.0 (all categories, one variant) +│ +Level 2: Category (e.g., unit tests) +├── hip-tests-catch-unit (all unit subdirs, all variants) +├── hip-tests-catch-unit-hip-7.2.0 (all unit subdirs, one variant) +│ +Level 3: Subdirectory (e.g., unit/compiler tests) +├── hip-tests-catch-unit-compiler (compiler tests, all variants) +└── hip-tests-catch-unit-compiler-hip-7.2.0 (compiler tests, one variant) +``` + +### Benefits of Hierarchical Targets + +1. **Flexibility**: Build/run at any granularity level +2. **Efficiency**: Test only what you need during development +3. **Multi-Variant Support**: Test across multiple ROCm versions or focus on one +4. **Incremental Testing**: Quick feedback by testing changed components + +### Example Workflows + +**Scenario 1: Compiler developer working on code generation** +```bash +# Quick iteration: test only compiler tests for one ROCm version +ninja hip-tests-catch-unit-compiler-hip-7.2.0 +ninja check-hip-catch-unit-compiler-hip-7.2.0 +``` + +**Scenario 2: Testing a change across all ROCm versions** +```bash +# Build compiler tests for all installed ROCm versions +ninja hip-tests-catch-unit-compiler +ninja check-hip-catch-unit-compiler +``` + +**Scenario 3: Pre-commit validation** +```bash +# Run all unit tests across all variants +ninja check-hip-catch-unit +``` + +**Scenario 4: Nightly CI testing** +```bash +# Run everything +ninja check-hip-catch +``` + +## Test Organization + +The framework organizes tests by: + +1. **ROCm Version**: Each ROCm installation gets its own test variant + - Example: `hip-7.2.0`, `hip-6.2.0` + +2. **Category**: Tests are grouped by category + - `unit`: Core API functionality + - `stress`: High-load scenarios + - `performance`: Benchmarking + - `perftests`: Detailed metrics + +3. **Subdirectory**: Each subdirectory within a category + - `unit/compiler`, `unit/memory`, `unit/stream`, etc. + +4. **Test Executable**: Each subdirectory produces a test executable + - Example: `catch_unit_compiler-hip-7.2.0` + +## Building Tests at Different Levels + +### Build by Category + +```bash +# Configure to include only unit tests +cmake -DCATCH_TEST_CATEGORIES="unit" ... + +# Build all unit tests (all variants) +ninja hip-tests-catch-unit + +# Build all unit tests for specific variant +ninja hip-tests-catch-unit-hip-7.2.0 +``` + +### Build by Subdirectory + +```bash +# Configure to include specific subdirectories +cmake -DCATCH_TEST_SUBDIRS="compiler;memory" ... + +# Build unit/compiler tests (all variants) +ninja hip-tests-catch-unit-compiler + +# Build unit/compiler tests for specific variant +ninja hip-tests-catch-unit-compiler-hip-7.2.0 +``` + +### Build Everything + +```bash +# Build all catch tests (all categories, all variants) +ninja hip-tests-catch + +# Build all catch tests for specific variant +ninja hip-tests-catch-hip-7.2.0 +``` + +## Running Tests at Different Levels + +### Run All Catch Tests + +```bash +# Run all catch tests (all categories, all variants) +ninja check-hip-catch + +# Run all catch tests for specific variant +ninja check-hip-catch-hip-7.2.0 +``` + +### Run Category-Level Tests + +```bash +# Run all unit tests (all variants) +ninja check-hip-catch-unit + +# Run all unit tests for specific variant +ninja check-hip-catch-unit-hip-7.2.0 +``` + +### Run Subdirectory-Level Tests + +```bash +# Run unit/compiler tests (all variants) +ninja check-hip-catch-unit-compiler + +# Run unit/compiler tests for specific variant +ninja check-hip-catch-unit-compiler-hip-7.2.0 +``` + +### Run Individual Test Executable + +```bash +# Run a specific test executable directly +./External/HIP/catch_tests/catch_unit_compiler-hip-7.2.0 +``` + +### Using LIT + +The tests are integrated with the LIT test runner: + +```bash +# Run all HIP tests +lit External/HIP + +# Run only Catch tests (filter by name pattern) +lit -a External/HIP | grep catch_ +``` + +## Troubleshooting + +### Catch2 Not Found + +**Error**: `Catch2 not found in expected location` + +**Solution**: Ensure the hip-tests repository has the Catch2 submodule initialized: +```bash +cd /path/to/hip-tests +git submodule update --init --recursive +``` + +### hip-tests Repository Not Found + +**Error**: `Could not find hip-tests repository` + +**Solution**: Either: +1. Set `-DHIP_CATCH_TESTS_REPO=/path/to/hip-tests` +2. Place hip-tests in one of the auto-detected locations + +### No Test Sources Found + +**Error**: `No test sources found in category/subdir` + +**Solution**: The CMakeLists.txt parser may have failed. This can happen if: +- The test category doesn't exist in your hip-tests version +- The CMakeLists.txt format is not recognized + +Check available test categories: +```bash +ls /path/to/hip-tests/catch/ +``` + +### Compilation Errors + +**Common issues**: + +1. **Missing includes**: Ensure ROCm headers are accessible +2. **Architecture mismatch**: Verify `AMDGPU_ARCHS` matches your GPU +3. **ROCm version mismatch**: Ensure HIP runtime matches compiler version + +## Architecture + +The framework consists of: + +1. **HipCatchTests.cmake**: Main CMake module with functions for: + - Repository discovery and validation + - Test category discovery + - CMakeLists.txt parsing + - Test executable creation + - LIT integration + +2. **Modified CMakeLists.txt**: Integration points in the main HIP test CMakeLists.txt: + - Initialization in `create_hip_tests()` + - Per-variant integration in `create_hip_test()` + - Target dependencies in `hip-tests-all` + +3. **Test Wrappers**: Shell scripts for LIT integration + +## Extending the Framework + +### Adding Custom Test Categories + +To add support for additional test categories: + +1. Add the category to `CATCH_TEST_CATEGORIES`: + ```bash + -DCATCH_TEST_CATEGORIES="unit;stress;mycategory" + ``` + +2. The framework will automatically discover subdirectories in: + ``` + llvm-test-suite/External/HIP/catch/mycategory/ + ``` + +## Performance Considerations + +- **Build Time**: Catch tests can significantly increase build time. Use specific categories to reduce build scope. +- **Disk Space**: Each test variant creates separate executables. +- **Parallelism**: Use ninja's `-j` flag to parallelize builds: + ```bash + ninja -j16 hip-tests-catch + ``` + +## Contributing + +To contribute improvements to the framework: + +1. Test changes with multiple ROCm versions +2. Verify tests build and run correctly +3. Update this documentation +4. Submit changes to the LLVM Test Suite + +## Future Enhancements + +Potential improvements: +- [ ] Add more test categories (stress, performance, etc.) +- [ ] Add more unit test subdirectories (memory, streams, etc.) +- [ ] Test selection by regex pattern +- [ ] Integration with CTest +- [ ] Test result aggregation and reporting +- [ ] Enhanced test filtering options + +## Directory Structure + +The Catch test infrastructure is self-contained in `External/HIP/catch/`: + +``` +External/HIP/catch/ +├── unit/ # Unit test category +│ └── compiler/ # Compiler test subdirectory +│ ├── hipClassKernel.cc +│ ├── hipClassKernel.h +│ ├── hipSquare.cc +│ └── hipSquareGenericTarget.cc +├── include/ # Common test headers +│ ├── hip_test_common.hh +│ ├── hip_test_context.hh +│ ├── hip_test_features.hh +│ ├── hip_test_filesystem.hh +│ └── cmd_options.hh +├── hipTestMain/ # Test framework main files +│ ├── main.cc +│ ├── hip_test_context.cc +│ └── hip_test_features.cc +└── external/ # Third-party libraries + ├── Catch2/ + │ └── catch.hpp # Catch2 test framework (required) + └── picojson/ + └── picojson.h # JSON parser (required) +``` + +**Note**: The `kernels/` directory is not needed for `unit/compiler` tests. These tests define kernels inline using `__global__` functions. + +## References + +- [hip-tests Repository](https://github.com/ROCm/hip-tests) (original source of tests) +- [ROCm Documentation](https://rocm.docs.amd.com/) +- [LLVM Test Suite](https://llvm.org/docs/TestSuiteGuide.html) +- [Catch2 Framework](https://github.com/catchorg/Catch2) diff --git a/External/HIP/CMakeLists.txt b/External/HIP/CMakeLists.txt index 37d1cf6c24..dabb71da28 100644 --- a/External/HIP/CMakeLists.txt +++ b/External/HIP/CMakeLists.txt @@ -7,6 +7,9 @@ message(STATUS "TEST_SUITE_HIP_ROOT: ${TEST_SUITE_HIP_ROOT}") get_filename_component(HIP_CLANG_PATH ${CMAKE_CXX_COMPILER} DIRECTORY) message(STATUS "HIP_CLANG_PATH: ${HIP_CLANG_PATH}") +# Include Catch tests integration module +include(${CMAKE_CURRENT_LIST_DIR}/HipCatchTests.cmake) + # Inspired from create_one_local_test. Runs hipify on the TestSource and then compiles it. # Search for the reference files next to TestSource. macro(create_one_hipify_cuda_test TestName TestSource VairantOffload VariantSuffix VariantCPPFlags VariantLibs) @@ -151,6 +154,11 @@ function(create_hip_test VariantSuffix) DEPENDS hip-tests-simple-${VariantSuffix} USES_TERMINAL) add_dependencies(check-hip-simple check-hip-simple-${VariantSuffix}) + + # Integrate Catch tests for this variant (if enabled) + if(ENABLE_HIP_CATCH_TESTS) + integrate_catch_tests(${VariantSuffix} ${_RocmPath}) + endif() endfunction(create_hip_test) macro(create_hip_tests) @@ -176,6 +184,9 @@ macro(create_hip_tests) add_custom_target(check-hip-simple COMMENT "Run all simple HIP tests") + # Initialize Catch tests framework + initialize_catch_tests() + if(NOT AMDGPU_ARCHS) list(APPEND AMDGPU_ARCHS "gfx906;gfx90a;gfx1030;gfx1100;native") endif() @@ -260,8 +271,14 @@ macro(create_hip_tests) endif() - add_custom_target(hip-tests-all DEPENDS hip-tests-simple - COMMENT "Build all HIP tests.") + # Build all HIP tests (simple + catch if enabled) + if(ENABLE_HIP_CATCH_TESTS) + add_custom_target(hip-tests-all DEPENDS hip-tests-simple hip-tests-catch + COMMENT "Build all HIP tests (simple + catch).") + else() + add_custom_target(hip-tests-all DEPENDS hip-tests-simple + COMMENT "Build all HIP tests (simple only, catch disabled).") + endif() file(COPY lit.local.cfg DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") endmacro(create_hip_tests) diff --git a/External/HIP/HipCatchTests.cmake b/External/HIP/HipCatchTests.cmake new file mode 100644 index 0000000000..959ddc81a1 --- /dev/null +++ b/External/HIP/HipCatchTests.cmake @@ -0,0 +1,490 @@ +# CMake module for integrating hip-tests Catch tests into llvm-test-suite +# This module provides functions to discover and build Catch-based HIP tests + +include(CMakeParseArguments) + +# Global variables for Catch test configuration +set(ENABLE_HIP_CATCH_TESTS ON CACHE BOOL "Enable HIP Catch test framework and all catch test targets") +set(CATCH_TEST_CATEGORIES "unit" CACHE STRING "Semicolon-separated list of test categories to include (unit;stress;performance;perftests)") +set(CATCH_TEST_SUBDIRS "" CACHE STRING "Semicolon-separated list of test subdirectories to include (e.g., compiler;memory;stream). Empty means all subdirectories within enabled categories.") +set(HIP_CATCH_TEST_TIMEOUT 60 CACHE STRING "Timeout for individual Catch tests in seconds") + +# Local paths for Catch test infrastructure (now self-contained) +set(HIP_CATCH_TESTS_DIR "${CMAKE_CURRENT_LIST_DIR}/catch") +set(CATCH2_INCLUDE_PATH "${HIP_CATCH_TESTS_DIR}/external/Catch2") +set(CATCH2_FOUND TRUE) + +# Global tracking for hierarchical targets +# These will be set as GLOBAL properties to track across function calls +define_property(GLOBAL PROPERTY CATCH_ALL_VARIANTS + BRIEF_DOCS "List of all discovered HIP variants" + FULL_DOCS "Tracks all variant suffixes (e.g., hip-7.2.0) discovered during configuration") + +define_property(GLOBAL PROPERTY CATCH_CATEGORY_TARGETS_CREATED + BRIEF_DOCS "List of categories for which aggregated targets have been created" + FULL_DOCS "Prevents duplicate target creation for category-level aggregated targets") + +define_property(GLOBAL PROPERTY CATCH_SUBDIR_TARGETS_CREATED + BRIEF_DOCS "List of category-subdir pairs for which aggregated targets have been created" + FULL_DOCS "Prevents duplicate target creation for subdirectory-level aggregated targets") + +# Function to validate Catch test infrastructure +function(validate_catch_tests_infrastructure) + set(_required_paths + "${HIP_CATCH_TESTS_DIR}/unit/compiler" + "${HIP_CATCH_TESTS_DIR}/external/Catch2/catch.hpp" + "${HIP_CATCH_TESTS_DIR}/external/picojson/picojson.h" + "${HIP_CATCH_TESTS_DIR}/hipTestMain" + "${HIP_CATCH_TESTS_DIR}/include" + ) + # Note: kernels/ directory not required for unit/compiler tests + + foreach(_path ${_required_paths}) + if(NOT EXISTS "${_path}") + message(FATAL_ERROR "Required Catch test path not found: ${_path}") + endif() + endforeach() + + message(STATUS "Using local Catch test infrastructure: ${HIP_CATCH_TESTS_DIR}") + message(STATUS "Catch2 found at: ${CATCH2_INCLUDE_PATH}") +endfunction() + +# Function to discover test sources from hip-tests +# Arguments: +# CATEGORY - Test category (unit, stress, performance, perftests) +# SUBDIRS - Specific subdirectories to include (optional, default: all) +# Returns: +# Sets ${CATEGORY}_TEST_DIRS in parent scope +function(discover_catch_test_category CATEGORY) + set(options) + set(oneValueArgs) + set(multiValueArgs SUBDIRS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(_catch_base "${HIP_CATCH_TESTS_DIR}/${CATEGORY}") + + if(NOT IS_DIRECTORY "${_catch_base}") + message(STATUS "Category ${CATEGORY} not found in Catch tests, skipping") + return() + endif() + + # If specific subdirectories requested via argument, use them; + # otherwise check CATCH_TEST_SUBDIRS cache variable; + # otherwise discover all + if(ARG_SUBDIRS) + set(_test_subdirs ${ARG_SUBDIRS}) + elseif(CATCH_TEST_SUBDIRS) + # Use subdirectories from CATCH_TEST_SUBDIRS, filtering to only those that exist + set(_test_subdirs "") + foreach(_subdir ${CATCH_TEST_SUBDIRS}) + if(IS_DIRECTORY "${_catch_base}/${_subdir}") + list(APPEND _test_subdirs "${_subdir}") + message(STATUS "Including subdirectory from CATCH_TEST_SUBDIRS: ${CATEGORY}/${_subdir}") + else() + message(STATUS "Subdirectory ${CATEGORY}/${_subdir} not found, skipping") + endif() + endforeach() + else() + # Discover all subdirectories automatically. + file(GLOB _potential_subdirs RELATIVE "${_catch_base}" "${_catch_base}/*") + set(_test_subdirs "") + foreach(_subdir ${_potential_subdirs}) + if(IS_DIRECTORY "${_catch_base}/${_subdir}") + # Check if directory has any .cc test files + file(GLOB _test_files "${_catch_base}/${_subdir}/*.cc") + if(_test_files) + list(APPEND _test_subdirs "${_subdir}") + endif() + endif() + endforeach() + endif() + + if(_test_subdirs) + message(STATUS "Discovered ${CATEGORY} test subdirectories: ${_test_subdirs}") + else() + message(STATUS "No test subdirectories found for ${CATEGORY} category") + endif() + set(${CATEGORY}_TEST_DIRS "${_test_subdirs}" PARENT_SCOPE) +endfunction() + +# Helper function to track test targets at multiple levels +# Arguments: +# TEST_TARGET - The test target name (e.g., catch_unit_compiler-hip-7.2.0.test) +# CATEGORY - Category name (e.g., unit) +# SUBDIR - Subdirectory name (e.g., compiler) +# VARIANT - Variant suffix (e.g., hip-7.2.0) +function(track_test_target_multi_level TEST_TARGET CATEGORY SUBDIR VARIANT) + # Track at global level (all catch tests) + set_property(GLOBAL APPEND PROPERTY CATCH_ALL_TEST_TARGETS "${TEST_TARGET}") + + # Track at per-variant global level + set_property(GLOBAL APPEND PROPERTY "CATCH_TEST_TARGETS_${VARIANT}" "${TEST_TARGET}") + + # Track at per-category level (all variants) + set_property(GLOBAL APPEND PROPERTY "CATCH_${CATEGORY}_TEST_TARGETS" "${TEST_TARGET}") + + # Track at per-category-variant level + set_property(GLOBAL APPEND PROPERTY "CATCH_${CATEGORY}_TEST_TARGETS_${VARIANT}" "${TEST_TARGET}") + + # Track at per-subdirectory level (all variants) + set_property(GLOBAL APPEND PROPERTY "CATCH_${CATEGORY}_${SUBDIR}_TEST_TARGETS" "${TEST_TARGET}") + + # Track at per-subdirectory-variant level + set_property(GLOBAL APPEND PROPERTY "CATCH_${CATEGORY}_${SUBDIR}_TEST_TARGETS_${VARIANT}" "${TEST_TARGET}") +endfunction() + +# Function to create a Catch test executable +# Arguments: +# TEST_NAME - Name of the test +# TEST_SOURCES - List of source files +# TEST_DIR - Directory containing the test sources +# CATEGORY - Test category (unit, stress, etc.) +# SUBDIR - Subdirectory name +# VARIANT_SUFFIX - Variant suffix (e.g., hip-7.2.0) +# ROCM_PATH - Path to ROCm installation +macro(create_catch_test_executable TEST_NAME TEST_SOURCES TEST_DIR CATEGORY SUBDIR VARIANT_SUFFIX ROCM_PATH) + set(_test_exe "${TEST_NAME}-${VARIANT_SUFFIX}") + set(_test_sources "") + + # Build full paths to source files + foreach(_src ${TEST_SOURCES}) + list(APPEND _test_sources "${TEST_DIR}/${_src}") + endforeach() + + # Add hipTestMain sources (required for catch2 integration) + list(APPEND _test_sources + "${HIP_CATCH_TESTS_DIR}/hipTestMain/main.cc" + "${HIP_CATCH_TESTS_DIR}/hipTestMain/hip_test_context.cc" + "${HIP_CATCH_TESTS_DIR}/hipTestMain/hip_test_features.cc" + ) + + # Check if sources exist + set(_valid_sources "") + foreach(_src ${_test_sources}) + if(EXISTS "${_src}") + list(APPEND _valid_sources "${_src}") + else() + message(STATUS "Source file not found: ${_src}") + endif() + endforeach() + + if(NOT _valid_sources) + message(STATUS "No valid sources found for ${TEST_NAME}, skipping") + return() + endif() + + # Create the executable + add_executable(${_test_exe} EXCLUDE_FROM_ALL ${_valid_sources}) + + # Ensure timeit tool is built first (needed for compilation timing) + if(TARGET build-timeit) + add_dependencies(${_test_exe} build-timeit) + endif() + + # Set properties + set_target_properties(${_test_exe} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/catch_tests" + ) + + # Include directories + target_include_directories(${_test_exe} PRIVATE + ${CATCH2_INCLUDE_PATH} + "${HIP_CATCH_TESTS_DIR}/include" + "${HIP_CATCH_TESTS_DIR}/external/picojson" + ) + + # Add HIP runtime includes + # hipcc wrapper provides these automatically, direct compilers need explicit paths + if(NOT _compiler_name MATCHES "hipcc") + target_include_directories(${_test_exe} PRIVATE + "${ROCM_PATH}/include" + ) + endif() + + # Compile definitions + # Note: __HIP_PLATFORM_AMD__ or __HIP_PLATFORM_NVIDIA__ is automatically + # defined by HIP headers based on the compiler backend, so no manual + # platform definition is needed + # target_compile_definitions(${_test_exe} PRIVATE ...) + + # Compile options + target_compile_options(${_test_exe} PRIVATE + ${VariantCPPFLAGS} + -x hip + -Wall + -Wno-deprecated + -Wno-unused-command-line-argument + ) + + # Link options - platform-specific handling + # If using hipcc wrapper (AMD or NVIDIA backend), it handles flags automatically + # Otherwise, add explicit flags for AMD clang + get_filename_component(_compiler_name "${CMAKE_CXX_COMPILER}" NAME) + if(_compiler_name MATCHES "hipcc") + # hipcc wrapper handles platform-specific flags automatically + message(VERBOSE "Using hipcc wrapper: ${CMAKE_CXX_COMPILER}") + else() + # Direct compiler (AMD clang) - add explicit HIP link flags + target_link_options(${_test_exe} PRIVATE + --rocm-path=${ROCM_PATH} + --hip-link + -rtlib=compiler-rt + -unwindlib=libgcc + -frtlib-add-rpath + ) + endif() + + # Link libraries + target_link_libraries(${_test_exe} PRIVATE + ${VariantLibs} + stdc++fs + dl + pthread + rt + ) + + # Add to subdirectory variant target (lowest level) + add_dependencies(hip-tests-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} ${_test_exe}) + + # Create a test wrapper script + set(_test_wrapper "${CMAKE_CURRENT_BINARY_DIR}/catch_tests/${_test_exe}_wrapper.sh") + file(WRITE "${_test_wrapper}" "#!/bin/bash\n") + file(APPEND "${_test_wrapper}" "exec \"${CMAKE_CURRENT_BINARY_DIR}/catch_tests/${_test_exe}\" \"$@\"\n") + execute_process(COMMAND chmod +x "${_test_wrapper}") + + # Register with LIT + llvm_test_run(EXECUTABLE "/bin/bash" "${_test_exe}_wrapper.sh") + llvm_add_test(${_test_exe}.test ${_test_exe}_wrapper.sh) + + # Track this test target at all hierarchy levels + track_test_target_multi_level(${_test_exe}.test ${CATEGORY} ${SUBDIR} ${VARIANT_SUFFIX}) + + # Also add to VARIANT_CATCH_TEST_TARGETS for backward compatibility + list(APPEND VARIANT_CATCH_TEST_TARGETS ${_test_exe}.test) + set(VARIANT_CATCH_TEST_TARGETS ${VARIANT_CATCH_TEST_TARGETS} PARENT_SCOPE) + + message(STATUS "Created Catch test executable: ${_test_exe}") +endmacro() + +# Function to create Catch tests for a specific category and subdirectory +# Arguments: +# CATEGORY - Test category (unit, stress, performance) +# SUBDIR - Subdirectory name +# VARIANT_SUFFIX - Variant suffix (e.g., hip-7.2.0) +# ROCM_PATH - Path to ROCm installation +function(create_catch_tests_for_subdir CATEGORY SUBDIR VARIANT_SUFFIX ROCM_PATH) + set(_test_dir "${HIP_CATCH_TESTS_DIR}/${CATEGORY}/${SUBDIR}") + + # Create unique identifier for this category-subdir pair + set(_subdir_id "${CATEGORY}-${SUBDIR}") + + # Create aggregated subdirectory-level targets (once per category-subdir pair) + get_property(_created_subdirs GLOBAL PROPERTY CATCH_SUBDIR_TARGETS_CREATED) + if(NOT "${_subdir_id}" IN_LIST _created_subdirs) + message(STATUS "Creating aggregated subdirectory targets for: ${CATEGORY}/${SUBDIR}") + + # Create aggregated build target + add_custom_target(hip-tests-catch-${CATEGORY}-${SUBDIR} + COMMENT "Build all HIP Catch ${CATEGORY}/${SUBDIR} tests across all variants") + add_dependencies(hip-tests-catch-${CATEGORY} hip-tests-catch-${CATEGORY}-${SUBDIR}) + + # Create aggregated check target (will be populated later) + add_custom_target(check-hip-catch-${CATEGORY}-${SUBDIR} + COMMENT "Run all HIP Catch ${CATEGORY}/${SUBDIR} tests across all variants") + add_dependencies(check-hip-catch-${CATEGORY} check-hip-catch-${CATEGORY}-${SUBDIR}) + + # Mark as created + set_property(GLOBAL APPEND PROPERTY CATCH_SUBDIR_TARGETS_CREATED "${_subdir_id}") + endif() + + # Create per-variant subdirectory-level targets + message(STATUS "Creating per-variant subdirectory targets for: ${CATEGORY}/${SUBDIR}-${VARIANT_SUFFIX}") + add_custom_target(hip-tests-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} + COMMENT "Build HIP Catch ${CATEGORY}/${SUBDIR} tests for variant ${VARIANT_SUFFIX}") + + # Wire dependencies: variant-specific target to aggregated subdirectory target + add_dependencies(hip-tests-catch-${CATEGORY}-${SUBDIR} hip-tests-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX}) + + # Wire dependencies: category variant target depends on subdirectory variant target + add_dependencies(hip-tests-catch-${CATEGORY}-${VARIANT_SUFFIX} hip-tests-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX}) + + # Discover test sources directly from .cc files + file(GLOB _test_sources RELATIVE "${_test_dir}" "${_test_dir}/*.cc") + + if(NOT _test_sources) + message(STATUS "No test sources found in ${CATEGORY}/${SUBDIR}, skipping") + return() + endif() + + message(STATUS "Discovered test sources in ${CATEGORY}/${SUBDIR}: ${_test_sources}") + + # Create test name from category and subdir + set(_test_name "catch_${CATEGORY}_${SUBDIR}") + + message(STATUS "Creating Catch test: ${_test_name} with ${CMAKE_CURRENT_LIST_LENGTH} sources") + + # Create the test executable + create_catch_test_executable("${_test_name}" "${_test_sources}" "${_test_dir}" "${CATEGORY}" "${SUBDIR}" "${VARIANT_SUFFIX}" "${ROCM_PATH}") + + # Create per-variant check target for this subdirectory + # Get test targets for this subdirectory-variant combination + get_property(_subdir_variant_tests GLOBAL PROPERTY "CATCH_${CATEGORY}_${SUBDIR}_TEST_TARGETS_${VARIANT_SUFFIX}") + + if(_subdir_variant_tests) + add_custom_target(check-hip-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} + COMMAND ${TEST_SUITE_LIT} ${TEST_SUITE_LIT_FLAGS} ${_subdir_variant_tests} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS hip-tests-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} + USES_TERMINAL + COMMENT "Run HIP Catch ${CATEGORY}/${SUBDIR} tests for variant ${VARIANT_SUFFIX}") + # Ensure litsupport files (including lit.cfg) and timeit-target are available + if(TARGET build-litsupport) + add_dependencies(check-hip-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} build-litsupport) + endif() + if(TARGET timeit-target) + add_dependencies(check-hip-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX} timeit-target) + endif() + + # Wire to aggregated check target (will run tests from all variants) + add_dependencies(check-hip-catch-${CATEGORY}-${SUBDIR} check-hip-catch-${CATEGORY}-${SUBDIR}-${VARIANT_SUFFIX}) + endif() +endfunction() + +# Main function to integrate Catch tests for a specific HIP variant +# Arguments: +# VARIANT_SUFFIX - Variant suffix (e.g., hip-7.2.0) +# ROCM_PATH - Path to ROCm installation +function(integrate_catch_tests VARIANT_SUFFIX ROCM_PATH) + message(STATUS "Integrating Catch tests for variant ${VARIANT_SUFFIX}") + + # Register this variant globally + get_property(_variants GLOBAL PROPERTY CATCH_ALL_VARIANTS) + if(NOT "${VARIANT_SUFFIX}" IN_LIST _variants) + set_property(GLOBAL APPEND PROPERTY CATCH_ALL_VARIANTS "${VARIANT_SUFFIX}") + endif() + + # Create catch test target for this variant + add_custom_target(hip-tests-catch-${VARIANT_SUFFIX} + COMMENT "Build Catch tests for HIP variant ${VARIANT_SUFFIX}") + + # Process each enabled category + foreach(_category ${CATCH_TEST_CATEGORIES}) + message(STATUS "Processing Catch test category: ${_category}") + + # Create aggregated category-level targets (once per category) + get_property(_created_categories GLOBAL PROPERTY CATCH_CATEGORY_TARGETS_CREATED) + if(NOT "${_category}" IN_LIST _created_categories) + message(STATUS "Creating aggregated category targets for: ${_category}") + + # Create aggregated build target + add_custom_target(hip-tests-catch-${_category} + COMMENT "Build all HIP Catch ${_category} tests across all variants") + add_dependencies(hip-tests-catch hip-tests-catch-${_category}) + + # Create aggregated check target (will be populated later) + add_custom_target(check-hip-catch-${_category} + COMMENT "Run all HIP Catch ${_category} tests across all variants") + add_dependencies(check-hip-catch check-hip-catch-${_category}) + + # Mark as created + set_property(GLOBAL APPEND PROPERTY CATCH_CATEGORY_TARGETS_CREATED "${_category}") + endif() + + # Create per-variant category-level targets + message(STATUS "Creating per-variant category targets for: ${_category}-${VARIANT_SUFFIX}") + add_custom_target(hip-tests-catch-${_category}-${VARIANT_SUFFIX} + COMMENT "Build HIP Catch ${_category} tests for variant ${VARIANT_SUFFIX}") + + # Wire dependencies: variant-specific target to aggregated category target + add_dependencies(hip-tests-catch-${_category} hip-tests-catch-${_category}-${VARIANT_SUFFIX}) + + # Wire dependencies: top-level variant target depends on category variant target + add_dependencies(hip-tests-catch-${VARIANT_SUFFIX} hip-tests-catch-${_category}-${VARIANT_SUFFIX}) + + # Discover test subdirectories + discover_catch_test_category(${_category}) + + # Get the discovered subdirectories + set(_subdir_var "${_category}_TEST_DIRS") + if(DEFINED ${_subdir_var}) + foreach(_subdir ${${_subdir_var}}) + create_catch_tests_for_subdir("${_category}" "${_subdir}" "${VARIANT_SUFFIX}" "${ROCM_PATH}") + endforeach() + endif() + endforeach() + + # Create per-variant check targets for each category + foreach(_category ${CATCH_TEST_CATEGORIES}) + # Get test targets for this category-variant combination + get_property(_category_variant_tests GLOBAL PROPERTY "CATCH_${_category}_TEST_TARGETS_${VARIANT_SUFFIX}") + + if(_category_variant_tests) + add_custom_target(check-hip-catch-${_category}-${VARIANT_SUFFIX} + COMMAND ${TEST_SUITE_LIT} ${TEST_SUITE_LIT_FLAGS} ${_category_variant_tests} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS hip-tests-catch-${_category}-${VARIANT_SUFFIX} + USES_TERMINAL + COMMENT "Run HIP Catch ${_category} tests for variant ${VARIANT_SUFFIX}") + # Ensure litsupport files (including lit.cfg) and timeit-target are available + if(TARGET build-litsupport) + add_dependencies(check-hip-catch-${_category}-${VARIANT_SUFFIX} build-litsupport) + endif() + if(TARGET timeit-target) + add_dependencies(check-hip-catch-${_category}-${VARIANT_SUFFIX} timeit-target) + endif() + + # Wire to aggregated check target (will run tests from all variants) + add_dependencies(check-hip-catch-${_category} check-hip-catch-${_category}-${VARIANT_SUFFIX}) + endif() + endforeach() + + # Add variant target to main catch target + add_dependencies(hip-tests-catch hip-tests-catch-${VARIANT_SUFFIX}) + + # Create check target + add_custom_target(check-hip-catch-${VARIANT_SUFFIX} + COMMAND ${TEST_SUITE_LIT} ${TEST_SUITE_LIT_FLAGS} + ${VARIANT_CATCH_TEST_TARGETS} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS hip-tests-catch-${VARIANT_SUFFIX} + USES_TERMINAL) + # Ensure litsupport files (including lit.cfg) and timeit-target are available + if(TARGET build-litsupport) + add_dependencies(check-hip-catch-${VARIANT_SUFFIX} build-litsupport) + endif() + if(TARGET timeit-target) + add_dependencies(check-hip-catch-${VARIANT_SUFFIX} timeit-target) + endif() + + add_dependencies(check-hip-catch check-hip-catch-${VARIANT_SUFFIX}) + + message(STATUS "Integrated ${CMAKE_CURRENT_LIST_LENGTH} Catch test targets for ${VARIANT_SUFFIX}") +endfunction() + +# Initialize the Catch test framework integration +macro(initialize_catch_tests) + if(ENABLE_HIP_CATCH_TESTS) + message(STATUS "=== Initializing HIP Catch Tests Integration ===") + + # Validate local Catch test infrastructure + validate_catch_tests_infrastructure() + + # Create main targets + add_custom_target(hip-tests-catch + COMMENT "Build all HIP Catch tests") + add_custom_target(check-hip-catch + COMMENT "Run all HIP Catch tests") + + message(STATUS "Catch test categories enabled: ${CATCH_TEST_CATEGORIES}") + if(CATCH_TEST_SUBDIRS) + message(STATUS "Catch test subdirectories filter: ${CATCH_TEST_SUBDIRS}") + else() + message(STATUS "Catch test subdirectories filter: ALL (no filter)") + endif() + message(STATUS "=== Catch Tests Integration Initialized ===") + else() + message(STATUS "HIP Catch tests are DISABLED (set ENABLE_HIP_CATCH_TESTS=ON to enable)") + endif() +endmacro() diff --git a/External/HIP/catch/external/Catch2/catch.hpp b/External/HIP/catch/external/Catch2/catch.hpp new file mode 100644 index 0000000000..ab39621b9a --- /dev/null +++ b/External/HIP/catch/external/Catch2/catch.hpp @@ -0,0 +1,17358 @@ +/* + * Catch v2.13.4 + * Generated: 2020-12-29 14:48:00.116107 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 4 + +#ifdef __clang__ +#pragma clang system_header +#elif defined __GNUC__ +#pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +#ifdef __ICC // icpc defines the __clang__ macro +#pragma warning(push) +#pragma warning(disable : 161 1682) +#else // __ICC +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif +#elif defined __GNUC__ +// Because REQUIREs trigger GCC's -Wparentheses, and because still +// supported version of g++ have only buggy support for _Pragmas, +// Wparentheses have to be suppressed globally. +#pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +#define CATCH_IMPL +#define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +#define CATCH_CONFIG_EXTERNAL_INTERFACES +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#undef CATCH_CONFIG_DISABLE_MATCHERS +#endif +#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +#include +#if TARGET_OS_OSX == 1 +#define CATCH_PLATFORM_MAC +#elif TARGET_OS_IPHONE == 1 +#define CATCH_PLATFORM_IPHONE +#endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +#define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) +#define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +#ifndef CLARA_CONFIG_MAIN +#define CLARA_CONFIG_MAIN_NOT_DEFINED +#define CLARA_CONFIG_MAIN +#endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { +unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +#if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +#define CATCH_CPP14_OR_GREATER +#endif + +#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define CATCH_CPP17_OR_GREATER +#endif + +#endif + +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic push") +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic pop") + +#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("clang diagnostic push") +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("clang diagnostic pop") + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +#if !defined(__ibmxl__) && !defined(__CUDACC__) +#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) \ + (void)__builtin_constant_p( \ + __VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +#endif + +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") + +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wparentheses\"") + +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wunused-variable\"") + +#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") + +#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wunused-template\"") + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) +#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +#define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +#define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +#if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) && \ + !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +#endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma(warning(push)) +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma(warning(pop)) + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define CATCH_CONFIG_COLOUR_NONE +#else +#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +#endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +#if !defined(__clang__) // Handle Clang masquerading for msvc +#if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +#define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif // MSVC_TRADITIONAL +#endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +#define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +#define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +#define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) +#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L) +#define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) +#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#define CATCH_INTERNAL_CONFIG_NO_ASYNC +#define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) +// Check if string_view is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW +#endif + +// Check if optional is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + +// Check if byte is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#include +#if __cpp_lib_byte > 0 +#define CATCH_INTERNAL_CONFIG_CPP17_BYTE +#endif +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + +// Check if variant is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#if defined(__clang__) && (__clang_major__ < 8) +// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 +// fix should be in clang 8, workaround in libstdc++ 8.2 +#include +#if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +#define CATCH_CONFIG_NO_CPP17_VARIANT +#else +#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +#endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +#else +#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +#endif // defined(__clang__) && (__clang_major__ < 8) +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && \ + !defined(CATCH_CONFIG_COUNTER) +#define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && \ + !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +#define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by +// default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && \ + !defined(CATCH_CONFIG_POSIX_SIGNALS) +#define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare +// exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && \ + !defined(CATCH_CONFIG_WCHAR) +#define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && \ + !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +#define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && \ + !defined(CATCH_CONFIG_CPP17_OPTIONAL) +#define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && \ + !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +#define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && \ + !defined(CATCH_CONFIG_CPP17_VARIANT) +#define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && \ + !defined(CATCH_CONFIG_CPP17_BYTE) +#define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +#define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && \ + !defined(CATCH_CONFIG_NEW_CAPTURE) +#define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && \ + !defined(CATCH_CONFIG_POLYFILL_ISNAN) +#define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && \ + !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +#define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && \ + !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +#define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && \ + !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +#define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE(name, line) INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) +#ifdef CATCH_CONFIG_COUNTER +#define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __COUNTER__) +#else +#define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + +struct CaseSensitive { + enum Choice { Yes, No }; +}; + +class NonCopyable { + NonCopyable(NonCopyable const&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); +}; + +struct SourceLineInfo { + SourceLineInfo() = delete; + SourceLineInfo(char const* _file, std::size_t _line) noexcept : file(_file), line(_line) {} + + SourceLineInfo(SourceLineInfo const& other) = default; + SourceLineInfo& operator=(SourceLineInfo const&) = default; + SourceLineInfo(SourceLineInfo&&) noexcept = default; + SourceLineInfo& operator=(SourceLineInfo&&) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator==(SourceLineInfo const& other) const noexcept; + bool operator<(SourceLineInfo const& other) const noexcept; + + char const* file; + std::size_t line; +}; + +std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info); + +// Bring in operator<< from global namespace into Catch namespace +// This is necessary because the overload of operator<< above makes +// lookup stop at namespace Catch +using ::operator<<; + +// Use this in variadic streaming macros to allow +// >> +StreamEndStop +// as well as +// >> stuff +StreamEndStop +struct StreamEndStop { + std::string operator+() const; +}; +template T const& operator+(T const& value, StreamEndStop) { return value; } +} // namespace Catch + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo(__FILE__, static_cast(__LINE__)) + +// end catch_common.h +namespace Catch { + +struct RegistrarForTagAliases { + RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo); +}; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS(alias, spec) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME(AutoRegisterTagAlias)( \ + alias, spec, CATCH_INTERNAL_LINEINFO); \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + +class TestSpec; + +struct ITestInvoker { + virtual void invoke() const = 0; + virtual ~ITestInvoker(); +}; + +class TestCase; +struct IConfig; + +struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted(IConfig const& config) const = 0; +}; + +bool isThrowSafe(TestCase const& testCase, IConfig const& config); +bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config); +std::vector filterTests(std::vector const& testCases, TestSpec const& testSpec, + IConfig const& config); +std::vector const& getAllTestCasesSorted(IConfig const& config); + +} // namespace Catch + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + +/// A non-owning string class (similar to the forthcoming std::string_view) +/// Note that, because a StringRef may be a substring of another string, +/// it may not be null terminated. +class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef(char const* rawChars) noexcept; + + constexpr StringRef(char const* rawChars, size_type size) noexcept + : m_start(rawChars), m_size(size) {} + + StringRef(std::string const& stdString) noexcept + : m_start(stdString.c_str()), m_size(stdString.size()) {} + + explicit operator std::string() const { return std::string(m_start, m_size); } + + public: // operators + auto operator==(StringRef const& other) const noexcept -> bool; + auto operator!=(StringRef const& other) const noexcept -> bool { return !(*this == other); } + + auto operator[](size_type index) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { return m_size == 0; } + constexpr auto size() const noexcept -> size_type { return m_size; } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr(size_type start, size_type length) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { return m_start[m_size] == '\0'; } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } +}; + +auto operator+=(std::string& lhs, StringRef const& sr) -> std::string&; +auto operator<<(std::ostream& os, StringRef const& sr) -> std::ostream&; + +constexpr auto operator"" _sr(char const* rawChars, std::size_t size) noexcept -> StringRef { + return StringRef(rawChars, size); +} +} // namespace Catch + +constexpr auto operator"" _catch_sr(char const* rawChars, std::size_t size) noexcept + -> Catch::StringRef { + return Catch::StringRef(rawChars, size); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) \ + CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) \ + CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) \ + CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) \ + CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) \ + CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) \ + CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER(CATCH_REC_NEXT0)(test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__) +#define CATCH_REC_LIST1(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0))(f, peek, __VA_ARGS__) +#define CATCH_REC_LIST2(f, x, peek, ...) \ + f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) \ + CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))(f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) \ + CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD))(f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) \ + f(userdata, x) \ + CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))(f, userdata, peek, __VA_ARGS__) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the +// results, and passes userdata as the first parameter to each invocation, e.g. CATCH_REC_LIST_UD(f, +// x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) \ + CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) \ + CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO##__VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ + INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand +// INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ + (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ + decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ + INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...) \ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST, __VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), \ + INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), \ + INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ + INTERNAL_CATCH_REMOVE_PARENS(_0), \ + INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN \ + template struct TypeList {}; \ + template constexpr auto get_wrapper() noexcept -> TypeList { \ + return {}; \ + } \ + template