#
# Define Incremental Testing Feature Levels
# Define Device name mappings (i.e. what comes after Kokkos:: for the ExecSpace)
#

set(KOKKOS_CUDA_FEATURE_LEVEL 999)
set(KOKKOS_CUDA_NAME Cuda)
set(KOKKOS_HIP_FEATURE_LEVEL 999)
set(KOKKOS_HIP_NAME HIP)
set(KOKKOS_HPX_FEATURE_LEVEL 999)
set(KOKKOS_HPX_NAME Experimental::HPX)
set(KOKKOS_OPENMP_FEATURE_LEVEL 999)
set(KOKKOS_OPENMP_NAME OpenMP)
set(KOKKOS_SERIAL_FEATURE_LEVEL 999)
set(KOKKOS_SERIAL_NAME Serial)
set(KOKKOS_SYCL_FEATURE_LEVEL 999)
set(KOKKOS_SYCL_NAME SYCL)
set(KOKKOS_THREADS_FEATURE_LEVEL 999)
set(KOKKOS_THREADS_NAME Threads)
set(KOKKOS_OPENACC_FEATURE_LEVEL 17)

set(KOKKOS_NEXTSILICON_FEATURE_LEVEL 5)
set(KOKKOS_NEXTSILICON_NAME Experimental::NextSilicon)

set(KOKKOS_OPENACC_NAME Experimental::OpenACC)

#
# Define the tests
#

#I will leave these alone for now because I don't need transitive dependencies on tests
kokkos_include_directories(${CMAKE_CURRENT_BINARY_DIR})
kokkos_include_directories(REQUIRED_DURING_INSTALLATION_TESTING ${CMAKE_CURRENT_SOURCE_DIR})
kokkos_include_directories(${KOKKOS_SOURCE_DIR}/core/unit_test/category_files)

set(COMPILE_ONLY_SOURCES
    TestArray.cpp
    TestCreateMirror.cpp
    TestDetectionIdiom.cpp
    TestBitManipulation.cpp
    TestHalfCommonType.cpp
    TestInterOp.cpp
    TestRangePolicyCTAD.cpp
    TestStringManipulation.cpp
    TestVersionMacros.cpp
    TestViewRank.cpp
    TestViewTypeTraits.cpp
    TestViewTypedefs.cpp
    TestTypeInfo.cpp
    TestTypeList.cpp
    TestMDRangePolicyCTAD.cpp
    TestTeamPolicyCTAD.cpp
    TestTeamPolicyCompileOnly.cpp
    TestTeamMDRangePolicyCTAD.cpp
    TestNestedReducerCTAD.cpp
    view/TestAccessorFromMemoryTraits.cpp
    view/TestBasicViewMDSpanConversion.cpp
    view/TestViewCustomization.cpp
    view/TestExtentsDatatypeConversion.cpp
    view/TestConversionFromPointer.cpp
    view/TestMemoryTraitTypes.cpp
    view/TestViewMDSpanTemplateArgumentEquivalence.cpp
    view/TestViewMDSpanTemplateArgumentTypeDefs.cpp
)

# FIXME_NEXTSILICON: TeamPolicy
if(Kokkos_ENABLE_NEXTSILICON)
  list(
    REMOVE_ITEM
    COMPILE_ONLY_SOURCES
    TestTeamPolicyCTAD.cpp
    TestTeamPolicyCompileOnly.cpp
    TestTeamMDRangePolicyCTAD.cpp
    TestViewTypedefs.cpp
    TestNestedReducerCTAD.cpp
  )
endif()

if(KOKKOS_CXX_COMPILER_ID STREQUAL "Intel")
  list(REMOVE_ITEM COMPILE_ONLY_SOURCES view/TestBasicViewMDSpanConversion.cpp)
endif()

#testing if windows.h and Kokkos_Core.hpp can be included
if(WIN32)
  list(APPEND COMPILE_ONLY_SOURCES TestWindowsInclude.cpp)
endif()

if(Kokkos_INSTALL_TESTING) # FIXME Kokkos_ and KOKKOS_ variables are out of sync
  if(Kokkos_CXX_COMPILER_ID STREQUAL "NVIDIA" AND Kokkos_CXX_HOST_COMPILER_ID STREQUAL "MSVC")
    list(REMOVE_ITEM COMPILE_ONLY_SOURCES TestTypeInfo.cpp)
  endif()
else()
  if(KOKKOS_CXX_COMPILER_ID STREQUAL "NVIDIA" AND KOKKOS_CXX_HOST_COMPILER_ID STREQUAL "MSVC")
    list(REMOVE_ITEM COMPILE_ONLY_SOURCES TestTypeInfo.cpp)
  endif()
endif()

kokkos_add_executable(CoreTestCompileOnly SOURCES TestCompileMain.cpp ${COMPILE_ONLY_SOURCES})

# Smoke tests, one per major API category
set(SMOKE_TEST_NAMES
    Abort
    Atomics
    BlockSizeDeduction
    CommonPolicyInterface
    Complex
    DeepCopy_Assignment
    ExecutionSpace
    Graph
    MDRange_a
    RangePolicy
    Reductions
    SharedAlloc
    TeamBasic
    TeamMDRange
    TeamVectorRange
    ViewAPI_a
    WorkGraph
)

foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;OpenACC;HIP;SYCL;NextSilicon)
  string(TOUPPER ${Tag} DEVICE)
  string(TOLOWER ${Tag} dir)

  if(Kokkos_ENABLE_${DEVICE})
    set(dir ${CMAKE_CURRENT_BINARY_DIR}/${dir})
    file(MAKE_DIRECTORY ${dir})
    # Needed to split this for Windows NVCC, since it ends up putting everything on the
    # command line in an intermediate compilation step even if CMake generated a response
    # file. That then exceeded the shell command line max length.
    set(${Tag}_SOURCES1A)
    foreach(
      Name
      ArrayOps
      AtomicOperations_complexdouble
      AtomicOperations_complexfloat
      AtomicOperations_double
      AtomicOperations_float
      AtomicOperations_int8
      AtomicOperations_int16
      AtomicOperations_int
      AtomicOperations_longint
      AtomicOperations_longlongint
      AtomicOperations_shared
      AtomicOperations_unsignedint
      AtomicOperations_unsignedlongint
      AtomicViews
      BadAlloc
      BitManipulationBuiltins
      CheckedIntegerOps
      CommonPolicyConstructors
      Concepts
      Crs
      DeepCopy_Narrowing
      DeepCopy_SameArgument
      DeepCopyAlignment
      ExecSpacePartitioning
      ExecSpaceThreadSafety
      FunctionAnnotationMacros
      FunctorAnalysis
      GraphNodeCtorProps
      HostSharedPtr
      HostSharedPtrAccessOnDevice
      JoinBackwardCompatibility
      LocalDeepCopy
      MathematicalConstants
      MathematicalFunctions1
      MathematicalFunctions2
      MathematicalFunctions3
      MathematicalSpecialFunctions
    )
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES1A ${file})
    endforeach()

    set(${Tag}_SOURCES1B)
    set(${Tag}_TESTNAMES1B
        MDRange_b
        MDRange_c
        MDRange_d
        MDRange_e
        MDRange_f
        MDRange_g
        MDRangePolicyConstructors
        MDRangeReduce
        MDSpan
        MDSpanAtomicAccessor
        MDSpanConversion
        MinMaxClamp
        NumericTraits
        OccupancyControlTrait
        Other
        ParallelScanRangePolicy
        CustomScalarParallelScan
        Printf
        QuadPrecisionMath
        RangePolicyConstructors
        RangePolicyRequire
        ReducerCTADs
        Reducers_a
        Reducers_b
        Reducers_c
        Reducers_d
        Reducers_e
        Reductions_DeviceView
        SpaceAwareAccessorAccessViolation
        SpaceAwareAccessor
        Swap
    )
    # This test case causes MSVC to fail with "number of sections exceeded object file format limit"
    if(MSVC)
      list(REMOVE_ITEM ${Tag}_TESTNAMES1B Reducers_d)
    endif()
    foreach(Name IN LISTS ${Tag}_TESTNAMES1B)
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES1B ${file})
    endforeach()

    # Add additional test(s) from subdirectory range_policy
    set(file ${dir}/Test${Tag}_RangePolicyExecutionTypes.cpp)
    file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n"
                                "#include <range_policy/TestRangePolicyExecutionTypes.hpp>\n"
    )
    configure_file(${dir}/dummy.cpp ${file})
    list(APPEND ${Tag}_SOURCES1B ${file})

    set(${Tag}_SOURCES2A)
    set(${Tag}_TESTNAMES2A
        TeamCombinedReducers
        TeamPolicyConstructors
        TeamReductionScan
        TeamScan
        TeamScratch
        TeamTeamSize
        Timer
        UniqueToken
        View_64bit
        ViewAPI_b
        ViewAPI_c
        ViewAPI_d
        ViewAPI_e
        ViewBadAlloc
        ViewCopy_a
        ViewCopy_b
        ViewCopy_c
        ViewCtorDimMatch
        ViewCtorProp
        ViewEmptyRuntimeUnmanaged
        ViewHooks
        ViewLayoutStrideAssignment
        ViewMapping_a
        ViewMapping_b
        ViewMapping_subview
        ViewMemoryAccessViolation
        ViewMove
        ViewOfClass
        ViewOfViews
        ViewOutOfBoundsAccess
        ViewResize
        WithoutInitializing
    )
    foreach(Name IN LISTS ${Tag}_TESTNAMES2A)
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES2A ${file})
    endforeach()

    set(TagHostAccessible ${Tag})
    if(Tag STREQUAL "Cuda")
      set(TagHostAccessible CudaUVM)
    elseif(Tag STREQUAL "HIP")
      set(TagHostAccessible HIPManaged)
    elseif(Tag STREQUAL "SYCL")
      set(TagHostAccessible SYCLSharedUSM)
    endif()

    set(${Tag}_SOURCES2B)
    foreach(
      Name
      SubView_a
      SubView_b
      SubView_c01
      SubView_c02
      SubView_c03
      SubView_c04
      SubView_c05
    )
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${TagHostAccessible}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES2B ${file})
    endforeach()

    set(${Tag}_SOURCES2C)
    foreach(Name SubView_c06 SubView_c07 SubView_c08 SubView_c09)
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${TagHostAccessible}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES2C ${file})
    endforeach()

    set(${Tag}_SOURCES2D)
    foreach(
      Name
      SubView_c10
      SubView_c11
      SubView_c12
      SubView_c13
      SubView_c14
      SubView_c15
      SubView_c16
    )
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${TagHostAccessible}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_SOURCES2D ${file})
    endforeach()

    set(${Tag}_SOURCES1 ${${Tag}_SOURCES1A} ${${Tag}_SOURCES1B})
    set(${Tag}_SOURCES2 ${${Tag}_SOURCES2A} ${${Tag}_SOURCES2B} ${${Tag}_SOURCES2C} ${${Tag}_SOURCES2D})
    set(${Tag}_SOURCES ${${Tag}_SOURCES1} ${${Tag}_SOURCES2})

    # ViewSupport should eventually contain the new implementation
    # detail tests for the mdspan based View
    set(BV_TestNames
        AllocationAndSpanSize
        BasicView
        CreateMirrorViewAndCopy
        LegacyLayoutFunction
        MinimalViewMDSpanTemplateArgumentViability
        ReferenceCountedAccessor
        ReferenceCountedDataHandle
        SubviewALLFullExtentEquivalence
        ViewEqualityOperator
        ViewCtorConvertibleToPtr
        ViewCtorDataHandle
        ViewCustomizationAccessorArg
        ViewCustomizationAllocationType
        ViewCustomizationAccessorFromMapping
        ViewMDSpanTemplateArgumentSubview
    )
    # FIXME_OPENACC
    if(Kokkos_ENABLE_OPENACC)
      list(
        REMOVE_ITEM
        BV_TestNames
        ViewCustomizationAccessorArg
        ViewCustomizationAllocationType
        ViewCustomizationAccessorFromMapping
        MinimalViewMDSpanTemplateArgumentViability
        ViewMDSpanTemplateArgumentSubview
      )
    endif()
    # FIXME_NEXTSILICON
    if(Kokkos_ENABLE_NEXTSILICON)
      list(REMOVE_ITEM BV_TestNames ViewCustomizationAccessorFromMapping # TeamPolicy
      )
    endif()
    set(${Tag}_VIEWSUPPORT)
    foreach(Name IN LISTS BV_TestNames)
      set(file ${dir}/Test${Tag}_View_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n" "#include <view/Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${Tag}_VIEWSUPPORT ${file})
    endforeach()

    kokkos_add_executable_and_test(CoreUnitTest_${Tag}_ViewSupport SOURCES UnitTestMainInit.cpp ${${Tag}_VIEWSUPPORT})
    # Smoke test: minimal subset for quick iteration (generate sources not built with main targets).
    foreach(Name IN LISTS SMOKE_TEST_NAMES)
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      file(WRITE ${dir}/dummy.cpp "#include <Test${Tag}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
    endforeach()
    set(${Tag}_SOURCES_SMOKE)
    foreach(Name IN LISTS SMOKE_TEST_NAMES)
      set(file ${dir}/Test${Tag}_${Name}.cpp)
      list(APPEND ${Tag}_SOURCES_SMOKE ${file})
    endforeach()
    # Fails for the OpenACC backend if 24.5 < NVHPC version < 26.5
    if(Tag STREQUAL "Serial" AND (Kokkos_ENABLE_OPENACC AND KOKKOS_CXX_COMPILER_VERSION VERSION_GREATER 24.5
                                  AND KOKKOS_CXX_COMPILER_VERSION VERSION_LESS 26.5)
    )
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_Graph.cpp)
    endif()
    # WorkGraph is not supported for SYCL in unit tests (historically excluded from CoreUnitTest_SYCL2A).
    if(Tag STREQUAL "SYCL")
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_WorkGraph.cpp)
    endif()
    # Same as OpenACC_SOURCES (WorkGraph removed from the main OpenACC unit-test bundle).
    if(Tag STREQUAL "OpenACC")
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_WorkGraph.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamBasic.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamMDRange.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamVectorRange.cpp)
    endif()
    if((Tag STREQUAL "Serial") AND Kokkos_ENABLE_NEXTSILICON)
      #FIXME_NEXTSILICON: requires TeamPolicy parallel_for on NextSilicon
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_DeepCopy_Assignment.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_Graph.cpp)
      #FIXME_NEXTSILICON: requires TeamPolicy parallel_reduce on NextSilicon
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_CommonPolicyInterface.cpp)
    endif()
    if(Tag STREQUAL "NextSilicon")
      #FIXME_NEXTSILICON: requires TeamPolicy parallel_for
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_BlockSizeDeduction.cpp)
      #FIXME_NEXTSILICON: requires TeamPolicy parallel_for on NextSilicon
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_DeepCopy_Assignment.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamBasic.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamMDRange.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_TeamVectorRange.cpp)
      #FIXME_NEXTSILICON: requires WorkGraphPolicy parallel_for on NextSilicon
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_WorkGraph.cpp)
      #FIXME_NEXTSILICON: requires TeamPolicy on NextSilicon
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_CommonPolicyInterface.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_Graph.cpp)
      list(REMOVE_ITEM ${Tag}_SOURCES_SMOKE ${dir}/Test${Tag}_MDRange_a.cpp)
    endif()
    kokkos_add_executable_and_test(CoreUnitTest_${Tag}_SmokeTest SOURCES UnitTestMainInit.cpp ${${Tag}_SOURCES_SMOKE})
  endif()
