include_directories(BEFORE
    ${PROJECT_SOURCE_DIR}/
    ${PROJECT_SOURCE_DIR}/profiler/include
)

include(googletest)

add_custom_target(tests)

function(add_test_executable TEST_NAME)
    message("adding test ${TEST_NAME}")
    set(result 1)
    if(DEFINED DTYPES)
    foreach(source IN LISTS ARGN)
        set(test 0)
        foreach(type IN LISTS DTYPES)
            if(type MATCHES "fp16")
                set(type1 "_f16")
            elseif(type MATCHES "fp32")
                set(type1 "_f32")
            elseif(type MATCHES "fp8")
                set(type1 "_f8")
            elseif(type MATCHES "bf16")
                set(type1 "_b16")
            elseif(type MATCHES "fp64")
                set(type1 "_f64")
            elseif(type MATCHES "int8")
                set(type1 "_i8")
            endif()
            if("${source}" MATCHES "${type}" OR "${source}" MATCHES "${type1}")
                #if filename matches any selected type, exit type loop and do no exclude the file from the list
                set(test 0)
                break()
            elseif((source MATCHES "fp8" OR source MATCHES "fp32" OR source MATCHES "fp64" OR source MATCHES "bf16" OR source MATCHES "int8" OR source MATCHES "fp16" OR
                source MATCHES "_f8" OR source MATCHES "_f32" OR source MATCHES "_f64" OR source MATCHES "_i8" OR source MATCHES "_f16" OR source MATCHES "_b16") AND 
                NOT(source MATCHES type OR source MATCHES type1))
                    #if filename contains a type which doesn't match any selected type, mark it for removal
                    set(test 1)
            endif()
        endforeach()
        if(test EQUAL 1)
            message("removing test ${source} ")
            list(REMOVE_ITEM ARGN "${source}")
        endif()
      endforeach()
      endif()
      foreach(source IN LISTS ARGN)
        if(NOT DEFINED DL_KERNELS AND source MATCHES "_dl")
            message("removing dl test ${source} ")
            list(REMOVE_ITEM ARGN "${source}")
        endif()
    endforeach()

    #only continue if there are some source files left on the list
    if(ARGN)
        add_executable(${TEST_NAME} ${ARGN})
        add_test(NAME ${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}>)
        add_dependencies(tests ${TEST_NAME})
        add_dependencies(check ${TEST_NAME})
        rocm_install(TARGETS ${TEST_NAME} COMPONENT tests)
        set(result 0)
    endif()
    #message("add_test returns ${result}")
    return(PROPAGATE result)
endfunction(add_test_executable TEST_NAME)

include(GoogleTest)

function(add_gtest_executable TEST_NAME)
    message("adding gtest ${TEST_NAME}")
    set(result 1)
    if(DEFINED DTYPES)
    foreach(source IN LISTS ARGN)
        set(test 0)
        foreach(type IN LISTS DTYPES)
            if(type MATCHES "fp16")
                set(type1 "_f16")
            elseif(type MATCHES "fp32")
                set(type1 "_f32")
            elseif(type MATCHES "fp8")
                set(type1 "_f8")
            elseif(type MATCHES "bf16")
                set(type1 "_b16")
            elseif(type MATCHES "fp64")
                set(type1 "_f64")
            elseif(type MATCHES "int8")
                set(type1 "_i8")
            endif()
            if("${source}" MATCHES "${type}" OR "${source}" MATCHES "${type1}")
                #if filename matches any selected type, exit type loop and do no exclude the file from the list
                set(test 0)
                break()
            elseif((source MATCHES "fp8" OR source MATCHES "fp32" OR source MATCHES "fp64" OR source MATCHES "bf16" OR source MATCHES "int8" OR source MATCHES "fp16" OR
                source MATCHES "_f8" OR source MATCHES "_f32" OR source MATCHES "_f64" OR source MATCHES "_i8" OR source MATCHES "_f16" OR source MATCHES "_b16") AND 
                NOT(source MATCHES type OR source MATCHES type1))
                    #if filename contains a type which doesn't match any selected type, mark it for removal
                    set(test 1)
            endif()
        endforeach()
        if(test EQUAL 1)
            message("removing gtest ${source} ")
            list(REMOVE_ITEM ARGN "${source}")
        endif()
    endforeach()
    endif()
    foreach(source IN LISTS ARGN)
        if(NOT DEFINED DL_KERNELS AND source MATCHES "_dl")
            message("removing dl test ${source} ")
            list(REMOVE_ITEM ARGN "${source}")
        endif()
    endforeach()
    #only continue if there are some source files left on the list
    if(ARGN)
        add_executable(${TEST_NAME} ${ARGN})
        add_dependencies(tests ${TEST_NAME})
        add_dependencies(check ${TEST_NAME})

        # suppress gtest warnings
        target_compile_options(${TEST_NAME} PRIVATE -Wno-global-constructors -Wno-undef)
        target_link_libraries(${TEST_NAME} PRIVATE gtest_main)
        add_test(NAME ${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}>)
        rocm_install(TARGETS ${TEST_NAME} COMPONENT tests)
        set(result 0)
    endif()
    #message("add_gtest returns ${result}")
    return(PROPAGATE result)
endfunction(add_gtest_executable TEST_NAME)

add_subdirectory(magic_number_division)
add_subdirectory(space_filling_curve)
add_subdirectory(conv_util)
add_subdirectory(reference_conv_fwd)
add_subdirectory(gemm)
add_subdirectory(gemm_layernorm)
add_subdirectory(gemm_split_k)
add_subdirectory(gemm_reduce)
add_subdirectory(batched_gemm)
add_subdirectory(batched_gemm_reduce)
add_subdirectory(batched_gemm_gemm)
add_subdirectory(batched_gemm_softmax_gemm)
add_subdirectory(batched_gemm_softmax_gemm_permute)
add_subdirectory(grouped_gemm)
add_subdirectory(reduce)
add_subdirectory(convnd_fwd)
add_subdirectory(convnd_bwd_data)
add_subdirectory(grouped_convnd_fwd)
add_subdirectory(grouped_convnd_bwd_weight)
add_subdirectory(block_to_ctile_map)
add_subdirectory(softmax)
add_subdirectory(normalization)
add_subdirectory(data_type)
add_subdirectory(elementwise_normalization)
add_subdirectory(batchnorm)
add_subdirectory(contraction)
add_subdirectory(pool)
add_subdirectory(batched_gemm_multi_d)
add_subdirectory(grouped_convnd_bwd_data)
add_subdirectory(conv_tensor_rearrange)
add_subdirectory(work_scheduling)
if(GPU_TARGETS MATCHES "gfx11")
    add_subdirectory(wmma_op)
endif()
