cmake_minimum_required(VERSION 3.21)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    project(VifUnpackTests LANGUAGES CXX)
    include(CTest)
endif()
add_executable(vif_unpack_tests vif_unpack_tests.cpp)
target_compile_features(vif_unpack_tests PRIVATE cxx_std_17)
target_include_directories(vif_unpack_tests PRIVATE ../../ps2xRuntime/src/lib)
add_test(NAME vif_unpack.exact COMMAND vif_unpack_tests)
find_package(Threads REQUIRED)
add_executable(vu_async_tests vu_async_tests.cpp vu_async_batch_stubs.cpp ../../ps2xRuntime/src/lib/vu/ps2_vu1_async.cpp)
target_compile_features(vu_async_tests PRIVATE cxx_std_17)
target_include_directories(vu_async_tests PRIVATE mock ../../ps2xRuntime/include)
target_link_libraries(vu_async_tests PRIVATE Threads::Threads)
add_test(NAME vu_async.barriers COMMAND vu_async_tests)
set_tests_properties(vu_async.barriers PROPERTIES TIMEOUT 30)
add_executable(chain_buffers_tests ../../ps2xRuntime/tests/chain_buffers_tests.cpp)
target_compile_features(chain_buffers_tests PRIVATE cxx_std_17)
target_include_directories(chain_buffers_tests PRIVATE ../../ps2xRuntime/include)
target_link_libraries(chain_buffers_tests PRIVATE Threads::Threads)
add_test(NAME chain_buffers.pool COMMAND chain_buffers_tests)
add_executable(vu_ring_tests ../../ps2xRuntime/tests/vu_ring_tests.cpp)
target_compile_features(vu_ring_tests PRIVATE cxx_std_17)
target_include_directories(vu_ring_tests PRIVATE ../../ps2xRuntime/src/lib)
add_test(NAME vu_ring.exact COMMAND vu_ring_tests)
add_executable(vu_busy_retire_tests ../../ps2xRuntime/tests/vu_busy_retire_tests.cpp)
target_compile_features(vu_busy_retire_tests PRIVATE cxx_std_20)
target_include_directories(vu_busy_retire_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include)
add_test(NAME vu_busy_retire.exact COMMAND vu_busy_retire_tests)
add_executable(vu_stream_tests ../../ps2xRuntime/tests/vu_stream_tests.cpp)
target_compile_features(vu_stream_tests PRIVATE cxx_std_17)
target_include_directories(vu_stream_tests PRIVATE ../../ps2xRuntime/src/lib)
add_test(NAME vu_stream.exact COMMAND vu_stream_tests)
add_executable(vu_simd_tests ../../ps2xRuntime/tests/vu_simd_tests.cpp)
target_compile_features(vu_simd_tests PRIVATE cxx_std_20)
target_include_directories(vu_simd_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include)
add_test(NAME vu_simd.exact COMMAND vu_simd_tests)
add_executable(vu_lanes_tests ../../ps2xRuntime/tests/vu_lanes_tests.cpp)
target_compile_features(vu_lanes_tests PRIVATE cxx_std_20)
target_include_directories(vu_lanes_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include)
add_test(NAME vu_lanes.exact COMMAND vu_lanes_tests)
set_tests_properties(vu_lanes.exact PROPERTIES TIMEOUT 120)
# Vertex-program records of the batch path: the CPU evaluation's arithmetic against the engine's, the tracker's policy.
add_executable(vu_gpu_batch_tests ../../ps2xRuntime/tests/vu_gpu_batch_tests.cpp)
target_compile_features(vu_gpu_batch_tests PRIVATE cxx_std_20)
target_include_directories(vu_gpu_batch_tests PRIVATE ../../ps2xRuntime/src/lib ../../../runtime/gs/include)
if(NOT MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    target_compile_options(vu_gpu_batch_tests PRIVATE -msse4.1)
endif()
add_test(NAME vu_gpu_batch.exact COMMAND vu_gpu_batch_tests)
set_tests_properties(vu_gpu_batch.exact PROPERTIES TIMEOUT 120)
add_executable(vu_flag_batch_tests ../../ps2xRuntime/tests/vu_flag_batch_tests.cpp)
target_compile_features(vu_flag_batch_tests PRIVATE cxx_std_17)
target_include_directories(vu_flag_batch_tests PRIVATE ../../ps2xRuntime/src/lib)
add_test(NAME vu_flag_batch.exact COMMAND vu_flag_batch_tests)
if(TARGET ps2_runtime AND TARGET ps2_iop)
    add_executable(vu_timed_q_tests ../../ps2xRuntime/tests/vu_timed_q_tests.cpp ../src/test_function_table.cpp)
    target_compile_features(vu_timed_q_tests PRIVATE cxx_std_20)
    target_include_directories(vu_timed_q_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include ../../ps2xIOP/include)
    target_link_libraries(vu_timed_q_tests PRIVATE ps2_runtime ps2_iop)
    if(MSVC)
        target_link_options(vu_timed_q_tests PRIVATE /STACK:16777216)
    endif()
    add_test(NAME vu_timed_q.exact COMMAND vu_timed_q_tests)
    if(TARGET ps2EntryRunner)
        set_tests_properties(vu_timed_q.exact PROPERTIES WORKING_DIRECTORY "$<TARGET_FILE_DIR:ps2EntryRunner>")
    endif()
endif()

if(TARGET ps2_runtime AND TARGET ps2_iop)
    add_executable(vu_normalized_tests ../../ps2xRuntime/tests/vu_normalized_tests.cpp ../src/test_function_table.cpp)
    target_compile_features(vu_normalized_tests PRIVATE cxx_std_20)
    target_include_directories(vu_normalized_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include ../../ps2xIOP/include)
    target_link_libraries(vu_normalized_tests PRIVATE ps2_runtime ps2_iop)
    if(MSVC)
        target_link_options(vu_normalized_tests PRIVATE /STACK:16777216)
    endif()
    add_test(NAME vu_normalized.exact COMMAND vu_normalized_tests)
    if(TARGET ps2EntryRunner)
        set_tests_properties(vu_normalized.exact PROPERTIES WORKING_DIRECTORY "$<TARGET_FILE_DIR:ps2EntryRunner>")
    endif()
endif()

if(TARGET ps2_runtime AND TARGET ps2_iop)
    foreach(name IN ITEMS vu_native_loop_tests vu_normalized_lane_tests path3_async_tests vu_packet_kernel_tests vu_uv_kernel_tests vu_transform_kernel_tests vu_fmac_reference_tests)
        add_executable(${name} ../../ps2xRuntime/tests/${name}.cpp ../src/test_function_table.cpp)
        target_compile_features(${name} PRIVATE cxx_std_20)
        target_include_directories(${name} PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include ../../ps2xIOP/include)
        target_link_libraries(${name} PRIVATE ps2_runtime ps2_iop)
        if(MSVC)
            target_link_options(${name} PRIVATE /STACK:16777216)
        endif()
        add_test(NAME ${name}.exact COMMAND ${name})
        set_tests_properties(${name}.exact PROPERTIES TIMEOUT 30)
        if(TARGET ps2EntryRunner)
            set_tests_properties(${name}.exact PROPERTIES WORKING_DIRECTORY "$<TARGET_FILE_DIR:ps2EntryRunner>")
        endif()
    endforeach()
    set_tests_properties(path3_async_tests.exact PROPERTIES ENVIRONMENT "DRAKAN_RENDER_QUEUE=1;PS2X_VU1_THREAD=1")
endif()

add_executable(vu_operand_bits_tests ../../ps2xRuntime/tests/vu_operand_bits_tests.cpp)
target_compile_features(vu_operand_bits_tests PRIVATE cxx_std_20)
target_include_directories(vu_operand_bits_tests PRIVATE ../../ps2xRuntime/src/lib)
if(NOT MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    target_compile_options(vu_operand_bits_tests PRIVATE -msse4.1)
endif()
add_test(NAME vu_operand_bits.exhaustive COMMAND vu_operand_bits_tests)
set_tests_properties(vu_operand_bits.exhaustive PROPERTIES TIMEOUT 120)

# Opt-in investigation tool: requires a VUR1 recording, so it is not a CTest.
# Its parallel timing excludes serial checkpoint preparation, not a game FPS test.
if(TARGET ps2_runtime AND TARGET ps2_iop)
    add_executable(vu_parallel_replay EXCLUDE_FROM_ALL ../../ps2xRuntime/tests/vu_parallel_replay.cpp ../src/test_function_table.cpp)
    target_compile_features(vu_parallel_replay PRIVATE cxx_std_20)
    target_include_directories(vu_parallel_replay PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include ../../ps2xIOP/include)
    target_link_libraries(vu_parallel_replay PRIVATE ps2_runtime ps2_iop Threads::Threads)
    add_executable(vu_live_batch_tests EXCLUDE_FROM_ALL ../../ps2xRuntime/tests/vu_live_batch_tests.cpp ../src/test_function_table.cpp)
    target_compile_features(vu_live_batch_tests PRIVATE cxx_std_20)
    target_include_directories(vu_live_batch_tests PRIVATE ../../ps2xRuntime/src/lib ../../ps2xRuntime/include ../../ps2xIOP/include)
    target_link_libraries(vu_live_batch_tests PRIVATE ps2_runtime ps2_iop Threads::Threads)
    if(MSVC)
        target_link_options(vu_parallel_replay PRIVATE /STACK:16777216)
        target_link_options(vu_live_batch_tests PRIVATE /STACK:16777216)
    endif()
endif()