endforeach()

foreach(PairDeviceSpace HIP-HostPinned;HIP-Managed;Cuda-HostPinned;Cuda-UVM;SYCL-HostUSM;SYCL-SharedUSM)
  string(REGEX REPLACE "([^-]*)-(.*)" "\\1" DEVICE ${PairDeviceSpace})
  string(REGEX REPLACE "([^-]*)-(.*)" "\\2" SPACE ${PairDeviceSpace})

  string(TOUPPER ${DEVICE} UPPER_DEVICE)
  string(TOLOWER ${DEVICE} dir)

  if(Kokkos_ENABLE_${UPPER_DEVICE})
    set(dir ${CMAKE_CURRENT_BINARY_DIR}/${dir})
    file(MAKE_DIRECTORY ${dir})
    foreach(
      Name
      SharedAlloc
      ViewAPI_a
      ViewAPI_b
      ViewAPI_c
      ViewAPI_d
      ViewAPI_e
      ViewCopy_a
      ViewCopy_b
      ViewCopy_c
      ViewMapping_a
      ViewMapping_b
      ViewMapping_subview
    )
      set(file ${dir}/Test${DEVICE}${SPACE}_${Name}.cpp)
      # Write to a temporary intermediate file and call configure_file to avoid
      # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
      file(WRITE ${dir}/dummy.cpp "#include <Test${DEVICE}${SPACE}_Category.hpp>\n" "#include <Test${Name}.hpp>\n")
      configure_file(${dir}/dummy.cpp ${file})
      list(APPEND ${DEVICE}_SOURCES3 ${file})
      list(APPEND ${DEVICE}_SOURCES ${file})
    endforeach()
  endif()
endforeach()

kokkos_add_executable_and_test(
  CoreUnitTest_DefaultInstanceFencesOnFinalize SOURCES UnitTestMain.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/default/TestDefaultInstanceFencesOnFinalize.cpp
)

if(Kokkos_ENABLE_OPENACC)
  list(
    REMOVE_ITEM
    OpenACC_SOURCES
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_AtomicOperations_complexdouble.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_AtomicOperations_complexfloat.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_Crs.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_JoinBackwardCompatibility.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_LocalDeepCopy.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_Other.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamCombinedReducers.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamMDRange.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamReductionScan.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamScan.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_ViewAPI_e.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_ViewMapping_subview.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_ViewOfClass.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_WorkGraph.cpp
  )
endif()

# FIXME_OPENACC - Comment non-passing tests with the NVIDIA HPC compiler nvc++
if(KOKKOS_ENABLE_OPENACC AND KOKKOS_CXX_COMPILER_ID STREQUAL NVHPC)
  list(
    REMOVE_ITEM
    OpenACC_SOURCES
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_AtomicOperations_shared.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_BlockSizeDeduction.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_DeepCopyAlignment.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_HostSharedPtr.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_HostSharedPtrAccessOnDevice.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_MathematicalFunctions1.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_MathematicalFunctions2.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_MathematicalFunctions3.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_MDRange_f.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_NumericTraits.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_RangePolicy.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_RangePolicyRequire.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_Reducers_d.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_Reductions_DeviceView.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamBasic.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamScratch.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_TeamTeamSize.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_UniqueToken.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/openacc/TestOpenACC_ViewResize.cpp
  )
endif()

if(Kokkos_ENABLE_NEXTSILICON)
  #FIXME_NEXTSILICON: some Serial tests require operations on the default device
  list(
    REMOVE_ITEM
    Serial_SOURCES1
    #FIXME_NEXTSILICON: requires TeamPolicy<NextSilicon>
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_CommonPolicyConstructors.cpp
    #FIXME_NEXTSILICON: requires TeamPolicy parallel_for on NextSilicon
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_DeepCopy_Assignment.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_DeepCopy_Narrowing.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_Graph.cpp
    #FIXME_NEXTSILICON: requires long double support
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_MathematicalConstants.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_MathematicalFunctions1.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_MathematicalFunctions2.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_MathematicalFunctions3.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_NumericTraits.cpp
    #FIXME_NEXTSILICON requires TeamPolicy parallel_for
    ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_RangePolicyExecutionTypes.cpp
  )
endif()

if(Kokkos_ENABLE_OPENACC AND KOKKOS_CXX_COMPILER_VERSION VERSION_GREATER 24.5 AND KOKKOS_CXX_COMPILER_VERSION
                                                                                  VERSION_LESS 26.5
)
  #FIXME_OPENACC: some Serial tests fail if NVHPC version > 24.5
  list(REMOVE_ITEM Serial_SOURCES1 ${CMAKE_CURRENT_BINARY_DIR}/serial/TestSerial_Other.cpp)
endif()

if(Kokkos_ENABLE_SERIAL)
  kokkos_add_executable_and_test(CoreUnitTest_Serial1 SOURCES UnitTestMainInit.cpp ${Serial_SOURCES1})
  kokkos_add_executable_and_test(CoreUnitTest_Serial2 SOURCES UnitTestMainInit.cpp ${Serial_SOURCES2})
endif()

if(Kokkos_ENABLE_THREADS)
  kokkos_add_executable_and_test(CoreUnitTest_Threads SOURCES ${Threads_SOURCES} UnitTestMainInit.cpp)
endif()

if(Kokkos_ENABLE_OPENMP)
  kokkos_add_executable_and_test(CoreUnitTest_OpenMP SOURCES UnitTestMainInit.cpp ${OpenMP_SOURCES})
  kokkos_add_executable_and_test(CoreUnitTest_OpenMPInterOp SOURCES UnitTestMain.cpp openmp/TestOpenMP_InterOp.cpp)
endif()

