#
# File: test/CMakeLists.txt

# Each test is contained in its own subdirectory of this test directory.
# The tests are driven by CTest; build the test suite with -DBUILD_TESTING=ON
# and run it with `ctest`.

cmake_minimum_required(VERSION 3.18..4.0 FATAL_ERROR)
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
  project(test-hipfort)
endif()

# cmake-based test infrastructure

if(BUILD_TESTING)
  # The Intel compilers (ifx/ifort) do not recognize the .f03/.f08 source
  # extensions and skip such files ("no action performed"). Force Fortran
  # compilation by inserting -Tf immediately before the source in the compile
  # rule (set_source_files_properties(LANGUAGE Fortran) alone is not enough).
  if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
    string(REPLACE "<SOURCE>" "-Tf <SOURCE>"
           CMAKE_Fortran_COMPILE_OBJECT "${CMAKE_Fortran_COMPILE_OBJECT}")
  endif()

  function(hipfort_add_test lib func dir)
    # The f2008 tests exercise the array overloads (USE_FPOINTER_INTERFACES) and
    # the f2018 tests the assumed-rank overloads; skip each when its interface
    # level is disabled so a plain C-binding build still tests cleanly.
    if(dir STREQUAL "f2008" AND NOT HIPFORT_USE_FPOINTER_INTERFACES)
      return()
    endif()
    if(dir STREQUAL "f2018" AND NOT HIPFORT_ASSUMED_RANK)
      return()
    endif()
    if(dir STREQUAL "f2008")
      set(ext "f08")
    elseif(dir STREQUAL "f2018")
      # F2018 sources use .f90; .f18 would require compiler-dependent flags.
      set(ext "f90")
    else()
      set(ext "f03")
    endif()
    # Build absolute source path and fail early if checkout is incomplete.
    set(src "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/${lib}/${func}.${ext}")
    if(NOT EXISTS "${src}")
      message(FATAL_ERROR "Missing test source: ${src}")
    endif()

    # Force language detection for .f03/.f08 in toolchains where CMake misses it.
    set_source_files_properties("${src}" PROPERTIES LANGUAGE Fortran)
    add_executable(hipfort_test_${dir}_${lib}_${func} "${src}")
    set_target_properties(hipfort_test_${dir}_${lib}_${func}
      PROPERTIES LINKER_LANGUAGE Fortran)
    target_link_libraries(hipfort_test_${dir}_${lib}_${func} PRIVATE hipfort::${lib} hipfort::hip)

    # the tests call EXIT, which is a GNU extension in gfortran
    target_compile_options(hipfort_test_${dir}_${lib}_${func} PRIVATE $<$<COMPILE_LANG_AND_ID:Fortran,GNU>:-std=gnu>)
    
    add_test(
      NAME hipfort_test_${dir}_${lib}_${func}
      COMMAND hipfort_test_${dir}_${lib}_${func}
    )
  endfunction()

  # Extended, exhaustive per-library "symbol" tests (test_<lib>.F03),
  # auto-generated by the rocm-fortran generator
  # (src/tools/gen_symbol_tests.jl, run with LAYOUT=hipfort). Each references
  # *every* bind(c) routine of a library through its generic name, guarded
  # so nothing executes: the point is purely to prove each interface compiles
  # and each C symbol links. Because they reference every symbol, enabling them
  # turns an undefined-symbol (missing in the installed ROCm) into a build error
  # -- handy to audit a specific ROCm version, but off by default so a
  # partial/older ROCm does not break the normal test build. Reuses the
  # HIPFORT_EXTENDED_TESTS option declared in the top-level CMakeLists.txt:
  # like the undefined-symbol shared-link test it gates, this needs a recent,
  # complete ROCm/CUDA install to be certain it passes.
  #
  # The sources are preprocessed .F03: routines with no CUDA counterpart are
  # wrapped in #ifndef USE_CUDA_NAMES, so the same file also builds on the NVIDIA
  # backend, where the interfaces bind to cu* symbols. On that backend the test
  # must be compiled with -DUSE_CUDA_NAMES to match the nvptx library it links.
  #
  # Detect the active backend the way lib/CMakeLists.txt does: this test/ tree is
  # a sibling add_subdirectory and cannot see lib/'s HIP_PLATFORM, so re-run the
  # same detection here. The symbol tests build whenever HIPFORT_EXTENDED_TESTS is
  # on and the backend's runtime libraries are found (the per-test if(TARGET
  # hipfort::<lib>) guards handle that); this only decides the symbol naming.
  # NB: CUDAToolkit is often found on an AMD box too, so it alone is not the
  # discriminator -- HIP_PLATFORM is.
  set(_hipfort_cuda_backend FALSE)
  if(HIPFORT_EXTENDED_TESTS)
    find_package(hip QUIET PATHS ${ROCM_PATH})
    find_package(CUDAToolkit QUIET)
    if(NOT HIP_PLATFORM STREQUAL "amd" AND CUDAToolkit_FOUND)
      set(_hipfort_cuda_backend TRUE)
    endif()
  endif()
  function(hipfort_add_symbol_test lib)
    if(NOT HIPFORT_EXTENDED_TESTS)
      return()
    endif()
    set(src "${CMAKE_CURRENT_SOURCE_DIR}/f2003/${lib}/test_${lib}.F03")
    if(NOT EXISTS "${src}")
      message(FATAL_ERROR "Missing symbol test source: ${src}")
    endif()
    set(tgt hipfort_test_f2003_${lib}_test_${lib})
    set_source_files_properties("${src}" PROPERTIES
      LANGUAGE Fortran Fortran_PREPROCESS ON)
    add_executable(${tgt} "${src}")
    set_target_properties(${tgt} PROPERTIES LINKER_LANGUAGE Fortran)
    target_link_libraries(${tgt} PRIVATE hipfort::${lib} hipfort::hip)
    if(_hipfort_cuda_backend)
      target_compile_definitions(${tgt} PRIVATE USE_CUDA_NAMES)
      # The HIP runtime maps ~50 routines to the CUDA *driver* API (cu*), which
      # live in libcuda, not libcudart (hipfort::hip -> CUDA::cudart). Link the
      # driver stub so the exhaustive runtime symbol test resolves them.
      if(lib STREQUAL "hip" AND TARGET CUDA::cuda_driver)
        target_link_libraries(${tgt} PRIVATE CUDA::cuda_driver)
      endif()
    endif()
    add_test(NAME ${tgt} COMMAND ${tgt})
  endfunction()

  if(TARGET hipfort::hipblas)
    hipfort_add_symbol_test(hipblas)
    hipfort_add_test(hipblas cgemm f2003)
    hipfort_add_test(hipblas dgemm f2003)
    hipfort_add_test(hipblas sgemm f2003)
    hipfort_add_test(hipblas zgemm f2003)
    hipfort_add_test(hipblas sgemm_batched f2003)
    hipfort_add_test(hipblas dgemm_batched f2003)
    hipfort_add_test(hipblas cgemm_batched f2003)
    hipfort_add_test(hipblas zgemm_batched f2003)
    hipfort_add_test(hipblas sgemm_strided_batched f2003)
    hipfort_add_test(hipblas dgemm_strided_batched f2003)
    hipfort_add_test(hipblas cgemm_strided_batched f2003)
    hipfort_add_test(hipblas zgemm_strided_batched f2003)
    hipfort_add_test(hipblas dger f2003)
    hipfort_add_test(hipblas dscal f2003)
    hipfort_add_test(hipblas saxpy f2003)
    hipfort_add_test(hipblas daxpy f2003)
    hipfort_add_test(hipblas caxpy f2003)
    hipfort_add_test(hipblas zaxpy f2003)
    hipfort_add_test(hipblas scopy f2003)
    hipfort_add_test(hipblas sgemv f2003)
    hipfort_add_test(hipblas dgemv f2003)
    hipfort_add_test(hipblas cgemv f2003)
    hipfort_add_test(hipblas zgemv f2003)
    hipfort_add_test(hipblas strsv f2003)
    hipfort_add_test(hipblas dtrsv f2003)
    hipfort_add_test(hipblas ctrsv f2003)
    hipfort_add_test(hipblas ztrsv f2003)
    hipfort_add_test(hipblas strsm f2003)
    hipfort_add_test(hipblas dtrsm f2003)
    hipfort_add_test(hipblas ctrsm f2003)
    hipfort_add_test(hipblas ztrsm f2003)
    hipfort_add_test(hipblas sdot  f2003)
    hipfort_add_test(hipblas ddot  f2003)
    hipfort_add_test(hipblas cdotu f2003)
    hipfort_add_test(hipblas cdotc f2003)
    hipfort_add_test(hipblas zdotu f2003)
    hipfort_add_test(hipblas zdotc f2003)
    hipfort_add_test(hipblas sger f2003)
    hipfort_add_test(hipblas sswap f2003)

    hipfort_add_test(hipblas cgemm f2008)
    hipfort_add_test(hipblas dgemm f2008)
    hipfort_add_test(hipblas sgemm f2008)
    hipfort_add_test(hipblas zgemm f2008)
    hipfort_add_test(hipblas sgemm_batched f2008)
    hipfort_add_test(hipblas dgemm_batched f2008)
    hipfort_add_test(hipblas cgemm_batched f2008)
    hipfort_add_test(hipblas zgemm_batched f2008)
    hipfort_add_test(hipblas sgemm_strided_batched f2008)
    hipfort_add_test(hipblas dgemm_strided_batched f2008)
    hipfort_add_test(hipblas cgemm_strided_batched f2008)
    hipfort_add_test(hipblas zgemm_strided_batched f2008)
    hipfort_add_test(hipblas dger f2008)
    hipfort_add_test(hipblas dscal f2008)
    hipfort_add_test(hipblas saxpy f2008)
    hipfort_add_test(hipblas daxpy f2008)
    hipfort_add_test(hipblas caxpy f2008)
    hipfort_add_test(hipblas zaxpy f2008)
    hipfort_add_test(hipblas scopy f2008)
    hipfort_add_test(hipblas sgemv f2008)
    hipfort_add_test(hipblas dgemv f2008)
    hipfort_add_test(hipblas cgemv f2008)
    hipfort_add_test(hipblas zgemv f2008)
    hipfort_add_test(hipblas strsv f2008)
    hipfort_add_test(hipblas dtrsv f2008)
    hipfort_add_test(hipblas ctrsv f2008)
    hipfort_add_test(hipblas ztrsv f2008)
    hipfort_add_test(hipblas strsm f2008)
    hipfort_add_test(hipblas dtrsm f2008)
    hipfort_add_test(hipblas ctrsm f2008)
    hipfort_add_test(hipblas ztrsm f2008)
    hipfort_add_test(hipblas sdot  f2008)
    hipfort_add_test(hipblas ddot  f2008)
    hipfort_add_test(hipblas cdotu f2008)
    hipfort_add_test(hipblas cdotc f2008)
    hipfort_add_test(hipblas zdotu f2008)
    hipfort_add_test(hipblas zdotc f2008)
    hipfort_add_test(hipblas sger f2008)
    hipfort_add_test(hipblas sswap f2008)
    hipfort_add_test(hipblas stpsv f2008)
  endif()

  if(TARGET hipfort::hipfft)
    hipfort_add_symbol_test(hipfft)
    hipfort_add_test(hipfft hipfft f2003)
    hipfort_add_test(hipfft hipfft f2008)
    hipfort_add_test(hipfft hipfft_c2c_1d_z f2003)
    hipfort_add_test(hipfft hipfft_c2c_1d_z f2008)
    hipfort_add_test(hipfft hipfft_c2c_1d_c f2003)
    hipfort_add_test(hipfft hipfft_c2c_1d_c f2008)
    hipfort_add_test(hipfft hipfft_r2c_c2r_1d_d f2003)
    hipfort_add_test(hipfft hipfft_r2c_c2r_1d_d f2008)
    hipfort_add_test(hipfft hipfft_r2c_c2r_1d_s f2003)
    hipfort_add_test(hipfft hipfft_r2c_c2r_1d_s f2008)
    hipfort_add_test(hipfft hipfft_c2c_2d_z f2003)
    hipfort_add_test(hipfft hipfft_c2c_2d_z f2008)
    hipfort_add_test(hipfft hipfft_c2c_3d_z f2003)
    hipfort_add_test(hipfft hipfft_c2c_3d_z f2008)
    hipfort_add_test(hipfft hipfft_c2c_1d_batched_z f2003)
    hipfort_add_test(hipfft hipfft_c2c_1d_batched_z f2008)
    hipfort_add_test(hipfft hipfft_planmany_2d_z2z f2003)
    hipfort_add_test(hipfft hipfft_planmany_2d_z2z f2008)
    hipfort_add_test(hipfft hipfft_makeplanmany_z f2003)
    hipfort_add_test(hipfft hipfft_makeplanmany_z f2008)
    hipfort_add_test(hipfft hipfft_estimate_getsize_d f2003)
    hipfort_add_test(hipfft hipfft_estimate_getsize_d f2008)
    hipfort_add_test(hipfft hipfft_setstream_z f2003)
    hipfort_add_test(hipfft hipfft_setstream_z f2008)
  endif()

  if(TARGET hipfort::hipfftw)
    hipfort_add_symbol_test(hipfftw)
    # Detect hipfftw API features based on hipfft version.
    # Version-to-feature mapping (based on ROCm releases):
    #   hipfft < 1.0.21: no hipfftw library
    #   hipfft 1.0.21:   hipfftw exists but no fftw_execute_dft (ROCm 7.1)
    #   hipfft 1.0.22:   adds fftw_execute_dft (ROCm 7.2)
    #   hipfft 1.0.23+:  adds fftw_plan_many_dft and fftw_plan_guru_dft
    #                    (therock/ROCm 7.3+)
    set(HIPFFTW_HAS_EXECUTE_DFT FALSE)
    set(HIPFFTW_HAS_PLAN_MANY_DFT FALSE)

    # hipfft's config doesn't export hipfft_VERSION, so extract it from the version file
    set(_hipfft_version_file "${hipfft_DIR}/hipfft-config-version.cmake")
    if(EXISTS "${_hipfft_version_file}")
      file(STRINGS "${_hipfft_version_file}" _hipfft_version_line
           REGEX "^set\\(PACKAGE_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\"\\)")
      if(_hipfft_version_line)
        string(REGEX REPLACE ".*\"([0-9]+\\.[0-9]+\\.[0-9]+)\".*" "\\1"
               _hipfft_version "${_hipfft_version_line}")
        message(STATUS "Detected hipfft version: ${_hipfft_version}")
        if(_hipfft_version VERSION_GREATER_EQUAL "1.0.22")
          set(HIPFFTW_HAS_EXECUTE_DFT TRUE)
        endif()
        if(_hipfft_version VERSION_GREATER_EQUAL "1.0.23")
          set(HIPFFTW_HAS_PLAN_MANY_DFT TRUE)
        endif()
      endif()
    else()
      message(STATUS "hipfft version file not found, cannot detect hipfftw features")
    endif()

    if(HIPFFTW_HAS_EXECUTE_DFT)
      hipfort_add_test(hipfftw hipfftw_c2c f2003)
      hipfort_add_test(hipfftw hipfftw_r2c_c2r f2003)
      hipfort_add_test(hipfftw hipfftw_dft_2d f2003)
      hipfort_add_test(hipfftw hipfftw_dft_3d f2003)
      hipfort_add_test(hipfftw hipfftw_alloc f2003)
    else()
      message(STATUS "Skipping hipfftw c2c/r2c_c2r/dft_2d/dft_3d tests (requires hipfft >= 1.0.22)")
    endif()

    if(HIPFFTW_HAS_PLAN_MANY_DFT)
      hipfort_add_test(hipfftw hipfftw_many f2003)
      hipfort_add_test(hipfftw hipfftw_guru f2003)
    else()
      message(STATUS "Skipping hipfftw_many/hipfftw_guru tests (requires hipfft >= 1.0.23)")
    endif()
  endif()

  if(TARGET hipfort::hipsolver)
    hipfort_add_symbol_test(hipsolver)
    hipfort_add_test(hipsolver hipsolver_sgetrf f2003)
    hipfort_add_test(hipsolver hipsolver_dgetrf f2003)
    hipfort_add_test(hipsolver hipsolver_cgetrf f2003)
    hipfort_add_test(hipsolver hipsolver_zgetrf f2003)
    hipfort_add_test(hipsolver hipsolver_sgetrf f2008)
    hipfort_add_test(hipsolver hipsolver_dgetrf f2008)
    hipfort_add_test(hipsolver hipsolver_cgetrf f2008)
    hipfort_add_test(hipsolver hipsolver_zgetrf f2008)
    hipfort_add_test(hipsolver hipsolver_dpotrf f2008)
    hipfort_add_test(hipsolver hipsolver_spotrfbatched f2003)
    hipfort_add_test(hipsolver hipsolver_spotrfbatched f2008)
    hipfort_add_test(hipsolver hipsolver_dpotrfbatched f2003)
    hipfort_add_test(hipsolver hipsolver_dpotrfbatched f2008)
    hipfort_add_test(hipsolver hipsolver_cpotrfbatched f2003)
    hipfort_add_test(hipsolver hipsolver_cpotrfbatched f2008)
    hipfort_add_test(hipsolver hipsolver_zpotrfbatched f2003)
    hipfort_add_test(hipsolver hipsolver_zpotrfbatched f2008)
    hipfort_add_test(hipsolver hipsolver_dsyevd f2008)
    hipfort_add_test(hipsolver hipsolver_ssyevd f2008)
    hipfort_add_test(hipsolver hipsolver_cheevd f2008)
    hipfort_add_test(hipsolver hipsolver_zheevd f2008)
    hipfort_add_test(hipsolver hipsolver_ssyevd f2003)
    hipfort_add_test(hipsolver hipsolver_cheevd f2003)
    hipfort_add_test(hipsolver hipsolver_zheevd f2003)
    hipfort_add_test(hipsolver hipsolver_sgesvd f2008)
    hipfort_add_test(hipsolver hipsolver_cgesvd f2008)
    hipfort_add_test(hipsolver hipsolver_zgesvd f2008)
    hipfort_add_test(hipsolver hipsolver_sgesvd f2003)
    hipfort_add_test(hipsolver hipsolver_cgesvd f2003)
    hipfort_add_test(hipsolver hipsolver_zgesvd f2003)
    hipfort_add_test(hipsolver hipsolver_ssyevdx f2008)
    hipfort_add_test(hipsolver hipsolver_dsyevdx f2008)
    hipfort_add_test(hipsolver hipsolver_cheevdx f2008)
    hipfort_add_test(hipsolver hipsolver_zheevdx f2008)
    hipfort_add_test(hipsolver hipsolver_ssygvd f2008)
    hipfort_add_test(hipsolver hipsolver_dsygvd f2008)
    hipfort_add_test(hipsolver hipsolver_chegvd f2008)
    hipfort_add_test(hipsolver hipsolver_zhegvd f2008)
    hipfort_add_test(hipsolver hipsolver_ssygvdx f2008)
    hipfort_add_test(hipsolver hipsolver_dsygvdx f2008)
    hipfort_add_test(hipsolver hipsolver_chegvdx f2008)
    hipfort_add_test(hipsolver hipsolver_zhegvdx f2008)
    hipfort_add_test(hipsolver hipsolver_ssyevdx f2003)
    hipfort_add_test(hipsolver hipsolver_dsyevdx f2003)
    hipfort_add_test(hipsolver hipsolver_cheevdx f2003)
    hipfort_add_test(hipsolver hipsolver_zheevdx f2003)
    hipfort_add_test(hipsolver hipsolver_ssygvd f2003)
    hipfort_add_test(hipsolver hipsolver_dsygvd f2003)
    hipfort_add_test(hipsolver hipsolver_chegvd f2003)
    hipfort_add_test(hipsolver hipsolver_zhegvd f2003)
    hipfort_add_test(hipsolver hipsolver_ssygvdx f2003)
    hipfort_add_test(hipsolver hipsolver_dsygvdx f2003)
    hipfort_add_test(hipsolver hipsolver_chegvdx f2003)
    hipfort_add_test(hipsolver hipsolver_zhegvdx f2003)
    hipfort_add_test(hipsolver hipsolver_dgetrs f2008)
    hipfort_add_test(hipsolver hipsolver_dgesvd f2008)
    hipfort_add_test(hipsolver hipsolver_sgeqrf f2003)
    hipfort_add_test(hipsolver hipsolver_sgeqrf f2008)
    hipfort_add_test(hipsolver hipsolver_dgeqrf f2003)
    hipfort_add_test(hipsolver hipsolver_dgeqrf f2008)
    hipfort_add_test(hipsolver hipsolver_cgeqrf f2003)
    hipfort_add_test(hipsolver hipsolver_cgeqrf f2008)
    hipfort_add_test(hipsolver hipsolver_zgeqrf f2003)
    hipfort_add_test(hipsolver hipsolver_zgeqrf f2008)
    hipfort_add_test(hipsolver hipsolver_sorgqr f2003)
    hipfort_add_test(hipsolver hipsolver_sorgqr f2008)
    hipfort_add_test(hipsolver hipsolver_dorgqr f2003)
    hipfort_add_test(hipsolver hipsolver_dorgqr f2008)
    hipfort_add_test(hipsolver hipsolver_cungqr f2003)
    hipfort_add_test(hipsolver hipsolver_cungqr f2008)
    hipfort_add_test(hipsolver hipsolver_zungqr f2003)
    hipfort_add_test(hipsolver hipsolver_zungqr f2008)
    hipfort_add_test(hipsolver hipsolver_spotrs f2003)
    hipfort_add_test(hipsolver hipsolver_spotrs f2008)
    hipfort_add_test(hipsolver hipsolver_dpotrs f2003)
    hipfort_add_test(hipsolver hipsolver_dpotrs f2008)
    hipfort_add_test(hipsolver hipsolver_cpotrs f2003)
    hipfort_add_test(hipsolver hipsolver_cpotrs f2008)
    hipfort_add_test(hipsolver hipsolver_zpotrs f2003)
    hipfort_add_test(hipsolver hipsolver_zpotrs f2008)
    hipfort_add_test(hipsolver hipsolver_ssyevj f2003)
    hipfort_add_test(hipsolver hipsolver_ssyevj f2008)
    hipfort_add_test(hipsolver hipsolver_dsyevj f2003)
    hipfort_add_test(hipsolver hipsolver_dsyevj f2008)
    hipfort_add_test(hipsolver hipsolver_sgesvdj f2003)
    hipfort_add_test(hipsolver hipsolver_sgesvdj f2008)
    hipfort_add_test(hipsolver hipsolver_dgesvdj f2003)
    hipfort_add_test(hipsolver hipsolver_dgesvdj f2008)
    hipfort_add_test(hipsolver hipsolver_cgesvdj f2003)
    hipfort_add_test(hipsolver hipsolver_cgesvdj f2008)
    hipfort_add_test(hipsolver hipsolver_zgesvdj f2003)
    hipfort_add_test(hipsolver hipsolver_zgesvdj f2008)
    hipfort_add_test(hipsolver hipsolver_dormqr f2003)
    hipfort_add_test(hipsolver hipsolver_dormqr f2008)
    hipfort_add_test(hipsolver hipsolver_sormqr f2003)
    hipfort_add_test(hipsolver hipsolver_sormqr f2008)
    hipfort_add_test(hipsolver hipsolver_cunmqr f2003)
    hipfort_add_test(hipsolver hipsolver_cunmqr f2008)
    hipfort_add_test(hipsolver hipsolver_zunmqr f2003)
    hipfort_add_test(hipsolver hipsolver_zunmqr f2008)
  endif()

  if(TARGET hipfort::hipsparse)
    hipfort_add_symbol_test(hipsparse)
    hipfort_add_test(hipsparse hipsparse_sgtsv f2008)
    hipfort_add_test(hipsparse hipsparse_scsr2csc f2008)
    hipfort_add_test(hipsparse hipsparse_xcsr2coo f2008)
    hipfort_add_test(hipsparse hipsparse_xcsr2coo f2003)
    hipfort_add_test(hipsparse hipsparse_xcoo2csr f2003)
    hipfort_add_test(hipsparse hipsparse_xcoo2csr f2008)
    hipfort_add_test(hipsparse hipsparse_sgthr f2003)
    hipfort_add_test(hipsparse hipsparse_sgthr f2008)
    hipfort_add_test(hipsparse hipsparse_dgthr f2003)
    hipfort_add_test(hipsparse hipsparse_dgthr f2008)
    hipfort_add_test(hipsparse hipsparse_cgthr f2003)
    hipfort_add_test(hipsparse hipsparse_cgthr f2008)
    hipfort_add_test(hipsparse hipsparse_zgthr f2003)
    hipfort_add_test(hipsparse hipsparse_zgthr f2008)
    hipfort_add_test(hipsparse hipsparse_ssctr f2003)
    hipfort_add_test(hipsparse hipsparse_ssctr f2008)
    hipfort_add_test(hipsparse hipsparse_dsctr f2003)
    hipfort_add_test(hipsparse hipsparse_dsctr f2008)
    hipfort_add_test(hipsparse hipsparse_csctr f2003)
    hipfort_add_test(hipsparse hipsparse_csctr f2008)
    hipfort_add_test(hipsparse hipsparse_zsctr f2003)
    hipfort_add_test(hipsparse hipsparse_zsctr f2008)
    hipfort_add_test(hipsparse hipsparse_sgemvi f2003)
    hipfort_add_test(hipsparse hipsparse_sgemvi f2008)
    hipfort_add_test(hipsparse hipsparse_dgemvi f2003)
    hipfort_add_test(hipsparse hipsparse_dgemvi f2008)
    hipfort_add_test(hipsparse hipsparse_cgemvi f2003)
    hipfort_add_test(hipsparse hipsparse_cgemvi f2008)
    hipfort_add_test(hipsparse hipsparse_zgemvi f2003)
    hipfort_add_test(hipsparse hipsparse_zgemvi f2008)
    hipfort_add_test(hipsparse hipsparse_scsrsv2 f2003)
    hipfort_add_test(hipsparse hipsparse_scsrsv2 f2008)
    hipfort_add_test(hipsparse hipsparse_dcsrsv2 f2003)
    hipfort_add_test(hipsparse hipsparse_dcsrsv2 f2008)
    hipfort_add_test(hipsparse hipsparse_ccsrsv2 f2003)
    hipfort_add_test(hipsparse hipsparse_ccsrsv2 f2008)
    hipfort_add_test(hipsparse hipsparse_zcsrsv2 f2003)
    hipfort_add_test(hipsparse hipsparse_zcsrsv2 f2008)
    hipfort_add_test(hipsparse hipsparse_scsrilu02 f2003)
    hipfort_add_test(hipsparse hipsparse_scsrilu02 f2008)
    hipfort_add_test(hipsparse hipsparse_dcsrilu02 f2003)
    hipfort_add_test(hipsparse hipsparse_dcsrilu02 f2008)
    hipfort_add_test(hipsparse hipsparse_ccsrilu02 f2003)
    hipfort_add_test(hipsparse hipsparse_ccsrilu02 f2008)
    hipfort_add_test(hipsparse hipsparse_zcsrilu02 f2003)
    hipfort_add_test(hipsparse hipsparse_zcsrilu02 f2008)
    hipfort_add_test(hipsparse hipsparse_sspmv f2003)
    hipfort_add_test(hipsparse hipsparse_sspmv f2008)
    hipfort_add_test(hipsparse hipsparse_dspmv f2003)
    hipfort_add_test(hipsparse hipsparse_dspmv f2008)
    hipfort_add_test(hipsparse hipsparse_cspmv f2003)
    hipfort_add_test(hipsparse hipsparse_cspmv f2008)
    hipfort_add_test(hipsparse hipsparse_zspmv f2003)
    hipfort_add_test(hipsparse hipsparse_zspmv f2008)
    hipfort_add_test(hipsparse hipsparse_sspmm f2003)
    hipfort_add_test(hipsparse hipsparse_sspmm f2008)
    hipfort_add_test(hipsparse hipsparse_dspmm f2003)
    hipfort_add_test(hipsparse hipsparse_dspmm f2008)
    hipfort_add_test(hipsparse hipsparse_cspmm f2003)
    hipfort_add_test(hipsparse hipsparse_cspmm f2008)
    hipfort_add_test(hipsparse hipsparse_zspmm f2003)
    hipfort_add_test(hipsparse hipsparse_zspmm f2008)
    hipfort_add_test(hipsparse hipsparse_ssddmm f2003)
    hipfort_add_test(hipsparse hipsparse_ssddmm f2008)
    hipfort_add_test(hipsparse hipsparse_dsddmm f2003)
    hipfort_add_test(hipsparse hipsparse_dsddmm f2008)
    hipfort_add_test(hipsparse hipsparse_csddmm f2003)
    hipfort_add_test(hipsparse hipsparse_csddmm f2008)
    hipfort_add_test(hipsparse hipsparse_zsddmm f2003)
    hipfort_add_test(hipsparse hipsparse_zsddmm f2008)
    hipfort_add_test(hipsparse hipsparse_scsrgemm f2003)
    hipfort_add_test(hipsparse hipsparse_scsrgemm f2008)
    hipfort_add_test(hipsparse hipsparse_dcsrgemm f2003)
    hipfort_add_test(hipsparse hipsparse_dcsrgemm f2008)
    hipfort_add_test(hipsparse hipsparse_ccsrgemm f2003)
    hipfort_add_test(hipsparse hipsparse_ccsrgemm f2008)
    hipfort_add_test(hipsparse hipsparse_zcsrgemm f2003)
    hipfort_add_test(hipsparse hipsparse_zcsrgemm f2008)
    hipfort_add_test(hipsparse hipsparse_ssptrsv f2003)
    hipfort_add_test(hipsparse hipsparse_ssptrsv f2008)
    hipfort_add_test(hipsparse hipsparse_dsptrsv f2003)
    hipfort_add_test(hipsparse hipsparse_dsptrsv f2008)
    hipfort_add_test(hipsparse hipsparse_csptrsv f2003)
    hipfort_add_test(hipsparse hipsparse_csptrsv f2008)
    hipfort_add_test(hipsparse hipsparse_zsptrsv f2003)
    hipfort_add_test(hipsparse hipsparse_zsptrsv f2008)
    hipfort_add_test(hipsparse hipsparse_ssptrsm f2003)
    hipfort_add_test(hipsparse hipsparse_ssptrsm f2008)
    hipfort_add_test(hipsparse hipsparse_dsptrsm f2003)
    hipfort_add_test(hipsparse hipsparse_dsptrsm f2008)
    hipfort_add_test(hipsparse hipsparse_csptrsm f2003)
    hipfort_add_test(hipsparse hipsparse_csptrsm f2008)
    hipfort_add_test(hipsparse hipsparse_zsptrsm f2003)
    hipfort_add_test(hipsparse hipsparse_zsptrsm f2008)
    hipfort_add_test(hipsparse hipsparse_dcsr2csc f2003)
    hipfort_add_test(hipsparse hipsparse_dcsr2csc f2008)
    hipfort_add_test(hipsparse hipsparse_ccsr2csc f2003)
    hipfort_add_test(hipsparse hipsparse_ccsr2csc f2008)
    hipfort_add_test(hipsparse hipsparse_zcsr2csc f2003)
    hipfort_add_test(hipsparse hipsparse_zcsr2csc f2008)
  endif()

  if(TARGET hipfort::rocblas)
    hipfort_add_symbol_test(rocblas)
    hipfort_add_test(rocblas saxpy f2003)
    hipfort_add_test(rocblas daxpy f2003)
    hipfort_add_test(rocblas caxpy f2003)
    hipfort_add_test(rocblas zaxpy f2003)
    hipfort_add_test(rocblas dtrmm f2003)
    hipfort_add_test(rocblas saxpy f2008)
    hipfort_add_test(rocblas daxpy f2008)
    hipfort_add_test(rocblas saxpy f2018)
    hipfort_add_test(rocblas caxpy f2008)
    hipfort_add_test(rocblas zaxpy f2008)
    hipfort_add_test(rocblas dtrmm f2008)
    hipfort_add_test(rocblas sgemm f2003)
    hipfort_add_test(rocblas dgemm f2003)
    hipfort_add_test(rocblas cgemm f2003)
    hipfort_add_test(rocblas zgemm f2003)
    hipfort_add_test(rocblas sgemm f2008)
    hipfort_add_test(rocblas dgemm f2008)
    hipfort_add_test(rocblas cgemm f2008)
    hipfort_add_test(rocblas zgemm f2008)
    hipfort_add_test(rocblas sgemm_batched f2003)
    hipfort_add_test(rocblas dgemm_batched f2003)
    hipfort_add_test(rocblas cgemm_batched f2003)
    hipfort_add_test(rocblas zgemm_batched f2003)
    hipfort_add_test(rocblas sgemm_strided_batched f2003)
    hipfort_add_test(rocblas dgemm_strided_batched f2003)
    hipfort_add_test(rocblas cgemm_strided_batched f2003)
    hipfort_add_test(rocblas zgemm_strided_batched f2003)
    hipfort_add_test(rocblas sgemm_batched f2008)
    hipfort_add_test(rocblas dgemm_batched f2008)
    hipfort_add_test(rocblas cgemm_batched f2008)
    hipfort_add_test(rocblas zgemm_batched f2008)
    hipfort_add_test(rocblas sgemm_strided_batched f2008)
    hipfort_add_test(rocblas dgemm_strided_batched f2008)
    hipfort_add_test(rocblas cgemm_strided_batched f2008)
    hipfort_add_test(rocblas zgemm_strided_batched f2008)
    hipfort_add_test(rocblas sgemv f2003)
    hipfort_add_test(rocblas dgemv f2003)
    hipfort_add_test(rocblas cgemv f2003)
    hipfort_add_test(rocblas zgemv f2003)
    hipfort_add_test(rocblas sgemv f2008)
    hipfort_add_test(rocblas dgemv f2008)
    hipfort_add_test(rocblas cgemv f2008)
    hipfort_add_test(rocblas zgemv f2008)
    hipfort_add_test(rocblas strsv f2003)
    hipfort_add_test(rocblas dtrsv f2003)
    hipfort_add_test(rocblas ctrsv f2003)
    hipfort_add_test(rocblas ztrsv f2003)
    hipfort_add_test(rocblas strsv f2008)
    hipfort_add_test(rocblas dtrsv f2008)
    hipfort_add_test(rocblas ctrsv f2008)
    hipfort_add_test(rocblas ztrsv f2008)
    hipfort_add_test(rocblas stpsv f2008)
    hipfort_add_test(rocblas strsm f2003)
    hipfort_add_test(rocblas dtrsm f2003)
    hipfort_add_test(rocblas ctrsm f2003)
    hipfort_add_test(rocblas ztrsm f2003)
    hipfort_add_test(rocblas strsm f2008)
    hipfort_add_test(rocblas dtrsm f2008)
    hipfort_add_test(rocblas ctrsm f2008)
    hipfort_add_test(rocblas ztrsm f2008)
    hipfort_add_test(rocblas sdot  f2003)
    hipfort_add_test(rocblas ddot  f2003)
    hipfort_add_test(rocblas cdotu f2003)
    hipfort_add_test(rocblas cdotc f2003)
    hipfort_add_test(rocblas zdotu f2003)
    hipfort_add_test(rocblas zdotc f2003)
    hipfort_add_test(rocblas sdot  f2008)
    hipfort_add_test(rocblas ddot  f2008)
    hipfort_add_test(rocblas cdotu f2008)
    hipfort_add_test(rocblas cdotc f2008)
    hipfort_add_test(rocblas zdotu f2008)
    hipfort_add_test(rocblas zdotc f2008)
    hipfort_add_test(rocblas sscal  f2003)
    hipfort_add_test(rocblas dscal  f2003)
    hipfort_add_test(rocblas cscal  f2003)
    hipfort_add_test(rocblas zscal  f2003)
    hipfort_add_test(rocblas csscal f2003)
    hipfort_add_test(rocblas zdscal f2003)
    hipfort_add_test(rocblas sscal  f2008)
    hipfort_add_test(rocblas dscal  f2008)
    hipfort_add_test(rocblas cscal  f2008)
    hipfort_add_test(rocblas zscal  f2008)
    hipfort_add_test(rocblas csscal f2008)
    hipfort_add_test(rocblas zdscal f2008)
    hipfort_add_test(rocblas dgemv_batched f2008)
  endif()

  if(TARGET hipfort::rocrand)
    hipfort_add_symbol_test(rocrand)
    hipfort_add_test(rocrand xorwow_uniform f2003)
    hipfort_add_test(rocrand xorwow_normal  f2003)
    hipfort_add_test(rocrand philox_uniform f2003)
    hipfort_add_test(rocrand philox_normal  f2003)
    hipfort_add_test(rocrand xorwow_uniform f2008)
    hipfort_add_test(rocrand xorwow_normal  f2008)
    hipfort_add_test(rocrand philox_uniform f2008)
    hipfort_add_test(rocrand philox_normal  f2008)
    hipfort_add_test(rocrand xorwow_uniform_double f2003)
    hipfort_add_test(rocrand xorwow_normal_double  f2003)
    hipfort_add_test(rocrand philox_uniform_double f2003)
    hipfort_add_test(rocrand philox_normal_double  f2003)
    hipfort_add_test(rocrand xorwow_uniform_double f2008)
    hipfort_add_test(rocrand xorwow_normal_double  f2008)
    hipfort_add_test(rocrand philox_uniform_double f2008)
    hipfort_add_test(rocrand philox_normal_double  f2008)
  endif()

  if(TARGET hipfort::hiprand)
    hipfort_add_symbol_test(hiprand)
    hipfort_add_test(hiprand xorwow_uniform f2003)
    hipfort_add_test(hiprand xorwow_normal  f2003)
    hipfort_add_test(hiprand philox_uniform f2003)
    hipfort_add_test(hiprand philox_normal  f2003)
    hipfort_add_test(hiprand xorwow_uniform f2008)
    hipfort_add_test(hiprand xorwow_normal  f2008)
    hipfort_add_test(hiprand philox_uniform f2008)
    hipfort_add_test(hiprand philox_normal  f2008)
    hipfort_add_test(hiprand xorwow_uniform_double f2003)
    hipfort_add_test(hiprand xorwow_normal_double  f2003)
    hipfort_add_test(hiprand philox_uniform_double f2003)
    hipfort_add_test(hiprand philox_normal_double  f2003)
    hipfort_add_test(hiprand xorwow_uniform_double f2008)
    hipfort_add_test(hiprand xorwow_normal_double  f2008)
    hipfort_add_test(hiprand philox_uniform_double f2008)
    hipfort_add_test(hiprand philox_normal_double  f2008)
  endif()

  if(TARGET hipfort::rocfft)
    hipfort_add_symbol_test(rocfft)
    hipfort_add_test(rocfft rocfft f2003)
    hipfort_add_test(rocfft rocfft f2008)
    hipfort_add_test(rocfft rocfft_c2c_1d_z f2003)
    hipfort_add_test(rocfft rocfft_c2c_1d_z f2008)
    hipfort_add_test(rocfft rocfft_c2c_1d_c f2003)
    hipfort_add_test(rocfft rocfft_c2c_1d_c f2008)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_d f2003)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_d f2008)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_s f2003)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_s f2008)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_inplace_d f2003)
    hipfort_add_test(rocfft rocfft_r2c_c2r_1d_inplace_d f2008)
    hipfort_add_test(rocfft rocfft_c2c_2d_z f2003)
    hipfort_add_test(rocfft rocfft_c2c_2d_z f2008)
    hipfort_add_test(rocfft rocfft_c2c_3d_z f2003)
    hipfort_add_test(rocfft rocfft_c2c_3d_z f2008)
    hipfort_add_test(rocfft rocfft_c2c_1d_batched_z f2003)
    hipfort_add_test(rocfft rocfft_c2c_1d_batched_z f2008)
    hipfort_add_test(rocfft rocfft_c2c_1d_notinplace_z f2003)
    hipfort_add_test(rocfft rocfft_c2c_1d_notinplace_z f2008)
    hipfort_add_test(rocfft rocfft_scale_factor_z f2003)
    hipfort_add_test(rocfft rocfft_scale_factor_z f2008)
    hipfort_add_test(rocfft rocfft_work_buffer_z f2003)
    hipfort_add_test(rocfft rocfft_work_buffer_z f2008)
    hipfort_add_test(rocfft rocfft_stream_z f2003)
    hipfort_add_test(rocfft rocfft_stream_z f2008)
    hipfort_add_test(rocfft rocfft_version f2003)
    hipfort_add_test(rocfft rocfft_version f2008)
    hipfort_add_test(rocfft rocfft_plan_print_z f2003)
    hipfort_add_test(rocfft rocfft_plan_print_z f2008)
    hipfort_add_test(rocfft rocfft_cache_z f2003)
    hipfort_add_test(rocfft rocfft_cache_z f2008)
    hipfort_add_test(rocfft rocfft_callback_z f2003)
    hipfort_add_test(rocfft rocfft_callback_z f2008)
    # Single-process multi-GPU field/brick decomposition; skips on < 2 GPUs.
    hipfort_add_test(rocfft rocfft_field_brick_z f2003)
    hipfort_add_test(rocfft rocfft_field_brick_z f2008)
  endif()

  if(TARGET hipfort::rocsolver)
    hipfort_add_symbol_test(rocsolver)
    hipfort_add_test(rocsolver rocsolver_dgeqrf f2003)
    hipfort_add_test(rocsolver rocsolver_dgeqrf f2008)
    hipfort_add_test(rocsolver rocsolver_dsterf f2003)
    hipfort_add_test(rocsolver rocsolver_dsterf f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrf_strided_batched f2003)
    hipfort_add_test(rocsolver rocsolver_dgetrf f2003)
    hipfort_add_test(rocsolver rocsolver_sgeqrf f2003)
    hipfort_add_test(rocsolver rocsolver_cgeqrf f2003)
    hipfort_add_test(rocsolver rocsolver_zgeqrf f2003)
    hipfort_add_test(rocsolver rocsolver_sgetrf f2003)
    hipfort_add_test(rocsolver rocsolver_cgetrf f2003)
    hipfort_add_test(rocsolver rocsolver_zgetrf f2003)
    hipfort_add_test(rocsolver rocsolver_spotrf f2003)
    hipfort_add_test(rocsolver rocsolver_dpotrf f2003)
    hipfort_add_test(rocsolver rocsolver_cpotrf f2003)
    hipfort_add_test(rocsolver rocsolver_zpotrf f2003)
    hipfort_add_test(rocsolver rocsolver_sgetrs f2003)
    hipfort_add_test(rocsolver rocsolver_dgetrs f2003)
    hipfort_add_test(rocsolver rocsolver_cgetrs f2003)
    hipfort_add_test(rocsolver rocsolver_zgetrs f2003)
    hipfort_add_test(rocsolver rocsolver_spotrs f2003)
    hipfort_add_test(rocsolver rocsolver_dpotrs f2003)
    hipfort_add_test(rocsolver rocsolver_cpotrs f2003)
    hipfort_add_test(rocsolver rocsolver_zpotrs f2003)
    hipfort_add_test(rocsolver rocsolver_sgesvd f2003)
    hipfort_add_test(rocsolver rocsolver_dgesvd f2003)
    hipfort_add_test(rocsolver rocsolver_cgesvd f2003)
    hipfort_add_test(rocsolver rocsolver_zgesvd f2003)
    hipfort_add_test(rocsolver rocsolver_ssyevd f2003)
    hipfort_add_test(rocsolver rocsolver_dsyevd f2003)
    hipfort_add_test(rocsolver rocsolver_cheevd f2003)
    hipfort_add_test(rocsolver rocsolver_zheevd f2003)
    hipfort_add_test(rocsolver rocsolver_dgetrf_strided_batched f2008)
    hipfort_add_test(rocsolver rocsolver_sgeqrf f2008)
    hipfort_add_test(rocsolver rocsolver_cgeqrf f2008)
    hipfort_add_test(rocsolver rocsolver_zgeqrf f2008)
    hipfort_add_test(rocsolver rocsolver_sgetrf f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrf f2008)
    hipfort_add_test(rocsolver rocsolver_cgetrf f2008)
    hipfort_add_test(rocsolver rocsolver_zgetrf f2008)
    hipfort_add_test(rocsolver rocsolver_spotrf f2008)
    hipfort_add_test(rocsolver rocsolver_dpotrf f2008)
    hipfort_add_test(rocsolver rocsolver_cpotrf f2008)
    hipfort_add_test(rocsolver rocsolver_zpotrf f2008)
    hipfort_add_test(rocsolver rocsolver_sgetrs f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrs f2008)
    hipfort_add_test(rocsolver rocsolver_cgetrs f2008)
    hipfort_add_test(rocsolver rocsolver_zgetrs f2008)
    hipfort_add_test(rocsolver rocsolver_spotrs f2008)
    hipfort_add_test(rocsolver rocsolver_dpotrs f2008)
    hipfort_add_test(rocsolver rocsolver_cpotrs f2008)
    hipfort_add_test(rocsolver rocsolver_zpotrs f2008)
    hipfort_add_test(rocsolver rocsolver_sgesvd f2008)
    hipfort_add_test(rocsolver rocsolver_dgesvd f2008)
    hipfort_add_test(rocsolver rocsolver_cgesvd f2008)
    hipfort_add_test(rocsolver rocsolver_zgesvd f2008)
    hipfort_add_test(rocsolver rocsolver_ssyevd f2008)
    hipfort_add_test(rocsolver rocsolver_dsyevd f2008)
    hipfort_add_test(rocsolver rocsolver_cheevd f2008)
    hipfort_add_test(rocsolver rocsolver_zheevd f2008)
    hipfort_add_test(rocsolver rocsolver_ssyevdx f2008)
    hipfort_add_test(rocsolver rocsolver_dsyevdx f2008)
    hipfort_add_test(rocsolver rocsolver_cheevdx f2008)
    hipfort_add_test(rocsolver rocsolver_zheevdx f2008)
    hipfort_add_test(rocsolver rocsolver_ssygvd f2008)
    hipfort_add_test(rocsolver rocsolver_dsygvd f2008)
    hipfort_add_test(rocsolver rocsolver_chegvd f2008)
    hipfort_add_test(rocsolver rocsolver_zhegvd f2008)
    hipfort_add_test(rocsolver rocsolver_ssygvdx f2008)
    hipfort_add_test(rocsolver rocsolver_dsygvdx f2008)
    hipfort_add_test(rocsolver rocsolver_chegvdx f2008)
    hipfort_add_test(rocsolver rocsolver_zhegvdx f2008)
    hipfort_add_test(rocsolver rocsolver_ssyevdx f2003)
    hipfort_add_test(rocsolver rocsolver_dsyevdx f2003)
    hipfort_add_test(rocsolver rocsolver_cheevdx f2003)
    hipfort_add_test(rocsolver rocsolver_zheevdx f2003)
    hipfort_add_test(rocsolver rocsolver_ssygvd f2003)
    hipfort_add_test(rocsolver rocsolver_dsygvd f2003)
    hipfort_add_test(rocsolver rocsolver_chegvd f2003)
    hipfort_add_test(rocsolver rocsolver_zhegvd f2003)
    hipfort_add_test(rocsolver rocsolver_ssygvdx f2003)
    hipfort_add_test(rocsolver rocsolver_dsygvdx f2003)
    hipfort_add_test(rocsolver rocsolver_chegvdx f2003)
    hipfort_add_test(rocsolver rocsolver_zhegvdx f2003)
    hipfort_add_test(rocsolver rocsolver_dgesv f2003)
    hipfort_add_test(rocsolver rocsolver_dgesv f2008)
    hipfort_add_test(rocsolver rocsolver_dgetri f2003)
    hipfort_add_test(rocsolver rocsolver_dgetri f2008)
    hipfort_add_test(rocsolver rocsolver_dlatrd f2003)
    hipfort_add_test(rocsolver rocsolver_dlatrd f2008)
    hipfort_add_test(rocsolver rocsolver_dsytrd f2003)
    hipfort_add_test(rocsolver rocsolver_dsytrd f2008)
    hipfort_add_test(rocsolver rocsolver_dlarft f2003)
    hipfort_add_test(rocsolver rocsolver_dlarft f2008)
    hipfort_add_test(rocsolver rocsolver_dtrtri f2003)
    hipfort_add_test(rocsolver rocsolver_dtrtri f2008)
    hipfort_add_test(rocsolver rocsolver_dposv f2003)
    hipfort_add_test(rocsolver rocsolver_dposv f2008)
    hipfort_add_test(rocsolver rocsolver_dsyev f2003)
    hipfort_add_test(rocsolver rocsolver_dsyev f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrf_batched f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrf_npvt f2008)
    hipfort_add_test(rocsolver rocsolver_dgetf2_npvt f2008)
    hipfort_add_test(rocsolver rocsolver_dgetri_npvt f2008)
    hipfort_add_test(rocsolver rocsolver_dsytrf f2003)
    hipfort_add_test(rocsolver rocsolver_dsytrf f2008)
    hipfort_add_test(rocsolver rocsolver_ssytrf f2003)
    hipfort_add_test(rocsolver rocsolver_ssytrf f2008)
    hipfort_add_test(rocsolver rocsolver_csytrf f2003)
    hipfort_add_test(rocsolver rocsolver_csytrf f2008)
    hipfort_add_test(rocsolver rocsolver_zsytrf f2003)
    hipfort_add_test(rocsolver rocsolver_zsytrf f2008)
    hipfort_add_test(rocsolver rocsolver_dsytrs f2003)
    hipfort_add_test(rocsolver rocsolver_dsytrs f2008)
    hipfort_add_test(rocsolver rocsolver_ssytrs f2003)
    hipfort_add_test(rocsolver rocsolver_ssytrs f2008)
    hipfort_add_test(rocsolver rocsolver_csytrs f2003)
    hipfort_add_test(rocsolver rocsolver_csytrs f2008)
    hipfort_add_test(rocsolver rocsolver_zsytrs f2003)
    hipfort_add_test(rocsolver rocsolver_zsytrs f2008)
    hipfort_add_test(rocsolver rocsolver_dsytf2 f2008)
    hipfort_add_test(rocsolver rocsolver_dsteqr f2008)
    hipfort_add_test(rocsolver rocsolver_dstedc f2008)
    hipfort_add_test(rocsolver rocsolver_dgetrf_64 f2008)
    hipfort_add_test(rocsolver rocsolver_dgetf2_64 f2008)
    hipfort_add_test(rocsolver rocsolver_dpotrf_64 f2008)
    hipfort_add_test(rocsolver rocsolver_dpotf2_64 f2008)
    hipfort_add_test(rocsolver rocsolver_dgetf2 f2008)
    hipfort_add_test(rocsolver rocsolver_dpotf2 f2008)
    hipfort_add_test(rocsolver rocsolver_dpotri f2008)
    hipfort_add_test(rocsolver rocsolver_zheev f2008)
    # #411 checklist: gels, syevj/heevj, gesvdj, gebrd, orgqr/ungqr, ormqr/unmqr
    hipfort_add_test(rocsolver rocsolver_sgels f2003)
    hipfort_add_test(rocsolver rocsolver_sgels f2008)
    hipfort_add_test(rocsolver rocsolver_dgels f2003)
    hipfort_add_test(rocsolver rocsolver_dgels f2008)
    hipfort_add_test(rocsolver rocsolver_cgels f2003)
    hipfort_add_test(rocsolver rocsolver_cgels f2008)
    hipfort_add_test(rocsolver rocsolver_zgels f2003)
    hipfort_add_test(rocsolver rocsolver_zgels f2008)
    hipfort_add_test(rocsolver rocsolver_dsyevj f2003)
    hipfort_add_test(rocsolver rocsolver_dsyevj f2008)
    hipfort_add_test(rocsolver rocsolver_ssyevj f2003)
    hipfort_add_test(rocsolver rocsolver_ssyevj f2008)
    hipfort_add_test(rocsolver rocsolver_cheevj f2003)
    hipfort_add_test(rocsolver rocsolver_cheevj f2008)
    hipfort_add_test(rocsolver rocsolver_zheevj f2003)
    hipfort_add_test(rocsolver rocsolver_zheevj f2008)
    hipfort_add_test(rocsolver rocsolver_sgesvdj f2003)
    hipfort_add_test(rocsolver rocsolver_sgesvdj f2008)
    hipfort_add_test(rocsolver rocsolver_dgesvdj f2003)
    hipfort_add_test(rocsolver rocsolver_dgesvdj f2008)
    hipfort_add_test(rocsolver rocsolver_cgesvdj f2003)
    hipfort_add_test(rocsolver rocsolver_cgesvdj f2008)
    hipfort_add_test(rocsolver rocsolver_zgesvdj f2003)
    hipfort_add_test(rocsolver rocsolver_zgesvdj f2008)
    hipfort_add_test(rocsolver rocsolver_sgebrd f2003)
    hipfort_add_test(rocsolver rocsolver_sgebrd f2008)
    hipfort_add_test(rocsolver rocsolver_dgebrd f2003)
    hipfort_add_test(rocsolver rocsolver_dgebrd f2008)
    hipfort_add_test(rocsolver rocsolver_cgebrd f2003)
    hipfort_add_test(rocsolver rocsolver_cgebrd f2008)
    hipfort_add_test(rocsolver rocsolver_zgebrd f2003)
    hipfort_add_test(rocsolver rocsolver_zgebrd f2008)
    hipfort_add_test(rocsolver rocsolver_sorgqr f2003)
    hipfort_add_test(rocsolver rocsolver_sorgqr f2008)
    hipfort_add_test(rocsolver rocsolver_dorgqr f2003)
    hipfort_add_test(rocsolver rocsolver_dorgqr f2008)
    hipfort_add_test(rocsolver rocsolver_cungqr f2003)
    hipfort_add_test(rocsolver rocsolver_cungqr f2008)
    hipfort_add_test(rocsolver rocsolver_zungqr f2003)
    hipfort_add_test(rocsolver rocsolver_zungqr f2008)
    hipfort_add_test(rocsolver rocsolver_sormqr f2003)
    hipfort_add_test(rocsolver rocsolver_sormqr f2008)
    hipfort_add_test(rocsolver rocsolver_dormqr f2003)
    hipfort_add_test(rocsolver rocsolver_dormqr f2008)
    hipfort_add_test(rocsolver rocsolver_cunmqr f2003)
    hipfort_add_test(rocsolver rocsolver_cunmqr f2008)
    hipfort_add_test(rocsolver rocsolver_zunmqr f2003)
    hipfort_add_test(rocsolver rocsolver_zunmqr f2008)
  endif()

  if(TARGET hipfort::rocsparse)
    hipfort_add_symbol_test(rocsparse)
    hipfort_add_test(rocsparse ddoti f2003)
    hipfort_add_test(rocsparse ddoti f2008)
    hipfort_add_test(rocsparse rocsparse_sgthr f2003)
    hipfort_add_test(rocsparse rocsparse_sgthr f2008)
    hipfort_add_test(rocsparse rocsparse_dgthr f2003)
    hipfort_add_test(rocsparse rocsparse_dgthr f2008)
    hipfort_add_test(rocsparse rocsparse_cgthr f2003)
    hipfort_add_test(rocsparse rocsparse_cgthr f2008)
    hipfort_add_test(rocsparse rocsparse_zgthr f2003)
    hipfort_add_test(rocsparse rocsparse_zgthr f2008)
    hipfort_add_test(rocsparse rocsparse_ssctr f2003)
    hipfort_add_test(rocsparse rocsparse_ssctr f2008)
    hipfort_add_test(rocsparse rocsparse_dsctr f2003)
    hipfort_add_test(rocsparse rocsparse_dsctr f2008)
    hipfort_add_test(rocsparse rocsparse_csctr f2003)
    hipfort_add_test(rocsparse rocsparse_csctr f2008)
    hipfort_add_test(rocsparse rocsparse_zsctr f2003)
    hipfort_add_test(rocsparse rocsparse_zsctr f2008)
    hipfort_add_test(rocsparse rocsparse_coo2csr f2003)
    hipfort_add_test(rocsparse rocsparse_coo2csr f2008)
    hipfort_add_test(rocsparse rocsparse_sgemvi f2003)
    hipfort_add_test(rocsparse rocsparse_sgemvi f2008)
    hipfort_add_test(rocsparse rocsparse_dgemvi f2003)
    hipfort_add_test(rocsparse rocsparse_dgemvi f2008)
    hipfort_add_test(rocsparse rocsparse_cgemvi f2003)
    hipfort_add_test(rocsparse rocsparse_cgemvi f2008)
    hipfort_add_test(rocsparse rocsparse_zgemvi f2003)
    hipfort_add_test(rocsparse rocsparse_zgemvi f2008)
    hipfort_add_test(rocsparse rocsparse_sbsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_sbsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_dbsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_dbsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_cbsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_cbsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_zbsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_zbsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_sgebsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_sgebsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_dgebsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_dgebsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_cgebsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_cgebsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_zgebsrmv f2003)
    hipfort_add_test(rocsparse rocsparse_zgebsrmv f2008)
    hipfort_add_test(rocsparse rocsparse_scsrilu0 f2003)
    hipfort_add_test(rocsparse rocsparse_scsrilu0 f2008)
    hipfort_add_test(rocsparse rocsparse_scsric0 f2003)
    hipfort_add_test(rocsparse rocsparse_scsric0 f2008)
    hipfort_add_test(rocsparse rocsparse_dcsrilu0 f2003)
    hipfort_add_test(rocsparse rocsparse_dcsrilu0 f2008)
    hipfort_add_test(rocsparse rocsparse_ccsrilu0 f2003)
    hipfort_add_test(rocsparse rocsparse_ccsrilu0 f2008)
    hipfort_add_test(rocsparse rocsparse_zcsrilu0 f2003)
    hipfort_add_test(rocsparse rocsparse_zcsrilu0 f2008)
    hipfort_add_test(rocsparse rocsparse_dcsric0 f2003)
    hipfort_add_test(rocsparse rocsparse_dcsric0 f2008)
    hipfort_add_test(rocsparse rocsparse_ccsric0 f2003)
    hipfort_add_test(rocsparse rocsparse_ccsric0 f2008)
    hipfort_add_test(rocsparse rocsparse_zcsric0 f2003)
    hipfort_add_test(rocsparse rocsparse_zcsric0 f2008)
    hipfort_add_test(rocsparse rocsparse_spildlt0 f2003)
    hipfort_add_test(rocsparse rocsparse_spildlt0 f2008)
    hipfort_add_test(rocsparse rocsparse_csr2coo f2008)
    hipfort_add_test(rocsparse rocsparse_sgtsv f2008)
    hipfort_add_test(rocsparse rocsparse_scsr2csc f2008)
    hipfort_add_test(rocsparse rocsparse_dcsr2csc f2008)
    hipfort_add_test(rocsparse rocsparse_ccsr2csc f2008)
    hipfort_add_test(rocsparse rocsparse_zcsr2csc f2008)
    hipfort_add_test(rocsparse rocsparse_sspmm f2008)
    hipfort_add_test(rocsparse rocsparse_dspmm f2008)
    hipfort_add_test(rocsparse rocsparse_cspmm f2008)
    hipfort_add_test(rocsparse rocsparse_zspmm f2008)
    hipfort_add_test(rocsparse rocsparse_sspmv f2008)
    hipfort_add_test(rocsparse rocsparse_dspmv f2008)
    hipfort_add_test(rocsparse rocsparse_cspmv f2008)
    hipfort_add_test(rocsparse rocsparse_zspmv f2008)
    hipfort_add_test(rocsparse rocsparse_ssddmm f2008)
    hipfort_add_test(rocsparse rocsparse_dsddmm f2008)
    hipfort_add_test(rocsparse rocsparse_csddmm f2008)
    hipfort_add_test(rocsparse rocsparse_zsddmm f2008)
    hipfort_add_test(rocsparse rocsparse_dsddmm_batched f2008)
    hipfort_add_test(rocsparse rocsparse_scsrgemm f2008)
    hipfort_add_test(rocsparse rocsparse_dcsrgemm f2008)
    hipfort_add_test(rocsparse rocsparse_ccsrgemm f2008)
    hipfort_add_test(rocsparse rocsparse_zcsrgemm f2008)
    hipfort_add_test(rocsparse rocsparse_scsrgeam f2008)
    hipfort_add_test(rocsparse rocsparse_dcsrgeam f2008)
    hipfort_add_test(rocsparse rocsparse_ccsrgeam f2008)
    hipfort_add_test(rocsparse rocsparse_zcsrgeam f2008)
    hipfort_add_test(rocsparse rocsparse_scsrgeam f2003)
    hipfort_add_test(rocsparse rocsparse_dcsrgeam f2003)
    hipfort_add_test(rocsparse rocsparse_ccsrgeam f2003)
    hipfort_add_test(rocsparse rocsparse_zcsrgeam f2003)
    hipfort_add_test(rocsparse rocsparse_ssptrsv f2008)
    hipfort_add_test(rocsparse rocsparse_dsptrsv f2008)
    hipfort_add_test(rocsparse rocsparse_csptrsv f2008)
    hipfort_add_test(rocsparse rocsparse_zsptrsv f2008)
    hipfort_add_test(rocsparse rocsparse_ssptrsm f2008)
    hipfort_add_test(rocsparse rocsparse_dsptrsm f2008)
    hipfort_add_test(rocsparse rocsparse_csptrsm f2008)
    hipfort_add_test(rocsparse rocsparse_zsptrsm f2008)
    hipfort_add_test(rocsparse zgpsv_interleaved_batch f2008)
    hipfort_add_test(rocsparse rocsparse_csr2coo f2003)
    hipfort_add_test(rocsparse rocsparse_scsr2csc f2003)
    hipfort_add_test(rocsparse rocsparse_dcsr2csc f2003)
    hipfort_add_test(rocsparse rocsparse_ccsr2csc f2003)
    hipfort_add_test(rocsparse rocsparse_zcsr2csc f2003)
    hipfort_add_test(rocsparse rocsparse_sspmm f2003)
    hipfort_add_test(rocsparse rocsparse_dspmm f2003)
    hipfort_add_test(rocsparse rocsparse_cspmm f2003)
    hipfort_add_test(rocsparse rocsparse_zspmm f2003)
    hipfort_add_test(rocsparse rocsparse_ssddmm f2003)
    hipfort_add_test(rocsparse rocsparse_dsddmm f2003)
    hipfort_add_test(rocsparse rocsparse_csddmm f2003)
    hipfort_add_test(rocsparse rocsparse_zsddmm f2003)
    hipfort_add_test(rocsparse rocsparse_sspmv f2003)
    hipfort_add_test(rocsparse rocsparse_dspmv f2003)
    hipfort_add_test(rocsparse rocsparse_cspmv f2003)
    hipfort_add_test(rocsparse rocsparse_zspmv f2003)
    hipfort_add_test(rocsparse rocsparse_scsrgemm f2003)
    hipfort_add_test(rocsparse rocsparse_dcsrgemm f2003)
    hipfort_add_test(rocsparse rocsparse_ccsrgemm f2003)
    hipfort_add_test(rocsparse rocsparse_zcsrgemm f2003)
    hipfort_add_test(rocsparse rocsparse_ssptrsv f2003)
    hipfort_add_test(rocsparse rocsparse_dsptrsv f2003)
    hipfort_add_test(rocsparse rocsparse_csptrsv f2003)
    hipfort_add_test(rocsparse rocsparse_zsptrsv f2003)
    hipfort_add_test(rocsparse rocsparse_ssptrsm f2003)
    hipfort_add_test(rocsparse rocsparse_dsptrsm f2003)
    hipfort_add_test(rocsparse rocsparse_csptrsm f2003)
    hipfort_add_test(rocsparse rocsparse_zsptrsm f2003)
  endif()

  # HIP runtime API tests: device management, streams, events, memset,
  # asynchronous copies, unified-memory hints and the module/kernel API.
  if(TARGET hipfort::hip)
    hipfort_add_symbol_test(hip)
    hipfort_add_test(hip device_management f2003)
    hipfort_add_test(hip stream f2003)
    hipfort_add_test(hip event f2003)
    hipfort_add_test(hip memset f2003)
    hipfort_add_test(hip memcpy_async f2003)
    hipfort_add_test(hip memcpy2d f2003)
    hipfort_add_test(hip memcpy2d f2008)
    hipfort_add_test(hip malloc_managed f2003)
    hipfort_add_test(hip malloc_managed f2008)
    hipfort_add_test(hip host_malloc f2003)
    hipfort_add_test(hip host_malloc f2008)
    hipfort_add_test(hip host_register f2003)
    hipfort_add_test(hip graph f2003)
    hipfort_add_test(hip graph_nodes f2003)
    hipfort_add_test(hip graph_memset_node f2003)
    hipfort_add_test(hip peer_access f2003)
    hipfort_add_test(hip graph_empty_node f2003)
    hipfort_add_test(hip stream_flags f2003)
    hipfort_add_test(hip stream_callback f2003)
    hipfort_add_test(hip event_timing f2003)
    hipfort_add_test(hip memory_ops f2003)
    hipfort_add_test(hip device_properties f2003)
    hipfort_add_test(hip error_version f2003)
    hipfort_add_test(hip pointer_attributes f2003)
    hipfort_add_test(hip mem_advise f2003)
    hipfort_add_test(hip virtual_memory f2003)
    hipfort_add_test(hip pointer_attributes f2008)
    hipfort_add_test(hip mem_advise f2008)

    # The hipModule* entry points need a real GPU kernel, so this test loads a
    # standalone code object built from the existing vecadd source. They have no
    # CUDA-driver counterpart in the generated bindings, hence the AMD-only guard.
    find_package(hip QUIET PATHS ${ROCM_PATH})
    find_program(HIPFORT_HIPCC hipcc HINTS ${ROCM_PATH}/bin)
    if(HIPFORT_HIPCC AND HIP_PLATFORM STREQUAL "amd")
      # --offload-arch=native and `rocm_agent_enumerator -name` both append the
      # :xnack suffix, which pins the code object to one XNACK mode and makes
      # hipModuleLoad fail in the other. The bare gfxNNN loads under both.
      set(_hipfort_arch "native")
      find_program(HIPFORT_AGENT_ENUM rocm_agent_enumerator
                   HINTS ${ROCM_PATH}/bin)
      if(HIPFORT_AGENT_ENUM)
        execute_process(COMMAND ${HIPFORT_AGENT_ENUM}
                        OUTPUT_VARIABLE _hipfort_agents
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        string(REPLACE "\n" ";" _hipfort_agents "${_hipfort_agents}")
        list(REMOVE_ITEM _hipfort_agents "gfx000")
        if(_hipfort_agents)
          list(GET _hipfort_agents 0 _hipfort_arch)
        endif()
      endif()
      set(_hipfort_code_object "${CMAKE_CURRENT_BINARY_DIR}/vecadd_kernel.co")
      add_custom_command(
        OUTPUT "${_hipfort_code_object}"
        COMMAND ${HIPFORT_HIPCC} --genco --offload-arch=${_hipfort_arch}
                "${CMAKE_CURRENT_SOURCE_DIR}/f2003/vecadd/hip_implementation.cpp"
                -o "${_hipfort_code_object}"
        DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/f2003/vecadd/hip_implementation.cpp"
        COMMENT "Building the HIP code object used by the module_kernel test")
      add_custom_target(hipfort_test_code_object DEPENDS "${_hipfort_code_object}")
      hipfort_add_test(hip module_kernel f2003)
      add_dependencies(hipfort_test_f2003_hip_module_kernel hipfort_test_code_object)
      set_tests_properties(hipfort_test_f2003_hip_module_kernel PROPERTIES
        ENVIRONMENT "HIPFORT_TEST_CODE_OBJECT=${_hipfort_code_object}")
    endif()
  endif()

  # vecadd mixes a Fortran driver with a HIP C++ kernel, so it needs the HIP
  # language enabled rather than the plain hipfort_add_test() helper.
  include(CheckLanguage)
  check_language(HIP)
  if(CMAKE_HIP_COMPILER)
    enable_language(HIP)
    foreach(std IN ITEMS f2003 f2008)
      # The f2008 interfaces are disabled on the Intel compilers, so skip the
      # f2008 vecadd test there (see USE_FPOINTER_INTERFACES in lib/CMakeLists.txt).
      if(std STREQUAL "f2008" AND CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
        continue()
      endif()
      # f2003 tests use .f03, f2008 tests use .f08 to match the target standard.
      if(std STREQUAL "f2008")
        set(ext "f08")
      else()
        set(ext "f03")
      endif()
      set(vecadd_target hipfort_test_${std}_vecadd_main)
      add_executable(${vecadd_target}
        ${std}/vecadd/main.${ext}
        ${std}/vecadd/hip_implementation.cpp)
      set_source_files_properties(${std}/vecadd/main.${ext} PROPERTIES LANGUAGE Fortran)
      set_source_files_properties(${std}/vecadd/hip_implementation.cpp PROPERTIES LANGUAGE HIP)
      target_link_libraries(${vecadd_target} PRIVATE hipfort::hip)
      set_target_properties(${vecadd_target}
        PROPERTIES
          LINKER_LANGUAGE Fortran
          POSITION_INDEPENDENT_CODE ON)
      # the tests call EXIT, which is a GNU extension in gfortran
      target_compile_options(${vecadd_target} PRIVATE $<$<COMPILE_LANG_AND_ID:Fortran,GNU>:-std=gnu>)
      add_test(NAME ${vecadd_target} COMMAND ${vecadd_target})
    endforeach()
  endif()

  # hipOccupancy* and hipLaunchCooperativeKernel take the host stub of a kernel.
  if(CMAKE_HIP_COMPILER AND TARGET hipfort::hip AND HIP_PLATFORM STREQUAL "amd")
    foreach(kernel_test IN ITEMS occupancy cooperative_launch)
      hipfort_add_test(hip ${kernel_test} f2003)
      target_sources(hipfort_test_f2003_hip_${kernel_test}
        PRIVATE f2003/vecadd/hip_implementation.cpp)
      set_source_files_properties(f2003/vecadd/hip_implementation.cpp
        PROPERTIES LANGUAGE HIP)
      set_target_properties(hipfort_test_f2003_hip_${kernel_test}
        PROPERTIES
          LINKER_LANGUAGE Fortran
          POSITION_INDEPENDENT_CODE ON)
    endforeach()
  endif()

  if(TARGET hipfort::roctx)
    hipfort_add_symbol_test(roctx)
    include(CheckLanguage)
    check_language(HIP)
    if(CMAKE_HIP_COMPILER)
      enable_language(HIP)
      hipfort_add_test(roctx main f2003)
      target_sources(hipfort_test_f2003_roctx_main PRIVATE f2003/roctx/hip_implementation.cpp)
      set_source_files_properties(f2003/roctx/hip_implementation.cpp
        PROPERTIES
          LANGUAGE HIP
      )
      set_target_properties(hipfort_test_f2003_roctx_main
        PROPERTIES
          LINKER_LANGUAGE Fortran
          POSITION_INDEPENDENT_CODE ON
      )
    endif()
  endif()

  # Regression test for SWDEV-427498: installing hipfort and calling
  # find_package(hipfort) from the install prefix must succeed. This guards the
  # multitoolchain-layout shim (lib/cmake/hipfort forwarding to
  # lib/fortran/<compiler>/cmake/hipfort) and the flat-layout config alike.
  add_test(NAME hipfort_find_package_install
    COMMAND ${CMAKE_COMMAND}
      -DHIPFORT_BUILD_DIR=${CMAKE_BINARY_DIR}
      -DCONSUMER_SRC=${CMAKE_CURRENT_SOURCE_DIR}/find_package
      -DWORK_DIR=${CMAKE_CURRENT_BINARY_DIR}/find_package_work
      -DFORTRAN_COMPILER=${CMAKE_Fortran_COMPILER}
      -P ${CMAKE_CURRENT_SOURCE_DIR}/find_package/run_find_package_test.cmake)

  # test/openmp needs offload (LLVM Flang) and a host LAPACK for the reference,
  # so every other toolchain skips with a reason instead of failing.
  if(CMAKE_Fortran_COMPILER_ID MATCHES "LLVMFlang")
    # "native" stays xnack-agnostic; an arch pinned to one HSA_XNACK mode will
    # not load in the other.
    set(HIPFORT_OFFLOAD_ARCH "native" CACHE STRING
      "AMD GPU architecture for the OpenMP offload tests (gfxNNN, or native)")
    set(_offload_flags -fopenmp -fopenmp-version=51 -fopenmp-offload-mandatory
                       --offload-arch=${HIPFORT_OFFLOAD_ARCH})

    # Also the GPU-less guard: --offload-arch=native cannot compile without a GPU.
    include(CheckFortranSourceCompiles)
    set(CMAKE_REQUIRED_FLAGS "-fopenmp --offload-arch=${HIPFORT_OFFLOAD_ARCH}")
    check_fortran_source_compiles("
program p
integer :: i(1)
!$omp target map(tofrom: i)
i(1) = 1
!$omp end target
end program" HIPFORT_HAVE_OMP_OFFLOAD)
    unset(CMAKE_REQUIRED_FLAGS)

    find_package(LAPACK QUIET)   # zhegvd, the reference for rocsolver_zhegvdx

    if(NOT HIPFORT_HAVE_OMP_OFFLOAD)
      message(STATUS "Skipping OpenMP offload tests: ${CMAKE_Fortran_COMPILER} cannot offload to ${HIPFORT_OFFLOAD_ARCH}")
    elseif(NOT LAPACK_FOUND)
      message(STATUS "Skipping OpenMP offload tests: no host LAPACK for the reference result")
    else()
      # openmp/<library>/test_<name>.f90 builds against hipfort::<library>, so a
      # new file is picked up on the next configure with no edit here.
      file(GLOB _omp_sources CONFIGURE_DEPENDS
        "${CMAKE_CURRENT_SOURCE_DIR}/openmp/*/test_*.f90")
      foreach(_src IN LISTS _omp_sources)
        get_filename_component(_lib "${_src}" DIRECTORY)
        get_filename_component(_lib "${_lib}" NAME)
        get_filename_component(_name "${_src}" NAME_WE)
        string(REGEX REPLACE "^test_" "" _name "${_name}")
        if(NOT TARGET hipfort::${_lib})
          message(STATUS "Skipping OpenMP offload test ${_name}: no hipfort::${_lib}")
          continue()
        endif()
        add_executable(hipfort_test_openmp_${_name} "${_src}")
        target_compile_options(hipfort_test_openmp_${_name} PRIVATE ${_offload_flags})
        target_link_options(hipfort_test_openmp_${_name} PRIVATE ${_offload_flags})
        target_link_libraries(hipfort_test_openmp_${_name}
          PRIVATE hipfort::${_lib} ${LAPACK_LIBRARIES})
        set_target_properties(hipfort_test_openmp_${_name}
          PROPERTIES LINKER_LANGUAGE Fortran)
        add_test(NAME hipfort_test_openmp_${_name}
          COMMAND hipfort_test_openmp_${_name})
      endforeach()
    endif()
  endif()
  # Source-only lint. Needs bash, so not on Windows.
  if(NOT CMAKE_HOST_WIN32)
    add_test(NAME hipfort_fortran_line_length
      COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/check_line_length.sh)
  endif()
endif()
