From 5b4c8b5dacd945dbe0e43ac6d200dd030021334e Mon Sep 17 00:00:00 2001 From: Christopher Bignamini Date: Mon, 16 Sep 2024 19:00:26 +0200 Subject: [PATCH 1/7] Example GTest created --- CMakeLists.txt | 10 + cmake/setup_GTest.cmake | 31 ++ src/clib/c_wrappers/wrap_interpolators_g.c | 60 +++ tests/CMakeLists.txt | 1 + tests/unit/CMakeLists.txt | 11 + tests/unit/test_unit_interpolators_g.cpp | 412 +++++++++++++++++++++ 6 files changed, 525 insertions(+) create mode 100644 cmake/setup_GTest.cmake create mode 100644 src/clib/c_wrappers/wrap_interpolators_g.c create mode 100644 tests/CMakeLists.txt create mode 100644 tests/unit/CMakeLists.txt create mode 100644 tests/unit/test_unit_interpolators_g.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6925b127..d8206fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,6 +184,16 @@ endif() # ----- # (this is where we will add targets for integration tests) +# Add BUILD_TESTS option available +option(BUILD_TESTS "build tests" OFF) + +# Setup GTEST if needed +if(BUILD_TESTS) + list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + include(setup_GTest) + add_subdirectory(tests) +endif() + # Packaging # --------- diff --git a/cmake/setup_GTest.cmake b/cmake/setup_GTest.cmake new file mode 100644 index 00000000..83773525 --- /dev/null +++ b/cmake/setup_GTest.cmake @@ -0,0 +1,31 @@ +find_package(GTest) + +if (NOT GTest_FOUND) + message(STATUS "Configure GTest from github") + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.13.0 + ) + + # Check if population has already been performed + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + message(STATUS "Downloading GTest from github") + # Fetch the content using previously declared details + FetchContent_Populate(googletest) + + # Prevent overriding the parent project's compiler/linker + # settings on Windows + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + # Bring the populated content into the build + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + endif() +endif() + +if (NOT TARGET GTest::gtest_main) + message("Target GTest:: stuff MISSING") +endif() diff --git a/src/clib/c_wrappers/wrap_interpolators_g.c b/src/clib/c_wrappers/wrap_interpolators_g.c new file mode 100644 index 00000000..9509fd05 --- /dev/null +++ b/src/clib/c_wrappers/wrap_interpolators_g.c @@ -0,0 +1,60 @@ +#include "grackle_macros.h" + +// TODO: FORTRAN_NAME not needed for unit tests +extern void FORTRAN_NAME(interpolate_1d_g)(double *input1, + long long *gridDim, + double *gridPar1, double *dgridPar1, + long long *dataSize, double *dataField, + double *value); + +extern void FORTRAN_NAME(interpolate_2d_g)(double *input1, double *input2, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + long long *dataSize, double *dataField, + double *value); + +extern void FORTRAN_NAME(interpolate_3d_g)(double *input1, double *input2, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + double *value); + +extern void FORTRAN_NAME(interpolate_3dz_g)(double *input1, double *input2, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, long long *index2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + int *end_int, + double *value); + +extern void FORTRAN_NAME(interpolate_2df3d_g)(double *input1, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + long long *index2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + double *value); + +extern void FORTRAN_NAME(interpolate_4d_g)(double *input1, double *input2, double *input3, double *input4, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + double *gridPar4, double *dgridPar4, + long long *dataSize, double *dataField, + double *value); + +extern void FORTRAN_NAME(interpolate_5d_g)(double *input1, double *input2, double *input3, double *input4, double *input5, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + double *gridPar4, double *dgridPar4, + double *gridPar5, double *dgridPar5, + long long *dataSize, double *dataField, + double *value); + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..269aea0c --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(unit) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 00000000..1d21b6a9 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(runInterpolationTests test_unit_interpolators_g.cpp) +target_link_libraries(runInterpolationTests Grackle_Grackle gtest gtest_main hdf5) +target_include_directories(runInterpolationTests PRIVATE ${PROJECT_SOURCE_DIR}/src/clib) + +add_test(NAME Interpolate1D COMMAND runInterpolationTests) +add_test(NAME Interpolate2D COMMAND runInterpolationTests) +add_test(NAME Interpolate3D COMMAND runInterpolationTests) +add_test(NAME Interpolate3Dz COMMAND runInterpolationTests) +add_test(NAME Interpolate2Df3D COMMAND runInterpolationTests) +add_test(NAME Interpolate4D COMMAND runInterpolationTests) +add_test(NAME Interpolate5D COMMAND runInterpolationTests) diff --git a/tests/unit/test_unit_interpolators_g.cpp b/tests/unit/test_unit_interpolators_g.cpp new file mode 100644 index 00000000..a38f360a --- /dev/null +++ b/tests/unit/test_unit_interpolators_g.cpp @@ -0,0 +1,412 @@ +#include "gtest/gtest.h" + +extern "C" { + #include "grackle_macros.h" +} + + +// TODO: FORTRAN_NAME for unit tests not needed +extern "C" void FORTRAN_NAME(interpolate_1d_g)(double *input1, + long long *gridDim, + double *gridPar1, double *dgridPar1, + long long *dataSize, double *dataField, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_2d_g)(double *input1, double *input2, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + long long *dataSize, double *dataField, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_3d_g)(double *input1, double *input2, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_3dz_g)(double *input1, double *input2, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, long long *index2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + int *end_int, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_2df3d_g)(double *input1, double *input3, + long long *gridDim, + double *gridPar1, double *dgridPar1, + long long *index2, + double *gridPar3, double *dgridPar3, + long long *dataSize, double *dataField, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_4d_g)(double *input1, double *input2, double *input3, double *input4, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + double *gridPar4, double *dgridPar4, + long long *dataSize, double *dataField, + double *value); + +extern "C" void FORTRAN_NAME(interpolate_5d_g)(double *input1, double *input2, double *input3, double *input4, double *input5, + long long *gridDim, + double *gridPar1, double *dgridPar1, + double *gridPar2, double *dgridPar2, + double *gridPar3, double *dgridPar3, + double *gridPar4, double *dgridPar4, + double *gridPar5, double *dgridPar5, + long long *dataSize, double *dataField, + double *value); + +TEST(InterpolationTest, Interpolate1D) { + + long long dataSize = 10; + double input1 = 5.0; + double dgridPar1 = 1.3; + std::vector gridDim(1,dataSize); + std::vector gridPar1(dataSize); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i gridDim = {dataSize1, dataSize2}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i gridDim = {dataSize1, dataSize2, dataSize3}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector gridPar3(dataSize3); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i gridDim = {dataSize1, dataSize2, dataSize3}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector gridPar3(dataSize3); + std::vector dataField(dataSize); + double value_end_int_0; + double value_end_int_1; + + for(auto i=0;i gridDim = {dataSize1, dataSize2, dataSize3}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector gridPar3(dataSize3); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i gridDim = {dataSize1, dataSize2, dataSize3, dataSize4}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector gridPar3(dataSize3); + std::vector gridPar4(dataSize4); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i gridDim = {dataSize1, dataSize2, dataSize3, dataSize4, dataSize5}; + std::vector gridPar1(dataSize1); + std::vector gridPar2(dataSize2); + std::vector gridPar3(dataSize3); + std::vector gridPar4(dataSize4); + std::vector gridPar5(dataSize5); + std::vector dataField(dataSize); + double value; + + for(auto i=0;i Date: Thu, 26 Sep 2024 11:55:24 +0200 Subject: [PATCH 2/7] Redundant line removed --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8206fdd..e24af7b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,7 +189,6 @@ option(BUILD_TESTS "build tests" OFF) # Setup GTEST if needed if(BUILD_TESTS) - list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") include(setup_GTest) add_subdirectory(tests) endif() From 103d541051d251dc9eff471947f06177f43d9984 Mon Sep 17 00:00:00 2001 From: ChristopherBignamini Date: Fri, 27 Sep 2024 17:53:34 +0200 Subject: [PATCH 3/7] CI config update for GTests execution --- .circleci/config.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index aa5f80d6..ddcb89c2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -310,6 +310,17 @@ jobs: build_kind: 'cmake' generate: 'false' + - run: + name: "Execute the C++ tests" + command: | + # compile the tests (it would probably would be better to do this when + # compiling the rest of Grackle) + cmake -DGRACKLE_BUILD_TESTS=ON -Bbuild + cmake --build build + # execute the tests + cd build + ctest + # TODO: once we merge in GH-#208, we need to issue a new gold standard, and then we should # issue a followup PR where we uncomment the remainder of this test test-standalone-pygrackle: From 3e7ae54efd3e6ffd1c010a509bd749370331243c Mon Sep 17 00:00:00 2001 From: ChristopherBignamini Date: Fri, 27 Sep 2024 17:55:14 +0200 Subject: [PATCH 4/7] Update to GTest zip downloading instead of cloning --- cmake/setup_GTest.cmake | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/cmake/setup_GTest.cmake b/cmake/setup_GTest.cmake index 83773525..d08f9a2c 100644 --- a/cmake/setup_GTest.cmake +++ b/cmake/setup_GTest.cmake @@ -1,29 +1,33 @@ +# This file includes logic for setting up GoogleTest find_package(GTest) if (NOT GTest_FOUND) - message(STATUS "Configure GTest from github") + message(STATUS + "Preparing to download GTest from GitHub & configure its build. Don't " + "worry about any mentions of Python in the following text -- that is " + "only used internally by the Google test build" + ) + + # NOTE: it is idiomatic to use FetchContent with a git hash rather than the + # name of a tag or branch (since the latter 2 can freely change). If we use + # the name of a tag/branch, then CMake will query GitHub on every + # subsequent build to check whether the tag/branch is still the same include(FetchContent) FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG v1.13.0 + googletest # the url contains the hash for v1.13.0 + URL https://github.com/google/googletest/archive/b796f7d44681514f58a683a3a71ff17c94edb0c1.zip ) - # Check if population has already been performed - FetchContent_GetProperties(googletest) - if(NOT googletest_POPULATED) - message(STATUS "Downloading GTest from github") - # Fetch the content using previously declared details - FetchContent_Populate(googletest) - - # Prevent overriding the parent project's compiler/linker - # settings on Windows - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(googletest) - # Bring the populated content into the build - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) - endif() +elseif("${CMAKE_VERSION}" VERSION_LESS "3.20") + # CMake's built-in `FindGTest` module imported targets have different names + # in earlier CMake versions + add_library(GTest::gtest ALIAS GTest::GTest) + add_library(GTest::gtest_main ALIAS GTest::Main) endif() if (NOT TARGET GTest::gtest_main) From 99e438b49e384f68cf1c5724c0d816c1131bf3d0 Mon Sep 17 00:00:00 2001 From: ChristopherBignamini Date: Fri, 27 Sep 2024 17:56:30 +0200 Subject: [PATCH 5/7] Automated test discovery and LINUX option issue fixed --- tests/unit/CMakeLists.txt | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 1d21b6a9..d80b7e7b 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,11 +1,17 @@ +# declare testdeps to bundle together dependencies used by all tests +# ------------------------------------------------------------------ +add_library(testdeps INTERFACE) +target_link_libraries(testdeps INTERFACE Grackle::Grackle GTest::gtest_main) + +# short-term hack to let tests invoke Fortran functions from C +target_compile_definitions(testdeps INTERFACE + "$<$:LINUX>") +target_include_directories(testdeps INTERFACE ${PROJECT_SOURCE_DIR}/src/clib) + +# start declaring targets for tests +# --------------------------------- add_executable(runInterpolationTests test_unit_interpolators_g.cpp) target_link_libraries(runInterpolationTests Grackle_Grackle gtest gtest_main hdf5) target_include_directories(runInterpolationTests PRIVATE ${PROJECT_SOURCE_DIR}/src/clib) -add_test(NAME Interpolate1D COMMAND runInterpolationTests) -add_test(NAME Interpolate2D COMMAND runInterpolationTests) -add_test(NAME Interpolate3D COMMAND runInterpolationTests) -add_test(NAME Interpolate3Dz COMMAND runInterpolationTests) -add_test(NAME Interpolate2Df3D COMMAND runInterpolationTests) -add_test(NAME Interpolate4D COMMAND runInterpolationTests) -add_test(NAME Interpolate5D COMMAND runInterpolationTests) +gtest_discover_tests(runInterpolationTests) From c084a64cf67792e2ab5222d9ec885a0a8972dd7d Mon Sep 17 00:00:00 2001 From: ChristopherBignamini Date: Fri, 27 Sep 2024 17:57:11 +0200 Subject: [PATCH 6/7] Test build flag naming updated --- CMakeLists.txt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e24af7b5..647a4795 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ endif() cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0077 NEW) cmake_policy(SET CMP0082 NEW) + project(Grackle VERSION ${_GRACKLE_VERSION_NO_DEVTAG} LANGUAGES C CXX Fortran) # Specify that `./cmake` contains cmake modules defining useful functionality @@ -185,15 +186,17 @@ endif() # (this is where we will add targets for integration tests) # Add BUILD_TESTS option available -option(BUILD_TESTS "build tests" OFF) - -# Setup GTEST if needed -if(BUILD_TESTS) - include(setup_GTest) - add_subdirectory(tests) +option(GRACKLE_BUILD_TESTS "build Grackle tests using GoogleTest" OFF) + +# if desired, setup Grackle's tests that use GoogleTest (this has no impact on +# the tests run via pytest, those are handled outside of cmake) +if(GRACKLE_BUILD_TESTS) + # load CMake's built-in module that defines functions to registering unit + # tests implemented with GoogleTest into CMake's test-runner, CTest + include(GoogleTest) + enable_testing() # enable the test-runner, CTest endif() - # Packaging # --------- # (probably not needed if not root project) From 5a06f1b912fbd8880719a8df3570ec57752acc19 Mon Sep 17 00:00:00 2001 From: ChristopherBignamini Date: Mon, 30 Sep 2024 19:53:50 +0200 Subject: [PATCH 7/7] Cmake files cleanup and comments added --- CMakeLists.txt | 17 +++++++++++++---- tests/unit/CMakeLists.txt | 6 ++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 647a4795..5ca3ea8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,11 @@ cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0077 NEW) cmake_policy(SET CMP0082 NEW) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + cmake_policy(SET CMP0135 NEW) # makes automatic dependency downloads more + # robust (& addresses noisy warnings) +endif() + project(Grackle VERSION ${_GRACKLE_VERSION_NO_DEVTAG} LANGUAGES C CXX Fortran) # Specify that `./cmake` contains cmake modules defining useful functionality @@ -191,10 +196,14 @@ option(GRACKLE_BUILD_TESTS "build Grackle tests using GoogleTest" OFF) # if desired, setup Grackle's tests that use GoogleTest (this has no impact on # the tests run via pytest, those are handled outside of cmake) if(GRACKLE_BUILD_TESTS) - # load CMake's built-in module that defines functions to registering unit - # tests implemented with GoogleTest into CMake's test-runner, CTest - include(GoogleTest) - enable_testing() # enable the test-runner, CTest + # setup GoogleTest framework (search for an installed copy on the machine + # OR download it & add its compilation to the rest of the build procedure) + include(setup_GTest) + # load CMake's built-in module that defines functions to registering unit + # tests implemented with GoogleTest into CMake's test-runner, CTest + include(GoogleTest) + enable_testing() # enable the test-runner, CTest + add_subdirectory(tests) # declare the recipes for each test endif() # Packaging diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index d80b7e7b..6f39c5d6 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -4,14 +4,12 @@ add_library(testdeps INTERFACE) target_link_libraries(testdeps INTERFACE Grackle::Grackle GTest::gtest_main) # short-term hack to let tests invoke Fortran functions from C -target_compile_definitions(testdeps INTERFACE - "$<$:LINUX>") +target_compile_definitions(testdeps INTERFACE "$<$:LINUX>") target_include_directories(testdeps INTERFACE ${PROJECT_SOURCE_DIR}/src/clib) # start declaring targets for tests # --------------------------------- add_executable(runInterpolationTests test_unit_interpolators_g.cpp) -target_link_libraries(runInterpolationTests Grackle_Grackle gtest gtest_main hdf5) -target_include_directories(runInterpolationTests PRIVATE ${PROJECT_SOURCE_DIR}/src/clib) +target_link_libraries(runInterpolationTests testdeps) gtest_discover_tests(runInterpolationTests)