if(Kokkos_ENABLE_HPX)
  kokkos_add_executable_and_test(CoreUnitTest_HPX SOURCES UnitTestMainInit.cpp ${HPX_SOURCES})
  kokkos_add_executable_and_test(CoreUnitTest_HPXInterOp SOURCES UnitTestMain.cpp hpx/TestHPX_InterOp.cpp)
  kokkos_add_executable_and_test(
    CoreUnitTest_HPX_IndependentInstances
    SOURCES
    UnitTestMainInit.cpp
    hpx/TestHPX_IndependentInstances.cpp
    hpx/TestHPX_IndependentInstancesDelayedExecution.cpp
    hpx/TestHPX_IndependentInstancesInstanceIds.cpp
    hpx/TestHPX_IndependentInstancesRefCounting.cpp
    hpx/TestHPX_IndependentInstancesSynchronization.cpp
  )
endif()

if(Kokkos_ENABLE_OPENACC)
  kokkos_add_executable_and_test(CoreUnitTest_OpenACC SOURCES UnitTestMainInit.cpp ${OpenACC_SOURCES})
endif()

if(Kokkos_ENABLE_CUDA)
  kokkos_add_executable_and_test(
    CoreUnitTest_Cuda1 SOURCES UnitTestMainInit.cpp ${Cuda_SOURCES1} cuda/TestCuda_ReducerViewSizeLimit.cpp
  )

  kokkos_add_executable_and_test(CoreUnitTest_Cuda2 SOURCES UnitTestMainInit.cpp ${Cuda_SOURCES2})

  kokkos_add_executable_and_test(
    CoreUnitTest_Cuda3
    SOURCES
    UnitTestMainInit.cpp
    cuda/TestCuda_TeamScratchStreams.cpp
    ${Cuda_SOURCES3}
    cuda/TestCuda_Spaces.cpp
    ${Cuda_SOURCES_SHAREDSPACE}
  )

  # This test seeks to make sure that `desul::ensure_cuda_lock_arrays_on_device` is called before a graph submission.
  # It is in a separate file to ensure that the test takes place in a separate compilation unit, in which this function
  # has not been called yet by Kokkos::initialize or by a preceding kernel launch.
  set(file ${CMAKE_CURRENT_BINARY_DIR}/cuda/TestCuda_GraphAtomicLocks.cpp)
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cuda/dummy.cpp "#include <TestCuda_Category.hpp>\n"
                                                        "#include <TestGraphAtomicLocks.hpp>\n"
  )
  configure_file(${CMAKE_CURRENT_BINARY_DIR}/cuda/dummy.cpp ${file})
  kokkos_add_executable_and_test(CoreUnitTest_CudaGraphAtomicLocks SOURCES UnitTestMainInit.cpp ${file})

  kokkos_add_executable_and_test(
    CoreUnitTest_CudaGraphScratch SOURCES UnitTestMainInit.cpp cuda/TestCuda_GraphScratch.cpp
  )

  kokkos_add_executable_and_test(
    CoreUnitTest_CudaLargeScratch SOURCES UnitTestMainInit.cpp cuda/TestCuda_LargeScratch.cpp
  )

  kokkos_add_executable_and_test(
    CoreUnitTest_CudaTimingBased SOURCES UnitTestMainInit.cpp cuda/TestCuda_DebugSerialExecution.cpp
    cuda/TestCuda_DebugPinUVMSpace.cpp
  )

  kokkos_add_executable_and_test(CoreUnitTest_CudaInterOpInit SOURCES UnitTestMain.cpp cuda/TestCuda_InterOp_Init.cpp)
  kokkos_add_executable_and_test(
    CoreUnitTest_CudaInterOpStreams SOURCES UnitTestMain.cpp cuda/TestCuda_InterOp_Streams.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_CudaInterOpStreamsMultiGPU SOURCES UnitTestMainInit.cpp cuda/TestCuda_InterOp_StreamsMultiGPU.cpp
  )

  kokkos_add_executable_and_test(
    CoreUnitTest_CudaInterOpGraph SOURCES UnitTestMainInit.cpp cuda/TestCuda_InterOp_Graph.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_CudaInterOpGraphMultiGPU SOURCES UnitTestMainInit.cpp cuda/TestCuda_InterOp_GraphMultiGPU.cpp
  )

  # This CUDA interop test is the only thing in the tree that needs CUPTI.
  #
  # FindCUDAToolkit already ran in cmake/Modules/FindTPLCUDA.cmake, and it has
  # provided CUDA::cupti since CMake 3.17. The catch is the include path:
  # cupti.h lives in extras/CUPTI/include, which is not on the normal CUDA
  # include path, and CMake only started locating it (as
  # CUDAToolkit_CUPTI_INCLUDE_DIR) and attaching it to the target in 3.24. We
  # support CMake back to 3.22, so 3.22 and 3.23 need the manual search below,
  # as does any toolkit layout CMake does not fully describe.
  # https://cmake.org/cmake/help/latest/module/FindCUDAToolkit.html#cupti
  set(KOKKOS_CUPTI_FOUND OFF)
  if(TARGET CUDA::cupti AND CUDAToolkit_CUPTI_INCLUDE_DIR)
    set(KOKKOS_CUPTI_FOUND ON)
  else()
    find_path(
      KOKKOS_CUPTI_INCLUDE_DIR
      NAMES cupti.h
      HINTS "${CUDAToolkit_ROOT}" "${CUDAToolkit_LIBRARY_ROOT}" ENV CUDA_HOME ENV CUDA_PATH
      PATH_SUFFIXES extras/CUPTI/include include
    )
    find_library(
      KOKKOS_CUPTI_LIBRARY
      NAMES cupti
      HINTS "${CUDAToolkit_ROOT}" "${CUDAToolkit_LIBRARY_ROOT}" ENV CUDA_HOME ENV CUDA_PATH
      PATH_SUFFIXES extras/CUPTI/lib64 lib64 lib
    )

    if(KOKKOS_CUPTI_INCLUDE_DIR AND KOKKOS_CUPTI_LIBRARY)
      set(KOKKOS_CUPTI_FOUND ON)
    endif()
  endif()

  if(KOKKOS_CUPTI_FOUND)
    kokkos_add_executable_and_test(
      CoreUnitTest_CudaCUPTILaunchRoute SOURCES UnitTestMainInit.cpp cuda/TestCuda_CUPTI_LaunchRoute.cpp
    )

    if(TARGET CUDA::cupti AND CUDAToolkit_CUPTI_INCLUDE_DIR)
      target_link_libraries(Kokkos_CoreUnitTest_CudaCUPTILaunchRoute PRIVATE CUDA::cupti)
    else()
      target_include_directories(Kokkos_CoreUnitTest_CudaCUPTILaunchRoute PRIVATE "${KOKKOS_CUPTI_INCLUDE_DIR}")
      target_link_libraries(Kokkos_CoreUnitTest_CudaCUPTILaunchRoute PRIVATE "${KOKKOS_CUPTI_LIBRARY}")
    endif()
  else()
    message(STATUS "CUPTI not found; skipping CUDA launch-route test")
  endif()
  unset(KOKKOS_CUPTI_FOUND)
endif()

