lgd_generate_sourcelists("./")
set(RELATIVE_PATH "")
include(auto.cmake)

get_filename_component(PWD ./ ABSOLUTE)
string(REPLACE "${CMAKE_SOURCE_DIR}" "" RELATIVE_PATH ${PWD})
string(REPLACE "/" _ BUFFER1 ${RELATIVE_PATH})
string(REPLACE ":" _ BUFFER2 ${BUFFER1})
set(TARGET_UNIT_TEST_EXE test_${BUFFER2})
set(TARGET_RUN_UNIT_TEST run_${BUFFER2})

get_filename_component(DIRNAME ${PWD} NAME)
string(REGEX MATCH "^parallel_hpx"    is_hpx_test    ${DIRNAME})
string(REGEX MATCH "^parallel_mpi"    is_mpi_test    ${DIRNAME})
string(REGEX MATCH "^parallel_openmp" is_openmp_test ${DIRNAME})
string(REGEX MATCH "^unit"            is_unit_test   ${DIRNAME})

# check if config enabled this test class
set(allowed_test false)
if (is_unit_test)
  set(allowed_test true)
  add_custom_target(${TARGET_RUN_UNIT_TEST} echo "running tests in..." && pwd && bash -c "${UNITEXEC} ./test")
endif()

if (is_hpx_test AND WITH_HPX)
  set(allowed_test true)
  string(REPLACE "parallel_hpx_" "" NUM_PROC "${DIRNAME}")
  string(REGEX REPLACE "_.+" "" NUM_LOCALITIES "${NUM_PROC}")
  string(REGEX REPLACE ".+_" "" NUM_THREADS    "${NUM_PROC}")

  add_custom_target(${TARGET_RUN_UNIT_TEST} echo "running tests in..." && pwd && bash -c "${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE_FLAG} ${MPIEXEC_NUMPROC_FLAG} ${NUM_LOCALITIES} ./test --hpx:bind=balanced --hpx:threads=${NUM_THREADS} -Ihpx.parcel.tcp.enable=0 -Ihpx.parcel.mpi.enable=1")
endif()

if (is_mpi_test AND WITH_MPI)
  set(allowed_test true)
  string(REPLACE "parallel_mpi_" "" NUM_PROC ${DIRNAME})
  add_custom_target(${TARGET_RUN_UNIT_TEST} echo "running tests in..." && pwd && bash -c "${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE_FLAG} ${MPIEXEC_NUMPROC_FLAG} ${NUM_PROC} ${MPIEXEC_PREFLAGS} ./test ${MPIEXEC_POSTFLAGS}")
endif()

if (is_openmp_test AND WITH_THREADS)
  set(allowed_test true)
  string(REPLACE "parallel_openmp_" "" NUM_THREADS ${DIRNAME})
  add_custom_target(${TARGET_RUN_UNIT_TEST} echo "running tests in..." && pwd && bash -c "OMP_NUM_THREADS=${NUM_THREADS} ${UNITEXEC} ./test")
endif()

# check whether LIMIT_TESTS selected this path, too
set(selected_test true)
if(LIMIT_TESTS)
  string(REGEX MATCH ${LIMIT_TESTS} selected_test ${RELATIVE_PATH})
endif()

