diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b1272a426438513d2d6482dd7f66752d141b6a..d7da026cedd0be42059b94cf469521ed25071c55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.18) project(fortran-support VERSION 0.1.0 LANGUAGES Fortran C) option(BUILD_SHARED_LIBS "Build shared libraries" ON) -option(BUILD_TESTING "Generate build files for unit tests" ON) +option(BUILD_TESTING "Build tests" ON) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING @@ -12,10 +12,17 @@ if(NOT CMAKE_BUILD_TYPE) endif(NOT CMAKE_BUILD_TYPE) include(GNUInstallDirs) -include(CTest) add_subdirectory(src) +include(CTest) +if(BUILD_TESTING) + add_subdirectory(test) +else() + # Allow for 'make test' even if the tests are disabled: + enable_testing() +endif() + export( EXPORT "${PROJECT_NAME}-targets" FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-targets.cmake" @@ -49,11 +56,6 @@ install( "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake" ) -if(BUILD_TESTING) - enable_testing() - add_subdirectory(test) -endif() - include("${PROJECT_SOURCE_DIR}/cmake/list_sources.cmake") # Collect source files of the project: diff --git a/cmake/gtest_helper.cmake b/cmake/gtest_helper.cmake index bcd4c731560128ff6731901eae89d4fc8cc18e45..f5a061d669923234af1fb20341a348776258e74b 100644 --- a/cmake/gtest_helper.cmake +++ b/cmake/gtest_helper.cmake @@ -1,26 +1,7 @@ macro(add_icon_c_test test_name file_name) add_executable("CTest_${test_name}" ${file_name}) - target_include_directories("CTest_${test_name}" SYSTEM AFTER PUBLIC "${PROJECT_SOURCE_DIR}/test/googletest/include" ${CMAKE_CURRENT_BINARY_DIR}) - target_link_libraries("CTest_${test_name}" PRIVATE fortran-support gtest gtest_main) + target_link_libraries("CTest_${test_name}" PRIVATE fortran-support::fortran-support GTest::gtest_main) add_test(NAME "CTest_${test_name}" COMMAND "CTest_${test_name}") - set_property(TEST "CTest_${test_name}" - PROPERTY LABELS C) -endmacro() - -macro(add_icon_fortran_test test_name file_name) - add_executable("FTest_${test_name}" ${file_name}) - target_include_directories("FTest_${test_name}" SYSTEM AFTER PUBLIC "${PROJECT_SOURCE_DIR}/test/googletest/include") - target_link_libraries("FTest_${test_name}" PRIVATE FTest_C_Binding fortran-support gtest gtest_main) - add_test(NAME "FTest_${test_name}" COMMAND "FTest_${test_name}") - set_property(TEST "FTest_${test_name}" - PROPERTY LABELS Fortran) -endmacro() - -macro(add_icon_fortran_c_test test_name file_name) - add_executable("FCTest_${test_name}" ${file_name}) - target_include_directories("FCTest_${test_name}" SYSTEM AFTER PUBLIC "${PROJECT_SOURCE_DIR}/test/googletest/include") - target_link_libraries("FCTest_${test_name}" PRIVATE FTest_C_Binding fortran-support gtest gtest_main) - add_test(NAME "FCTest_${test_name}" COMMAND "FCTest_${test_name}") - set_property(TEST "FCTest_${test_name}" - PROPERTY LABELS Fortran/C) + set_property(TEST "CTest_${test_name}" PROPERTY LABELS C) + set_target_properties("CTest_${test_name}" PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON) endmacro() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d7db70a34a31b0e56ac4a2402869d15aab2a4e6b..bedf0a39f2dd76e09c5bc7ca79e363f3a1672a8d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,16 +31,18 @@ add_library(fortran-support mo_util_timer.f90 nml_annotate.c util_arithmetic_expr.c + util_arithmetic_expr.h util_backtrace.c + util_backtrace.h util_file.c + util_file.h util_hash.c + util_hash.h util_stride.c util_string_parse.c util_sysinfo.c util_system.c util_timer.c - util_arithmetic_expr.hpp - util_backtrace.h ${CMAKE_CURRENT_BINARY_DIR}/config.h ) @@ -60,12 +62,15 @@ set_target_properties(fortran-support target_include_directories(fortran-support PUBLIC - $<BUILD_INTERFACE:${Fortran_MODULE_DIRECTORY}> - $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +# Path to the Fortran modules: + $<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:Fortran>:${Fortran_MODULE_DIRECTORY}>> + $<INSTALL_INTERFACE:$<$<COMPILE_LANGUAGE:Fortran>:${CMAKE_INSTALL_INCLUDEDIR}>> INTERFACE - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> +# Path to the internal C/C++ headers (for testing): + $<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:C,CXX>:${CMAKE_CURRENT_SOURCE_DIR}>> PRIVATE - $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> +# Path to config.h (for C and C++ only): + $<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:C,CXX>:${CMAKE_CURRENT_BINARY_DIR}>> ) install( diff --git a/src/util_arithmetic_expr.c b/src/util_arithmetic_expr.c index 01cf6b5752418ee60a921fe4b779ad61e1fae067..411944b213ea80949372e7d30b97906dd81468e0 100644 --- a/src/util_arithmetic_expr.c +++ b/src/util_arithmetic_expr.c @@ -13,7 +13,7 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include "util_arithmetic_expr.hpp" +#include "util_arithmetic_expr.h" const char* const priorities = "(;><;+-;/*;^"; const char* const left_assoc = "><+-/*^"; diff --git a/src/util_arithmetic_expr.hpp b/src/util_arithmetic_expr.h similarity index 71% rename from src/util_arithmetic_expr.hpp rename to src/util_arithmetic_expr.h index 8aa75f7f0fc0249d1c8a55f681ff435bef756562..b3f3f5df9c976827c7682e8e0f240229ab7e8cf0 100644 --- a/src/util_arithmetic_expr.hpp +++ b/src/util_arithmetic_expr.h @@ -1,5 +1,9 @@ -#ifndef UTIL_ARITHMETIC_EXPR_HPP -#define UTIL_ARITHMETIC_EXPR_HPP +#ifndef UTIL_ARITHMETIC_EXPR_H +#define UTIL_ARITHMETIC_EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif #define MAX_BUF_LEN 1024 #define NUM_FCT 9 @@ -42,4 +46,14 @@ int do_parse_infix(const char *in_parse_line, struct t_list *data); /* accessor function for function name strings */ int get_fctname(const int id, char *string); -#endif /* UTIL_ARITHMETIC_EXPR_HPP */ +/* returns the priority of an arithmetic operator */ +int priority(char op); + +/* returns the associativity of an arithmetic operator */ +int left_associative(char op); + +#ifdef __cplusplus +} +#endif + +#endif // UTIL_ARITHMETIC_EXPR_H diff --git a/src/util_arithmetic_expr.rl b/src/util_arithmetic_expr.rl index 7bbfe6a3130cc9e33879cf4db165793046650118..d2c8db6a3ce962788f6b0044b74188a5f7e8a418 100644 --- a/src/util_arithmetic_expr.rl +++ b/src/util_arithmetic_expr.rl @@ -11,7 +11,7 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include "util_arithmetic_expr.hpp" +#include "util_arithmetic_expr.h" const char* const priorities = "(;><;+-;/*;^"; const char* const left_assoc = "><+-/*^"; diff --git a/src/util_file.h b/src/util_file.h new file mode 100644 index 0000000000000000000000000000000000000000..669a60330787b5073c7af2e226cad286702a8229 --- /dev/null +++ b/src/util_file.h @@ -0,0 +1,16 @@ +#ifndef UTIL_FILE_H +#define UTIL_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +int util_islink(char *path); +long int util_filesize(char *filename); +int util_file_is_writable(char *filename); + +#ifdef __cplusplus +} +#endif + +#endif // UTIL_FILE_H diff --git a/src/util_hash.c b/src/util_hash.c index 503723ee83269797041612fd15dc3d6da2d29247..3105a8a4d3e0d97081b79f1f59818172da30cc73 100644 --- a/src/util_hash.c +++ b/src/util_hash.c @@ -88,6 +88,8 @@ #endif +#include "util_hash.h" + #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) /* diff --git a/src/util_hash.h b/src/util_hash.h new file mode 100644 index 0000000000000000000000000000000000000000..f99f18bc7c3a03d49f6b29bb6bb5066dc0819edb --- /dev/null +++ b/src/util_hash.h @@ -0,0 +1,16 @@ +#ifndef UTIL_HASH_H +#define UTIL_HASH_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t util_hashword(const void *key, size_t length, uint32_t initval); + +#ifdef __cplusplus +} +#endif + +#endif // UTIL_HASH_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b66ae958db5daa4fd502e4ac3de4832ad49437ee..6eadca6d5084a5409b41d22361a5c3f0e96bf31e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,20 +1,2 @@ -include(FetchContent) -enable_language(CXX) - -find_package(GTest 1.13) -if(NOT GTest_FOUND) - message(CHECK_START "Fetching external GTest") - if ("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.24") - cmake_policy(SET CMP0135 NEW) - endif() - FetchContent_Declare(googletest - URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz - URL_HASH MD5=95b29f0038ec84a611df951d74d99897 - ) - set(INSTALL_GTEST OFF CACHE BOOL "Do not install GTest") - FetchContent_MakeAvailable(googletest) - message(CHECK_PASS "done") -endif() - add_subdirectory(fortran) -add_subdirectory(googletest) +add_subdirectory(c) diff --git a/test/c/CMakeLists.txt b/test/c/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..953f455c2f61eaa7df56038f062cad5fecb1fdf0 --- /dev/null +++ b/test/c/CMakeLists.txt @@ -0,0 +1,39 @@ +enable_language(CXX) + +find_package(GTest 1.13) +if(NOT GTest_FOUND) + message(CHECK_START "Fetching external GTest") + if ("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.24") + cmake_policy(SET CMP0135 NEW) + endif() + include(FetchContent) + FetchContent_Declare(googletest + URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz + URL_HASH MD5=95b29f0038ec84a611df951d74d99897 + ) + set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest") + set(BUILD_GMOCK OFF CACHE BOOL "Do not build the googlemock subproject") + FetchContent_MakeAvailable(googletest) + # GTest puts its build artifacts to ${CMAKE_BINARY_DIR} instead of + # ${CMAKE_CURRENT_BINARY_DIR}. Therefore, we have to make it behave: + set_target_properties(gtest_main gtest + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${googletest_BINARY_DIR}/bin" + LIBRARY_OUTPUT_DIRECTORY "${googletest_BINARY_DIR}/lib" + ARCHIVE_OUTPUT_DIRECTORY "${googletest_BINARY_DIR}/lib" + PDB_OUTPUT_DIRECTORY "${googletest_BINARY_DIR}/bin" + COMPILE_PDB_OUTPUT_DIRECTORY "${googletest_BINARY_DIR}/lib" + ) + message(CHECK_PASS "done") +endif() + +include("${PROJECT_SOURCE_DIR}/cmake/gtest_helper.cmake") + +add_icon_c_test(UtilArithmeticExprTest ctest_util_arithmetic_expr.cpp) +add_icon_c_test(UtilHashTest ctest_util_hash.cpp) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/util_file_test.txt" + "This is a test file for unit tests for util_file.c\n") +file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/util_file_test.txt" + "${CMAKE_CURRENT_BINARY_DIR}/util_file_link.txt" SYMBOLIC) +add_icon_c_test(UtilFileTest ctest_util_file.cpp) diff --git a/test/googletest/c_test/ctest_util_arithmetic_expr.cpp b/test/c/ctest_util_arithmetic_expr.cpp similarity index 97% rename from test/googletest/c_test/ctest_util_arithmetic_expr.cpp rename to test/c/ctest_util_arithmetic_expr.cpp index 922104d94d0aaf5a61a2ab1b291e9700202278f5..401c815256f0b97c8ef773bda7ac092cc95c5e0e 100644 --- a/test/googletest/c_test/ctest_util_arithmetic_expr.cpp +++ b/test/c/ctest_util_arithmetic_expr.cpp @@ -1,7 +1,6 @@ #include <gtest/gtest.h> -#include <external_function.hpp> -#include <util_arithmetic_expr.hpp> +#include <util_arithmetic_expr.h> class UtilArithmeticExprTest : public ::testing::Test { protected: diff --git a/test/googletest/c_test/ctest_util_file.cpp b/test/c/ctest_util_file.cpp similarity index 52% rename from test/googletest/c_test/ctest_util_file.cpp rename to test/c/ctest_util_file.cpp index 65ad9e2bd209f80ae52dc678f9e58097986104bf..6cef0e3a6c8bcc4c896b21519c2a8bd6c850e4ac 100644 --- a/test/googletest/c_test/ctest_util_file.cpp +++ b/test/c/ctest_util_file.cpp @@ -1,18 +1,18 @@ #include <gtest/gtest.h> #include <string> -#include <path_config.h> -#include <external_function.hpp> +#include <util_file.h> + +static std::string working_dir = "."; class UtilFileTest : public ::testing::Test {}; TEST_F(UtilFileTest, FileIsLink) { - std::string path = current_path; - std::string file_notlink = path + "/test.txt"; - std::string file_islink = path + "/link.txt"; - std::string file_error = "./something.txt"; + std::string file_notlink = working_dir + "/util_file_test.txt"; + std::string file_islink = working_dir + "/util_file_link.txt"; + std::string file_error = working_dir + "/util_file_noexist.txt"; char *file_cstr; file_cstr = &file_notlink[0]; @@ -25,8 +25,7 @@ TEST_F(UtilFileTest, FileIsLink) { TEST_F(UtilFileTest, CanGetFileSize) { - std::string path = current_path; - std::string file = path + "/test.txt"; + std::string file = working_dir + "/util_file_test.txt"; char *file_cstr; file_cstr = &file[0]; @@ -36,11 +35,22 @@ TEST_F(UtilFileTest, CanGetFileSize) { TEST_F(UtilFileTest, CheckFileWritable) { - std::string path = current_path; - std::string file = path + "/test.txt"; + std::string file = working_dir + "/util_file_test.txt"; char *file_cstr; file_cstr = &file[0]; EXPECT_EQ(util_file_is_writable(file_cstr), 1); } + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + if (argc > 1) { + working_dir = argv[1]; + } + + std::cout << "Working directory: " << working_dir << std::endl; + + return RUN_ALL_TESTS(); +} diff --git a/test/googletest/c_test/ctest_util_hash.cpp b/test/c/ctest_util_hash.cpp similarity index 94% rename from test/googletest/c_test/ctest_util_hash.cpp rename to test/c/ctest_util_hash.cpp index 0d8cc05dd775962bcfccc9e0eeb8c691626cbcf6..eb128cc9b305752b92c19f897e6d4cecb7ba8ead 100644 --- a/test/googletest/c_test/ctest_util_hash.cpp +++ b/test/c/ctest_util_hash.cpp @@ -3,7 +3,7 @@ #include <stdexcept> #include <string> -#include <external_function.hpp> +#include <util_hash.h> class UtilHashCTest : public ::testing::Test {}; diff --git a/test/fortran/CMakeLists.txt b/test/fortran/CMakeLists.txt index 9ea990094ebb60e4a3d888e5cc3426999d8d5b1b..ce45562505274eeb79269f1e22685a5d89ca881f 100644 --- a/test/fortran/CMakeLists.txt +++ b/test/fortran/CMakeLists.txt @@ -7,19 +7,24 @@ FetchContent_Declare(fortutf URL https://github.com/artemis-beta/FortUTF/archive/10ea512e4b21fe9157ed838b037210874fbe92eb.tar.gz URL_HASH MD5=f1a5f9733553b32f2c6297c45b7c3f13 ) -FetchContent_MakeAvailable(fortutf) +# We do not need libFortUTF and want to avoid the redundant building of the +# library. Therefore, we do not call FetchContent_MakeAvailable(fortutf), which +# adds ${fortutf_SOURCE_DIR} as a subdirectory: +FetchContent_GetProperties(fortutf) +if(NOT fortutf_POPULATED) + FetchContent_Populate(fortutf) +endif() message(CHECK_PASS "done") -SET(FORTUTF_PROJECT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -SET(FORTUTF_PROJECT_SRC_LIBRARY ${PROJECT_NAME}::fortran-support) -SET(FORTUTF_PROJECT_SRC_FILES helpers.f90) +set(FORTUTF_PROJECT_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(FORTUTF_PROJECT_SRC_LIBRARY fortran-support::fortran-support) +set(FORTUTF_PROJECT_SRC_FILES helpers.f90) -INCLUDE(${fortutf_SOURCE_DIR}/cmake/fortutf.cmake) +include("${fortutf_SOURCE_DIR}/cmake/fortutf.cmake") # We have to prevent FortUTF from generating invalid Fortran code: -SET(project_name ${PROJECT_NAME}) +set(project_name ${PROJECT_NAME}) string(REPLACE "-" "_" PROJECT_NAME ${PROJECT_NAME}) FortUTF_Find_Tests() -SET(PROJECT_NAME ${project_name}) -add_test(NAME FortUTF_UnitTest - COMMAND fortran_support_Tests) +set(PROJECT_NAME ${project_name}) +add_test(NAME FortUTF_UnitTest COMMAND fortran_support_Tests) diff --git a/test/googletest/CMakeLists.txt b/test/googletest/CMakeLists.txt deleted file mode 100644 index c9e00d0dd05f9ebdacc6df495401105ccc324a24..0000000000000000000000000000000000000000 --- a/test/googletest/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -include(${PROJECT_SOURCE_DIR}/cmake/gtest_helper.cmake) - -add_subdirectory(c_test) diff --git a/test/googletest/c_test/CMakeLists.txt b/test/googletest/c_test/CMakeLists.txt deleted file mode 100644 index 598c2ee51a29214ab4047013e6f127212d10365e..0000000000000000000000000000000000000000 --- a/test/googletest/c_test/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_icon_c_test(UtilArithmeticExprTest ctest_util_arithmetic_expr.cpp) -add_icon_c_test(UtilHashTest ctest_util_hash.cpp) - -set(CurrentPath ${CMAKE_CURRENT_BINARY_DIR}) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/path_config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/path_config.h") -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/test.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/test.txt" "${CMAKE_CURRENT_BINARY_DIR}/link.txt" SYMBOLIC) -add_icon_c_test(UtilFileTest ctest_util_file.cpp) diff --git a/test/googletest/c_test/path_config.h.in b/test/googletest/c_test/path_config.h.in deleted file mode 100644 index a3b62bbfe60c5dea584be4d8f7397f095dd11154..0000000000000000000000000000000000000000 --- a/test/googletest/c_test/path_config.h.in +++ /dev/null @@ -1 +0,0 @@ -#define current_path "@CurrentPath@" diff --git a/test/googletest/c_test/test.txt b/test/googletest/c_test/test.txt deleted file mode 100644 index 4b34f50d85831db515e9912e1908bf9aa5a6db55..0000000000000000000000000000000000000000 --- a/test/googletest/c_test/test.txt +++ /dev/null @@ -1 +0,0 @@ -This is a test file for unit tests for util_file.c diff --git a/test/googletest/include/external_function.hpp b/test/googletest/include/external_function.hpp deleted file mode 100644 index 85c4687b2d6249d40dfbe2697a8e8bd970f9ab4c..0000000000000000000000000000000000000000 --- a/test/googletest/include/external_function.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EXTERNAL_FUNCTION_HPP_ -#define EXTERNAL_FUNCTION_HPP_ - - -extern "C" { -// util_arithmetic_expr.c -int priority(char op); -int left_associative(char op); -int do_parse_infix(const char *in_parse_line, struct t_list *queue); -int get_fctname(const int id, char *string); - -// util_file.c -int util_islink(const char *path); -long int util_filesize(char *filename); -int util_file_is_writable(char *filename); - -// util_hash.c -uint32_t util_hashword(const void *, size_t, uint32_t); -} - - -#endif // EXTERNAL_FUNCTION_HPP_ \ No newline at end of file