if(Kokkos_ENABLE_HIP)
  kokkos_add_executable_and_test(
    CoreUnitTest_HIP
    SOURCES
    UnitTestMainInit.cpp
    ${HIP_SOURCES}
    hip/TestHIP_ScanUnit.cpp
    hip/TestHIP_SharedResourceLock.cpp
    hip/TestHIP_Spaces.cpp
    hip/TestHIP_Memory_Requirements.cpp
    hip/TestHIP_TeamScratchStreams.cpp
    hip/TestHIP_AsyncLauncher.cpp
    hip/TestHIP_BlocksizeDeduction.cpp
    hip/TestHIP_UnifiedMemory_ZeroMemset.cpp
  )

  set(file ${CMAKE_CURRENT_BINARY_DIR}/hip/TestHIP_GraphAtomicLocks.cpp)
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/hip/dummy.cpp "#include <TestHIP_Category.hpp>\n"
                                                       "#include <TestGraphAtomicLocks.hpp>\n"
  )
  configure_file(${CMAKE_CURRENT_BINARY_DIR}/hip/dummy.cpp ${file})
  kokkos_add_executable_and_test(CoreUnitTest_HIPGraphAtomicLocks SOURCES UnitTestMainInit.cpp ${file})

  kokkos_add_executable_and_test(CoreUnitTest_HIPInterOpInit SOURCES UnitTestMain.cpp hip/TestHIP_InterOp_Init.cpp)
  kokkos_add_executable_and_test(
    CoreUnitTest_HIPInterOpStreams SOURCES UnitTestMain.cpp hip/TestHIP_InterOp_Streams.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_HIPInterOpGraph SOURCES UnitTestMainInit.cpp hip/TestHIP_InterOp_Graph.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_HIPInterOpStreamsMultiGPU SOURCES UnitTestMainInit.cpp hip/TestHIP_InterOp_StreamsMultiGPU.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_HIPInterOpGraphMultiGPU SOURCES UnitTestMainInit.cpp hip/TestHIP_InterOp_GraphMultiGPU.cpp
  )
endif()

if(Kokkos_ENABLE_SYCL)
  kokkos_add_executable_and_test(CoreUnitTest_SYCL1A SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES1A})

  kokkos_add_executable_and_test(CoreUnitTest_SYCL1B SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES1B})

  kokkos_add_executable_and_test(CoreUnitTest_SYCL2A SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES2A})

  kokkos_add_executable_and_test(CoreUnitTest_SYCL2B SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES2B})

  kokkos_add_executable_and_test(CoreUnitTest_SYCL2C SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES2C})

  kokkos_add_executable_and_test(CoreUnitTest_SYCL2D SOURCES UnitTestMainInit.cpp ${SYCL_SOURCES2D})

  kokkos_add_executable_and_test(
    CoreUnitTest_SYCL3 SOURCES UnitTestMainInit.cpp sycl/TestSYCL_TeamScratchStreams.cpp ${SYCL_SOURCES3}
    sycl/TestSYCL_Spaces.cpp
  )

  kokkos_add_executable_and_test(CoreUnitTest_SYCLInterOpInit SOURCES UnitTestMain.cpp sycl/TestSYCL_InterOp_Init.cpp)
  kokkos_add_executable_and_test(
    CoreUnitTest_SYCLInterOpInit_Context SOURCES UnitTestMainInit.cpp sycl/TestSYCL_InterOp_Init_Context.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_SYCLInterOpStreams SOURCES UnitTestMain.cpp sycl/TestSYCL_InterOp_Streams.cpp
  )
  kokkos_add_executable_and_test(
    CoreUnitTest_SYCLInterOpStreamsMultiGPU SOURCES UnitTestMainInit.cpp sycl/TestSYCL_InterOp_StreamsMultiGPU.cpp
  )

  if(KOKKOS_IMPL_HAVE_SYCL_EXT_ONEAPI_GRAPH AND NOT Kokkos_ENABLE_IMPL_SYCL_OUT_OF_ORDER_QUEUES)
    kokkos_add_executable_and_test(
      CoreUnitTest_SYCLInterOpGraph SOURCES UnitTestMainInit.cpp sycl/TestSYCL_InterOp_Graph.cpp
    )
  endif()
endif()

# FIXME_NEXTSILICON: whitelist tests
if(Kokkos_ENABLE_NEXTSILICON)
  set(NextSilicon_SOURCES1A
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_complexdouble.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_complexfloat.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_double.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_float.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_int8.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_int16.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_int.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_longint.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_longlongint.cpp
      # FIXME_NEXTSILICON: TeamPolicy parallel_for
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_shared.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_unsignedint.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicOperations_unsignedlongint.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_AtomicViews.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_BadAlloc.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_BitManipulationBuiltins.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_CheckedIntegerOps.cpp
      # FIXME_NEXTSILICON: needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Concepts.cpp
      # FIXME_NEXTSILICON: needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Crs.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_DeepCopy_Narrowing.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_DeepCopy_SameArgument.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_DeepCopyAlignment.cpp
      # FIXME_NEXTSILICON: needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ExecSpacePartitioning.cpp
      # FIXME_NEXTSILICON: needs single/PerTeam
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ExecSpaceThreadSafety.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_FunctionAnnotationMacros.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_FunctorAnalysis.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_GraphNodeCtorProps.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_HostSharedPtr.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_HostSharedPtrAccessOnDevice.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_JoinBackwardCompatibility.cpp
      # FIXME_NEXTSILICON: needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_LocalDeepCopy.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MathematicalConstants.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MathematicalFunctions1.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MathematicalFunctions2.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MathematicalFunctions3.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MathematicalSpecialFunctions.cpp
  )

  set(NextSilicon_SOURCES1B
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_b.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_c.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_d.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_e.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_f.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRange_g.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRangePolicyConstructors.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDRangeReduce.cpp
  )
  set(NextSilicon_SOURCES1C
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDSpan.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDSpanAtomicAccessor.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MDSpanConversion.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_MinMaxClamp.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_NumericTraits.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ParallelScanRangePolicy.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_CustomScalarParallelScan.cpp
  )
  set(NextSilicon_SOURCES1D
      # FIXME_NEXTSILICON: Needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_OccupancyControlTrait.cpp
      # FIXME_NEXTSILICON: Needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Other.cpp
      # FIXME_NEXTSILICON: needs device printf
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Printf.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_QuadPrecisionMath.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_RangePolicyConstructors.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_RangePolicyRequire.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ReducerCTADs.cpp
      # FIXME_NEXTSILICON segfaults and ecore panics 1.3.0-120
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reducers_a.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reducers_b.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reducers_c.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reducers_d.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reducers_e.cpp
      # FIXME_NEXTSILICON: TeamPolicy parallel_reduce
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Reductions_DeviceView.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_SpaceAwareAccessorAccessViolation.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_SpaceAwareAccessor.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Swap.cpp
  )

  set(NextSilicon_SOURCES2A
      # FIXME_NEXTSILICON: needs TeamPolicy
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamCombinedReducers.cpp
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamPolicyConstructors.cpp
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamReductionScan.cpp
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamScan.cpp
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamScratch.cpp
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_TeamTeamSize.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_Timer.cpp
      # FIXME_NEXTSILICON: sign on tokens.size()
      # ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_UniqueToken.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_View_64bit.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewAPI_b.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewAPI_c.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewAPI_d.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewAPI_e.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewBadAlloc.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewCopy_a.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewCopy_b.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewCopy_c.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewCtorDimMatch.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewCtorProp.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewEmptyRuntimeUnmanaged.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewHooks.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewLayoutStrideAssignment.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewMapping_a.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewMapping_b.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewMapping_subview.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewMemoryAccessViolation.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewMove.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewOfClass.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewOfViews.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewOutOfBoundsAccess.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_ViewResize.cpp
      ${CMAKE_CURRENT_BINARY_DIR}/nextsilicon/TestNextSilicon_WithoutInitializing.cpp
  )

  kokkos_add_executable_and_test(CoreUnitTest_NextSilicon1A SOURCES UnitTestMainInit.cpp ${NextSilicon_SOURCES1A})
  kokkos_add_executable_and_test(CoreUnitTest_NextSilicon1B SOURCES UnitTestMainInit.cpp ${NextSilicon_SOURCES1B})
  kokkos_add_executable_and_test(CoreUnitTest_NextSilicon1C SOURCES UnitTestMainInit.cpp ${NextSilicon_SOURCES1C})
  kokkos_add_executable_and_test(CoreUnitTest_NextSilicon1D SOURCES UnitTestMainInit.cpp ${NextSilicon_SOURCES1D})
  kokkos_add_executable_and_test(CoreUnitTest_NextSilicon2A SOURCES UnitTestMainInit.cpp ${NextSilicon_SOURCES2A})
  kokkos_add_executable_and_test(
    CoreUnitTest_NextSiliconInitializationCallbacks SOURCES nextsilicon/TestNextSilicon_InitializationCallbacks.cpp
  )
