diff --git a/.github/workflows/build-with-kokkos.yml b/.github/workflows/build-with-kokkos.yml index 7da5530a6..ad56034b1 100644 --- a/.github/workflows/build-with-kokkos.yml +++ b/.github/workflows/build-with-kokkos.yml @@ -71,9 +71,10 @@ jobs: exit -1 esac - - name: Install CMake, OpenMPI, PAPI and dtrace + - name: Install git, CMake, OpenMPI, PAPI and dtrace run: | apt --yes --no-install-recommends install \ + git ca-certificates \ cmake make \ libopenmpi-dev \ systemtap-sdt-dev \ diff --git a/CMakeLists.txt b/CMakeLists.txt index f2e1ba77f..45299188b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,7 @@ endif() # Tests if(KokkosTools_ENABLE_TESTS) enable_testing() + include(cmake/BuildGTest.cmake) add_subdirectory(tests) endif() diff --git a/cmake/BuildGTest.cmake b/cmake/BuildGTest.cmake new file mode 100644 index 000000000..0d16ff721 --- /dev/null +++ b/cmake/BuildGTest.cmake @@ -0,0 +1,35 @@ +# Look for Google Test and enable it as a target. +# +# The main targets that will be available are: +# * GTest::gtest +# * GTest::gmock +# +# References: +# * https://github.com/google/googletest +# * https://matgomes.com/integrate-google-test-into-cmake/ +# * https://google.github.io/googletest/quickstart-cmake.html +# * https://jeremimucha.com/2021/04/cmake-fetchcontent/ + +include(FetchContent) + +# Declare the Google Test dependency +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 +) + +# If not yet populated, add Google Test to the build with the following options: +# * disable installation of Google Test +# * enable GMock +# Note that we could have used FetchContent_MakeAvailable instead, but it would then +# use the default configuration that would install Google Test. +FetchContent_GetProperties(googletest) +if (NOT googletest_POPULATED) + FetchContent_Populate(googletest) + + set(BUILD_GMOCK ON) + set(INSTALL_GTEST OFF) + + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a5fa435c6..65ec02fe0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1,61 @@ +# Add an executable and its related test. +# +# The executable is always linked to 'kokkostools' and 'test_common'. +# +# Arguments: +# TARGET_NAME : name of the test (required) +# SOURCE_FILE : source file, defaults to .cpp (optional) +# KOKKOS_TOOLS_LIBS : the test environment will received the variable 'KOKKOS_TOOLS_LIBS' that is set as the path +# to the target file of this argument (optional) +function(kp_add_executable_and_test) + + cmake_parse_arguments(kaeat_args "" "TARGET_NAME;SOURCE_FILE;KOKKOS_TOOLS_LIBS" "" ${ARGN}) + + if(NOT DEFINED kaeat_args_TARGET_NAME) + message(FATAL_ERROR "'TARGET_NAME' is a required argument.") + endif() + + if(NOT DEFINED kaeat_args_SOURCE_FILE) + set(kaeat_args_SOURCE_FILE "${kaeat_args_TARGET_NAME}.cpp") + endif() + + add_executable(${kaeat_args_TARGET_NAME}) + + target_sources( + ${kaeat_args_TARGET_NAME} + PRIVATE + ${kaeat_args_SOURCE_FILE} + ) + target_link_libraries( + ${kaeat_args_TARGET_NAME} + PRIVATE + kokkostools test_common + ) + + add_test( + NAME ${kaeat_args_TARGET_NAME} + COMMAND $ + ) + + if(DEFINED kaeat_args_KOKKOS_TOOLS_LIBS) + set_property( + TEST ${kaeat_args_TARGET_NAME} + APPEND + PROPERTY + ENVIRONMENT "KOKKOS_TOOLS_LIBS=$" + ) + endif() + +endfunction(kp_add_executable_and_test) + +# Create a test library that contains the required Kokkos and Google Test +# initialization sequence. +add_library(test_common OBJECT) +target_sources( + test_common + PRIVATE + UnitTestMain.cpp +) +target_link_libraries(test_common PUBLIC GTest::gtest GTest::gmock Kokkos::kokkos) + add_subdirectory(space-time-stack) diff --git a/tests/UnitTestMain.cpp b/tests/UnitTestMain.cpp new file mode 100644 index 000000000..066d22adc --- /dev/null +++ b/tests/UnitTestMain.cpp @@ -0,0 +1,12 @@ +#include "gtest/gtest.h" + +#include "Kokkos_Core.hpp" + +//! Main entry point for tests. +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + + auto success = RUN_ALL_TESTS(); + + return success; +} diff --git a/tests/space-time-stack/CMakeLists.txt b/tests/space-time-stack/CMakeLists.txt index de68a5015..e16b0448c 100644 --- a/tests/space-time-stack/CMakeLists.txt +++ b/tests/space-time-stack/CMakeLists.txt @@ -1,18 +1,5 @@ -# A function to add such "simple" tests in 'tests/CMakeLists.txt' might be a good option. -add_executable(test_space_time_stack_demangling) -target_sources( - test_space_time_stack_demangling - PRIVATE - test_demangling.cpp -) -target_link_libraries( - test_space_time_stack_demangling - PRIVATE - Kokkos::kokkos kokkostools -) -add_test( - NAME test_space_time_stack_demangling - COMMAND $ - --kokkos-tools-libs=$ - --kokkos-tools-args=1e-9 +kp_add_executable_and_test( + TARGET_NAME test_space_time_stack_demangling + SOURCE_FILE test_demangling.cpp + KOKKOS_TOOLS_LIBS kp_space_time_stack ) diff --git a/tests/space-time-stack/test_demangling.cpp b/tests/space-time-stack/test_demangling.cpp index 8ed021da8..27ca95dd7 100644 --- a/tests/space-time-stack/test_demangling.cpp +++ b/tests/space-time-stack/test_demangling.cpp @@ -1,10 +1,10 @@ #include -#include #include -#include "Kokkos_Core.hpp" +#include "gmock/gmock.h" +#include "gtest/gtest.h" -#include "utils/demangle.hpp" +#include "Kokkos_Core.hpp" struct Tester { struct TagNamed {}; @@ -49,9 +49,13 @@ static const std::vector matchers{ "[0-9.e]+ sec [0-9.]+% 100.0% 0.0% ------ 1 Tester/Tester::TagUnnamed " "\\[for\\]"}; -int main(int argc, char* argv[]) { +/** + * @test This test checks that the tool effectively uses + * the demangling helpers. + */ +TEST(SpaceTimeStackTest, demangling) { //! Initialize @c Kokkos. - Kokkos::initialize(argc, argv); + Kokkos::initialize(); //! Redirect output for later analysis. std::cout.flush(); @@ -71,10 +75,6 @@ int main(int argc, char* argv[]) { //! Analyze test output. for (const auto& matcher : matchers) { - if (!std::regex_search(output.str(), std::regex(matcher))) - throw std::runtime_error("Couln't find " + matcher + " in output\n" + - output.str()); + EXPECT_THAT(output.str(), ::testing::ContainsRegex(matcher)); } - - return EXIT_SUCCESS; }