if(allowed_test AND selected_test)
  set(SOURCES)
  unset(HAS_CUDA_TESTS)

  include_directories(${CMAKE_SOURCE_DIR}/lib/cxxtest)

  foreach(header ${HEADERS})
    # cxxtestgen for test headers...
    if(header MATCHES "test.h")
      set(IS_CUDA_TEST false)
      file(READ "${header}" buffer)

      # compilation of CUDA tests requires some tweaks:
      if(buffer MATCHES "^#include.*cuda.h")
        set(IS_CUDA_TEST true)
        set(HAS_CUDA_TESTS true)
        set(TEST_SUFFIX "test.cu")
      else()
            set(TEST_SUFFIX "test.cpp")
      endif()

      string(REPLACE "test.h" "${TEST_SUFFIX}" source "${header}")
      set(SOURCE_FULL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${source}")

      if(IS_CUDA_TEST)
        if(WITH_CUDA)
          if(CMAKE_VERSION VERSION_LESS 3.10)
            cuda_compile(GENERATED_FILES "${SOURCE_FULL_PATH}")

            list(APPEND SOURCES "${GENERATED_FILES}")
          else()
            list(APPEND SOURCES "${SOURCE_FULL_PATH}")
          endif()
        endif()
      else()
        list(APPEND SOURCES "${SOURCE_FULL_PATH}")
      endif()

      # make sure that each test source will include mpi.h first for
      # Intel MPI compliance (which is touchy if stdio.h has been
      # included beforehand).
      add_custom_command(
        OUTPUT "${SOURCE_FULL_PATH}"
        COMMAND "${CXX_TEST_DIR}/bin/cxxtestgen" -o "${CMAKE_CURRENT_SOURCE_DIR}/${source}.tmp" --part "${CMAKE_CURRENT_SOURCE_DIR}/${header}"
	COMMAND cat "${CMAKE_SOURCE_DIR}/CMakeModules/testguard.h" >"${SOURCE_FULL_PATH}"
	COMMAND cat "${CMAKE_CURRENT_SOURCE_DIR}/${source}.tmp" >>"${SOURCE_FULL_PATH}"
	COMMAND rm -f "${CMAKE_CURRENT_SOURCE_DIR}/${source}.tmp"
        DEPENDS "${header}" )
    endif()
  endforeach(header)

  # ...and main()
  list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
  list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/run_tests.cpp")
  add_custom_command(
    OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/run_tests.cpp"
    COMMAND "${CXX_TEST_DIR}/bin/cxxtestgen" -o "${CMAKE_CURRENT_SOURCE_DIR}/run_tests.cpp" --root --main run_tests --error-printer )

  # set(main_function "int run_tests(int argc, char** argv); int main(int argc, char** argv) { return run_tests(argc, argv); }")

  if(is_hpx_test)
    set(main_function "
#include <hpx/hpx_init.hpp>
#include <hpx/hpx.hpp>

int run_tests(int argc, char **argv);

int hpx_main(int argc, char **argv)
{
    int ret1 = run_tests(argc, argv);
    int ret2 = hpx::finalize();
    return ret1 || ret2;
}

int main(int argc, char **argv)
{
    // We want HPX to run hpx_main() on all localities to avoid the
    // initial overhead caused by broadcasting the work from one to
    // all other localities:
    std::vector<std::string> config(1, \"hpx.run_hpx_main!=1\");
    return hpx::init(argc, argv, config);
}
")
  endif()

  if(is_mpi_test)
    set(main_function "
#include <libgeodecomp/config.h>
#ifdef LIBGEODECOMP_WITH_MPI
#include <mpi.h>
#include <libgeodecomp/communication/typemaps.h>

int run_tests(int argc, char **argv);

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    int res = run_tests(argc, argv);
    MPI_Finalize();
    return res;
}

#endif
")
  endif()

  if(is_openmp_test)
    set(main_function "
int run_tests(int argc, char **argv);

int main(int argc, char **argv)
{
    return run_tests(argc, argv);
}
")
  endif()
  if(is_unit_test)
    set(main_function "
int run_tests(int argc, char **argv);

int main(int argc, char **argv)
{
    return run_tests(argc, argv);
}
")
  endif()


  file(WRITE "main.cpp" "${main_function}")

  if(HAS_CUDA_TESTS AND WITH_CUDA)
    lfa_cuda_add_executable(${TARGET_UNIT_TEST_EXE} EXCLUDE_FROM_ALL ${HEADERS} ${SOURCES})
  else()
    add_executable(${TARGET_UNIT_TEST_EXE} EXCLUDE_FROM_ALL ${HEADERS} ${SOURCES})
  endif()

  set_target_properties(${TARGET_UNIT_TEST_EXE} PROPERTIES OUTPUT_NAME test)
  target_link_libraries(${TARGET_UNIT_TEST_EXE} ${LOCAL_LIBGEODECOMP_LINK_LIB})

  add_dependencies(tests ${TARGET_UNIT_TEST_EXE})
  add_dependencies(check ${TARGET_RUN_UNIT_TEST})
  add_dependencies(${TARGET_RUN_UNIT_TEST} ${TARGET_UNIT_TEST_EXE})
endif()