endif()

set(DEFAULT_DEVICE_SOURCES
    UnitTestMainInit.cpp
    TestPair.cpp
    TestCStyleMemoryManagement.cpp
    TestSharedSpace.cpp
    TestSharedHostPinnedSpace.cpp
    TestCompilerMacros.cpp
    default/TestDefaultDeviceType.cpp
    default/TestDefaultDeviceType_a1.cpp
    default/TestDefaultDeviceType_b1.cpp
    default/TestDefaultDeviceType_c1.cpp
    default/TestDefaultDeviceType_a2.cpp
    default/TestDefaultDeviceType_b2.cpp
    default/TestDefaultDeviceType_c2.cpp
    default/TestDefaultDeviceType_a3.cpp
    default/TestDefaultDeviceType_b3.cpp
    default/TestDefaultDeviceType_c3.cpp
    default/TestDefaultDeviceTypeResize.cpp
    default/TestDefaultDeviceTypeViewAPI.cpp
)
# FIXME_OPENACC do not provide a MemorySpace that can be accessed from all ExecSpaces
# FIXME_SYCL clock_tic does not give the correct timings for cloc_tic
# FIXME_NEXTSILICON: may be failing due to some unintended migrations
if(KOKKOS_ENABLE_OPENACC OR KOKKOS_ENABLE_SYCL OR Kokkos_ENABLE_NEXTSILICON)
  list(REMOVE_ITEM DEFAULT_DEVICE_SOURCES TestSharedSpace.cpp)
endif()
# FIXME_OPENACC do not provide a HostPinnedMemorySpace that can be accessed from all ExecSpaces
# FIXME_NEXTSILICON: does not provide a HostPinnedMemorySpace
if(KOKKOS_ENABLE_OPENACC OR Kokkos_ENABLE_NEXTSILICON)
  list(REMOVE_ITEM DEFAULT_DEVICE_SOURCES TestSharedHostPinnedSpace.cpp)
endif()

# FIXME_NEXTSILICON: no support for TeamPolicy yet
if(KOKKOS_ENABLE_NEXTSILICON)
  list(
    REMOVE_ITEM
    DEFAULT_DEVICE_SOURCES
    default/TestDefaultDeviceType_a1.cpp
    default/TestDefaultDeviceType_b1.cpp
    default/TestDefaultDeviceType_c1.cpp
    default/TestDefaultDeviceType_a2.cpp
    default/TestDefaultDeviceType_b2.cpp
    default/TestDefaultDeviceType_c2.cpp
    default/TestDefaultDeviceType_a3.cpp
    default/TestDefaultDeviceType_b3.cpp
    default/TestDefaultDeviceType_c3.cpp
  )
endif()

# FIXME_OPENACC - Comment non-passing tests with the NVIDIA HPC compiler nvc++
if(KOKKOS_ENABLE_OPENACC AND KOKKOS_CXX_COMPILER_ID STREQUAL NVHPC)
  list(
    REMOVE_ITEM
    DEFAULT_DEVICE_SOURCES
    default/TestDefaultDeviceType_a1.cpp
    default/TestDefaultDeviceType_b1.cpp
    default/TestDefaultDeviceType_c1.cpp
    default/TestDefaultDeviceType_a2.cpp
    default/TestDefaultDeviceType_b2.cpp
    default/TestDefaultDeviceType_c2.cpp
    default/TestDefaultDeviceType_a3.cpp
    default/TestDefaultDeviceType_b3.cpp
    default/TestDefaultDeviceType_c3.cpp
    default/TestDefaultDeviceTypeResize.cpp
    default/TestDefaultDeviceTypeViewAPI.cpp
  )
endif()

# FIXME_OPENACC - Non-passing tests with the NVIDIA HPC compiler nvc++ versions
# greater than 24.5 and less than 26.5
if(Kokkos_ENABLE_OPENACC
   AND KOKKOS_CXX_COMPILER_ID STREQUAL NVHPC
   AND KOKKOS_CXX_COMPILER_VERSION VERSION_GREATER 24.5
   AND KOKKOS_CXX_COMPILER_VERSION VERSION_LESS 26.5
)
  list(REMOVE_ITEM DEFAULT_DEVICE_SOURCES default/TestDefaultDeviceType.cpp)
endif()

kokkos_add_executable_and_test(CoreUnitTest_Default SOURCES ${DEFAULT_DEVICE_SOURCES})

kokkos_add_executable_and_test(
  CoreUnitTest_InitializeFinalize
  SOURCES
  UnitTestMain.cpp
  TestExecutionEnvironmentNonInitializedOrFinalized.cpp
  TestInitializationSettings.cpp
  TestInitializeFinalize.cpp
  TestKokkosHelpCausesNormalProgramTermination.cpp
  TestLegionInitialization.cpp
  TestParseCmdLineArgsAndEnvVars.cpp
  TestPushFinalizeHook.cpp
  TestScopeGuard.cpp
)

# This test is intended for development and debugging by putting code
# into TestDefaultDeviceDevelop.cpp. By default its empty.
kokkos_add_executable_and_test(CoreUnitTest_Develop SOURCES UnitTestMainInit.cpp default/TestDefaultDeviceDevelop.cpp)

if(KOKKOS_ENABLE_TUNING)
  kokkos_add_executable_and_test(CoreUnitTest_TuningBuiltins SOURCES UnitTestMainInit.cpp tools/TestBuiltinTuners.cpp)
  kokkos_add_executable_and_test(CoreUnitTest_TuningBasics SOURCES tools/TestTuning.cpp)
  kokkos_add_executable_and_test(CoreUnitTest_CategoricalTuner SOURCES tools/TestCategoricalTuner.cpp)
endif()

