add_subdirectory("${PROJECT_SOURCE_DIR}/googletest" "googletest")

macro(package_add_test TESTNAME)
    add_executable(${TESTNAME} ${ARGN})
    target_include_directories(${TESTNAME} PUBLIC ${CMAKE_SOURCE_DIR}/src)
    target_link_libraries(${TESTNAME} gtest gmock gtest_main)
    set_target_properties(${TESTNAME} PROPERTIES FOLDER tests)
endmacro()

macro(add_to_ctest TESTNAME)
    gtest_discover_tests(${TESTNAME}
        # set a working directory so your project root so that you can find test data via paths relative to the project root
        WORKING_DIRECTORY ${PROJECT_DIR}
        PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_DIR}"
    )
endmacro()

#####################
# GTest/GMock tests *
#####################
set(unit_test_src
    ${CMAKE_SOURCE_DIR}/src/totpuriparser.cpp
    unit_tests/totpparsertest.cpp
    ${CMAKE_SOURCE_DIR}/src/totpconverter.cpp
    unit_tests/totpconvertertest.cpp
    ${CMAKE_SOURCE_DIR}/src/randompasswordgenerator.cpp
    unit_tests/randompasswordgeneratortest.cpp
    ${CMAKE_SOURCE_DIR}/src/newtotpslotprovider.cpp
    unit_tests/newtotpslotprovidertest.cpp
    ${CMAKE_SOURCE_DIR}/src/duplicateslotexception.cpp
    ${CMAKE_SOURCE_DIR}/src/noemptyslotexception.cpp
)

#####################
# Tests on Nitrokey #
#####################
set(no_ctest_tests_src
    ${CMAKE_SOURCE_DIR}/src/authenticationexception.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeybase.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeyimpl.cpp
    against_key/nitrokeyimpltest.cpp
)

#######################
# Qt-aware unit tests #
#######################
set(nitrokeyprovidertests_src
    ${CMAKE_SOURCE_DIR}/src/authenticationexception.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeybase.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeyprovider.cpp
    ${CMAKE_SOURCE_DIR}/src/randompasswordgenerator.cpp
    qt_specific/nitrokeyprovidertest.cpp
)

set(keytotpmodeltests_src
    ${CMAKE_SOURCE_DIR}/src/authenticatedialog.cpp
    ${CMAKE_SOURCE_DIR}/src/authentication.cpp
    ${CMAKE_SOURCE_DIR}/src/connectionstate.cpp
    ${CMAKE_SOURCE_DIR}/src/duplicateslotexception.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeybase.cpp
    ${CMAKE_SOURCE_DIR}/src/keytotpmodel.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeyprovider.cpp
    ${CMAKE_SOURCE_DIR}/src/newtotpslotdialog.cpp
    ${CMAKE_SOURCE_DIR}/src/newtotpslotprovider.cpp
    ${CMAKE_SOURCE_DIR}/src/noemptyslotexception.cpp
    ${CMAKE_SOURCE_DIR}/src/randompasswordgenerator.cpp
    ${CMAKE_SOURCE_DIR}/src/totpconverter.cpp
    ${CMAKE_SOURCE_DIR}/src/totpuriparser.cpp
    ${CMAKE_SOURCE_DIR}/src/unauthenticatedexception.cpp
    qt_specific/keytotpmodeltest.cpp
)

set(authenticationtests_src
    ${CMAKE_SOURCE_DIR}/src/authenticatedialog.cpp
    ${CMAKE_SOURCE_DIR}/src/authenticationexception.cpp
    ${CMAKE_SOURCE_DIR}/src/authentication.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeybase.cpp
    ${CMAKE_SOURCE_DIR}/src/nitrokeyprovider.cpp
    ${CMAKE_SOURCE_DIR}/src/randompasswordgenerator.cpp
    ${CMAKE_SOURCE_DIR}/src/unauthenticatedexception.cpp
    qt_specific/authenticationtest.cpp
)

set(connectionstatetests_src
    ${CMAKE_SOURCE_DIR}/src/connectionstate.cpp
    qt_specific/connectionstatetest.cpp
)

# Common unit tests using GoogleTest and GoogleMock
package_add_test(tests ${unit_test_src})
add_to_ctest(tests)
target_link_libraries(tests
    ${Boost_LIBRARIES}
    Qt5::Widgets
)

# Tests that operate on actual key, so they cannot be included
# in main ctest run. Thus, no call to "add_to_ctest" macro for this
# target.
package_add_test(dont_add_to_ctest ${no_ctest_tests_src})
target_link_libraries(dont_add_to_ctest
    ${Boost_LIBRARIES}
    ${HIDAPI_LIBUSB_LDFLAGS} nitrokey
    Qt5::Widgets
)

# Unit tests using QTest -- those tests involve testing
# Qt-specific functionality, like signals and slots. They
# are part of main ctest run.
# Each test case requires a separate test executable.
macro(add_qt_specific_tests TEST_TARGET_NAME TEST_SRCS)
    add_executable(${TEST_TARGET_NAME} ${TEST_SRCS})
    target_include_directories(${TEST_TARGET_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/src)
    target_link_libraries(${TEST_TARGET_NAME}
        gtest gmock
        Qt5::Widgets
        Qt5::Test
        ${Boost_LIBRARIES}
    )
    add_test(NAME ${TEST_TARGET_NAME} COMMAND ${TEST_TARGET_NAME} --platform minimal)
endmacro()

add_qt_specific_tests(nitrokeyprovidertests "${nitrokeyprovidertests_src}")
add_qt_specific_tests(keytotpmodeltests "${keytotpmodeltests_src}")
add_qt_specific_tests(authenticationtests "${authenticationtests_src}")
add_qt_specific_tests(connectionstatetests "${connectionstatetests_src}")