set(KOKKOSP_SOURCES UnitTestMainInit.cpp tools/TestEventCorrectness.cpp tools/TestKernelNames.cpp
                    tools/TestProfilingSection.cpp tools/TestScopedRegion.cpp tools/TestWithoutInitializing.cpp
)

kokkos_add_executable_and_test(CoreUnitTest_KokkosP SOURCES ${KOKKOSP_SOURCES})

if(KOKKOS_ENABLE_LIBDL)
  kokkos_add_executable_and_test(CoreUnitTest_ToolIndependence SOURCES tools/TestIndependence.cpp)
  target_compile_definitions(Kokkos_CoreUnitTest_ToolIndependence PUBLIC KOKKOS_TOOLS_INDEPENDENT_BUILD)
  kokkos_add_test_library(kokkosprinter-tool SHARED SOURCES tools/printing-tool.cpp)

  if((NOT (Kokkos_ENABLE_CUDA AND WIN32)) AND (NOT ("${KOKKOS_CXX_COMPILER_ID}" STREQUAL "Fujitsu")))
    target_compile_features(kokkosprinter-tool PUBLIC cxx_std_14)
  endif()

  kokkos_add_test_library(kokkos-empty-profiling-tool SHARED SOURCES tools/empty-tool.cpp)

  kokkos_add_test_executable(ProfilingAllCalls tools/TestAllCalls.cpp)

  kokkos_add_test_executable(ToolsInitialization UnitTestMain.cpp tools/TestToolsInitialization.cpp)

  kokkos_add_test_executable(EmptyProfilingLibraryDeathTest UnitTestMain.cpp tools/TestEmptyProfilingLibrary.cpp)

  set(ADDRESS_REGEX "0x[0-9a-f]*")
  set(MEMSPACE_REGEX "[HC][ou][sd][ta][a-zA-Z]*")
  set(SIZE_REGEX "[0-9]*")
  set(SKIP_SCRATCH_INITIALIZATION_REGEX ".*")

  # check that loading a library with no profiling callbacks produces an error
  kokkos_add_test(
    SKIP_TRIBITS
    NAME
    ProfilingTestErrorNoCallbacks
    EXE
    EmptyProfilingLibraryDeathTest
    TOOL
    kokkos-empty-profiling-tool
  )

  # check help works via environment variable
  kokkos_add_test(
    SKIP_TRIBITS
    NAME
    ProfilingTestLibraryLoadHelp
    EXE
    ProfilingAllCalls
    TOOL
    kokkosprinter-tool
    ARGS
    --kokkos-tools-help
    PASS_REGULAR_EXPRESSION
    "kokkosp_init_library::kokkosp_print_help:Kokkos_ProfilingAllCalls::kokkosp_finalize_library::"
  )

  # check help works via direct library specification
  kokkos_add_test(
    SKIP_TRIBITS
    NAME
    ProfilingTestLibraryCmdLineHelp
    EXE
    ProfilingAllCalls
    ARGS
    --kokkos-tools-help
    --kokkos-tools-libs=$<TARGET_FILE:kokkosprinter-tool>
    PASS_REGULAR_EXPRESSION
    "kokkosp_init_library::kokkosp_print_help:Kokkos_ProfilingAllCalls::kokkosp_finalize_library::"
  )

  kokkos_add_test(
    SKIP_TRIBITS
    NAME
    ProfilingTestLibraryLoad
    EXE
    ProfilingAllCalls
    TOOL
    kokkosprinter-tool
    ARGS
    --kokkos-tools-args="-c test delimit"
    PASS_REGULAR_EXPRESSION
    "kokkosp_init_library::kokkosp_parse_args:4:Kokkos_ProfilingAllCalls:-c:test:delimit::.*::kokkosp_allocate_data:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::kokkosp_begin_parallel_for:Kokkos::View::initialization [[]source] via memset:[0-9]+:0::kokkosp_end_parallel_for:0::kokkosp_allocate_data:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:40::kokkosp_begin_parallel_for:Kokkos::View::initialization [[]destination] via memset:[0-9]+:0::kokkosp_end_parallel_for:0::kokkosp_begin_deep_copy:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::.*kokkosp_end_deep_copy::kokkosp_begin_parallel_for:parallel_for:${SIZE_REGEX}:0::kokkosp_end_parallel_for:0::kokkosp_begin_parallel_reduce:parallel_reduce:${SIZE_REGEX}:1${SKIP_SCRATCH_INITIALIZATION_REGEX}::kokkosp_end_parallel_reduce:1::kokkosp_begin_parallel_scan:parallel_scan:${SIZE_REGEX}:2::kokkosp_end_parallel_scan:2::kokkosp_push_profile_region:push_region::kokkosp_pop_profile_region::kokkosp_create_profile_section:created_section:3::kokkosp_start_profile_section:3::kokkosp_stop_profile_section:3::kokkosp_destroy_profile_section:3::kokkosp_profile_event:profiling_event::kokkosp_declare_metadata:dogs:good::kokkosp_deallocate_data:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:40::kokkosp_deallocate_data:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::kokkosp_finalize_library::"
  )

  # Above will test that leading/trailing quotes are stripped bc ctest cmd args is:
  #       "--kokkos-tools-args="-c test delimit""
  # The bracket argument syntax: [=[ and ]=] used below ensures it is treated as
  # a single argument:
  #       "--kokkos-tools-args=-c test delimit"
  #
  # https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#bracket-argument
  #
  kokkos_add_test(
    SKIP_TRIBITS
    NAME
    ProfilingTestLibraryCmdLine
    EXE
    ProfilingAllCalls
    ARGS
    [=[--kokkos-tools-args=-c test delimit]=]
    --kokkos-tools-libs=$<TARGET_FILE:kokkosprinter-tool>
    PASS_REGULAR_EXPRESSION
    "kokkosp_init_library::kokkosp_parse_args:4:Kokkos_ProfilingAllCalls:-c:test:delimit::.*::kokkosp_allocate_data:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::kokkosp_begin_parallel_for:Kokkos::View::initialization [[]source] via memset:[0-9]+:0::kokkosp_end_parallel_for:0::kokkosp_allocate_data:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:40::kokkosp_begin_parallel_for:Kokkos::View::initialization [[]destination] via memset:[0-9]+:0::kokkosp_end_parallel_for:0::kokkosp_begin_deep_copy:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::.*kokkosp_end_deep_copy::kokkosp_begin_parallel_for:parallel_for:${SIZE_REGEX}:0::kokkosp_end_parallel_for:0::kokkosp_begin_parallel_reduce:parallel_reduce:${SIZE_REGEX}:1${SKIP_SCRATCH_INITIALIZATION_REGEX}::kokkosp_end_parallel_reduce:1::kokkosp_begin_parallel_scan:parallel_scan:${SIZE_REGEX}:2::kokkosp_end_parallel_scan:2::kokkosp_push_profile_region:push_region::kokkosp_pop_profile_region::kokkosp_create_profile_section:created_section:3::kokkosp_start_profile_section:3::kokkosp_stop_profile_section:3::kokkosp_destroy_profile_section:3::kokkosp_profile_event:profiling_event::kokkosp_declare_metadata:dogs:good::kokkosp_deallocate_data:${MEMSPACE_REGEX}:destination:${ADDRESS_REGEX}:40::kokkosp_deallocate_data:${MEMSPACE_REGEX}:source:${ADDRESS_REGEX}:40::kokkosp_finalize_library::"
  )
endif() #KOKKOS_ENABLE_LIBDL
kokkos_add_test_executable(
  StackTraceTestExec
  SOURCES
  TestStackTrace.cpp
  TestStackTrace_f0.cpp
  TestStackTrace_f1.cpp
  TestStackTrace_f2.cpp
  TestStackTrace_f3.cpp
  TestStackTrace_f4.cpp
)
# We need -rdynamic on GNU platforms for the stacktrace functionality
# to work correctly with shared libraries
kokkos_set_exe_property(StackTraceTestExec ENABLE_EXPORTS ON)

kokkos_add_test(NAME CoreUnitTest_StackTraceTest EXE StackTraceTestExec FAIL_REGULAR_EXPRESSION "FAILED")

if(KOKKOS_ENABLE_HWLOC)
  kokkos_add_executable_and_test(CoreUnitTest_HWLOC SOURCES UnitTestMain.cpp TestHWLOC.cpp)
endif()

function(KOKKOS_ADD_INCREMENTAL_TEST DEVICE)
  kokkos_option(${DEVICE}_EXCLUDE_TESTS "" STRING "Incremental test exclude list")
  # Add unit test main
  set(${DEVICE}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/UnitTestMainInit.cpp)

  # Iterate over incremental tests in directory

  append_glob(INCREMENTAL_FILE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/incremental/*.hpp)

  set(DEVICE_NAME ${KOKKOS_${DEVICE}_NAME})
  foreach(CURRENT_FILE_PATH ${INCREMENTAL_FILE_LIST})
    get_filename_component(CURRENT_FILE_NAME ${CURRENT_FILE_PATH} NAME)
    string(REPLACE ".hpp" "" CURRENT_TEST_NAME ${CURRENT_FILE_NAME})
    if(NOT CURRENT_TEST_NAME IN_LIST Kokkos_${DEVICE}_EXCLUDE_TESTS)
      set(CURRENT_TEST_OUTPUT_FILENAME ${CURRENT_TEST_NAME}_${DEVICE})
      file(STRINGS ${CURRENT_FILE_PATH} CURRENT_REQUIRED_FEATURE_LINE REGEX "Kokkos_Feature_Level_Required")
      # From each test get level implementation required
      string(REGEX REPLACE ".*Kokkos_Feature_Level_Required:" "" CURRENT_REQUIRED_FEATURE_LEVEL
                           ${CURRENT_REQUIRED_FEATURE_LINE}
      )
      # Cross-reference list of dependencies with selected feature list > matching feature test files are added to test applications
      if(KOKKOS_${DEVICE}_FEATURE_LEVEL GREATER_EQUAL CURRENT_REQUIRED_FEATURE_LEVEL)
        configure_file(
          IncrementalTest.cpp.in ${CMAKE_BINARY_DIR}/core/unit_test/generated/${CURRENT_TEST_OUTPUT_FILENAME}.cpp
        )
        set(${DEVICE}_SOURCES ${${DEVICE}_SOURCES};
                              ${CMAKE_BINARY_DIR}/core/unit_test/generated/${CURRENT_TEST_OUTPUT_FILENAME}.cpp
        )
      endif()
    endif()
  endforeach()

  string(TOUPPER ${DEVICE} UC_DEVICE)

  kokkos_option(ENABLE_${UC_DEVICE} ON BOOL "ENABLE ${UC_DEVICE}")

  kokkos_add_executable_and_test(IncrementalTest_${DEVICE} SOURCES ${${DEVICE}_SOURCES})

  set(EXE_NAME ${PACKAGE_NAME}_IncrementalTest_${DEVICE})
  # Check that the target was actually created because in a TribITS build
  # where only tests marked as PERFORMANCE enabled it would not be.
  if(TARGET ${EXE_NAME})
    target_include_directories(${EXE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/incremental)
  endif()

endfunction()

foreach(DEVICE ${KOKKOS_ENABLED_DEVICES})
  kokkos_add_incremental_test(${DEVICE})
endforeach()

kokkos_add_executable_and_test(CoreUnitTest_CTestDevice SOURCES UnitTestMain.cpp TestCTestDevice.cpp)

kokkos_add_executable_and_test(
  CoreUnitTest_CMakePassCmdLineArgs SOURCES UnitTest_CMakePassCmdLineArgs.cpp ARGS "one 2 THREE"
)

kokkos_add_executable(CoreUnitTest_CMakeTriBITSCompatibility SOURCES UnitTest_CMakeTriBITSCompatibility.cpp)

kokkos_add_test(NAME CoreUnitTest_CMakeTriBITSCompatibilityWillFail EXE CoreUnitTest_CMakeTriBITSCompatibility)
set_property(TEST Kokkos_CoreUnitTest_CMakeTriBITSCompatibilityWillFail PROPERTY WILL_FAIL TRUE)

set(Kokkos_CoreUnitTest_CMakeTriBITSCompatibilityDisable_DISABLE ON)
kokkos_add_test(NAME CoreUnitTest_CMakeTriBITSCompatibilityDisable EXE CoreUnitTest_CMakeTriBITSCompatibility)

set(Kokkos_CoreUnitTest_CMakeTriBITSCompatibilityExtraArgs_EXTRA_ARGS "--kokkos-test-tribits-compatibility=1")
kokkos_add_test(NAME CoreUnitTest_CMakeTriBITSCompatibilityExtraArgs EXE CoreUnitTest_CMakeTriBITSCompatibility)

set(Kokkos_CoreUnitTest_CMakeTriBITSCompatibilityEnvironment_ENVIRONMENT "KOKKOS_TEST_TRIBITS_COMPATIBILITY=1")
kokkos_add_test(NAME CoreUnitTest_CMakeTriBITSCompatibilityEnvironment EXE CoreUnitTest_CMakeTriBITSCompatibility)

set_source_files_properties(UnitTest_DeviceAndThreads.cpp PROPERTIES LANGUAGE ${KOKKOS_COMPILE_LANGUAGE})
add_executable(Kokkos_CoreUnitTest_DeviceAndThreads UnitTest_DeviceAndThreads.cpp)
target_link_libraries(Kokkos_CoreUnitTest_DeviceAndThreads Kokkos::kokkoscore)
find_package(Python3 COMPONENTS Interpreter)
if(Python3_Interpreter_FOUND AND Python3_VERSION VERSION_GREATER_EQUAL 3.7)
  file(
    GENERATE
    OUTPUT $<TARGET_FILE_DIR:Kokkos_CoreUnitTest_DeviceAndThreads>/TestDeviceAndThreads.py
    INPUT TestDeviceAndThreads.py
    USE_SOURCE_PERMISSIONS
  )
  add_test(NAME Kokkos_CoreUnitTest_DeviceAndThreads
           COMMAND ${Python3_EXECUTABLE}
                   $<TARGET_FILE_DIR:Kokkos_CoreUnitTest_DeviceAndThreads>/TestDeviceAndThreads.py -v
  )
endif()

if(KOKKOS_ENABLE_HEADER_SELF_CONTAINMENT_TESTS AND NOT WIN32)
  add_subdirectory(headers_self_contained)
endif()
