diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index c3c6f70..ab50693 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -13,7 +13,7 @@ jobs: - uses: cvmfs-contrib/github-action-cvmfs@v2 - uses: aidasoft/run-lcg-view@v3 with: - coverity-cmake-command: 'cmake -C $ILCSOFT/ILCSoft.cmake ..' + coverity-cmake-command: 'cmake -C $ILCSOFT/ILCSoft.cmake -DBUILD_TESTING=OFF ..' coverity-project: 'iLCSoft%2FMarlinUtil' coverity-project-token: ${{ secrets.MARLINUTIL_COVERITY_TOKEN }} github-pat: ${{ secrets.READ_COVERITY_IMAGE }} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 6cbc7ea..3c9065d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -15,15 +15,15 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: cvmfs-contrib/github-action-cvmfs@v2 - - uses: aidasoft/run-lcg-view@v3 + - uses: cvmfs-contrib/github-action-cvmfs@v3 + - uses: aidasoft/run-lcg-view@v4 with: view-path: "/cvmfs/clicdp.cern.ch/iLCSoft/lcg/${{ matrix.LCG }}/nightly/x86_64-centos7-${{ matrix.COMPILER }}-opt" setup-script: "init_ilcsoft.sh" run: | mkdir build cd build - cmake -GNinja -C ${ILCSOFT}/ILCSoft.cmake -DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always " -DINSTALL_DOC=ON .. + cmake -GNinja -C ${ILCSOFT}/ILCSoft.cmake -DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always " -DINSTALL_DOC=ON -DUSE_EXTERNAL_CATCH2=OFF .. ninja -k0 ctest --output-on-failure ninja install diff --git a/CMakeLists.txt b/CMakeLists.txt index 4987a67..6f6c444 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,24 +120,11 @@ SET_SOURCE_FILES_PROPERTIES( "./source/src/ann/kd_pr_search.cpp" PROPERTIES COMP #ADD_SHARED_LIBRARY( ${PROJECT_NAME}_ann ${ann_library_sources} ) #INSTALL_SHARED_LIBRARY( ${PROJECT_NAME}_ann DESTINATION lib ) +option(USE_EXTERNAL_CATCH2 "Link against an external Catch2 v3 static library, otherwise build it locally" ON) -# helper macro for adding new tests -# build with 'make tests' -ADD_CUSTOM_TARGET( tests ) -MACRO( ADD_MARLINUTIL_TEST _name ) - # MarlinUtil test - IF( BUILD_TESTING ) - ADD_EXECUTABLE( ${_name} "./source/tests/${_name}.cc" ) - ELSE() - ADD_EXECUTABLE( ${_name} EXCLUDE_FROM_ALL "./source/tests/${_name}.cc" ) - ENDIF() - ADD_DEPENDENCIES( tests ${_name} ) - TARGET_LINK_LIBRARIES( ${_name} ${PROJECT_NAME} ) - #INSTALL( TARGETS ${_name} DESTINATION bin ) -ENDMACRO() - -ADD_MARLINUTIL_TEST( testmarlinutil ) - +IF( BUILD_TESTING ) + ADD_SUBDIRECTORY(source/tests) +ENDIF() # display some variables and write them to cache DISPLAY_STD_VARIABLES() diff --git a/source/include/HelixClassT.h b/source/include/HelixClassT.h index e038670..cb0e327 100644 --- a/source/include/HelixClassT.h +++ b/source/include/HelixClassT.h @@ -56,7 +56,10 @@ template class HelixClassT { public: - + /** + * The floatint point type used internally. Useful for generic programming + */ + using float_type = FloatT; /** * Constructor. Initializations of constants which are used * to calculate various parameters associated with helix. @@ -109,12 +112,12 @@ class HelixClassT { * Returns momentum of particle at the point of closest approach
* to IP
*/ - const FloatT *const getMomentum() const { return _momentum; } + const FloatT* getMomentum() const { return _momentum; } /** * Returns reference point of track
*/ - const FloatT *const getReferencePoint() const { return _referencePoint; } + const FloatT* getReferencePoint() const { return _referencePoint; } /** * Returns Phi angle of the momentum vector
@@ -242,12 +245,12 @@ class HelixClassT { /** * Returns starting point of helix */ - const FloatT *const getStartingPoint() const {return _xStart;} + const FloatT* getStartingPoint() const {return _xStart;} /** * Returns endpoint of helix */ - const FloatT *const getEndPoint() const {return _xEnd;} + const FloatT* getEndPoint() const {return _xEnd;} /** * Returns BZ for the second parameterization diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt new file mode 100644 index 0000000..2aa8ff6 --- /dev/null +++ b/source/tests/CMakeLists.txt @@ -0,0 +1,50 @@ +# helper macro for adding new tests +# build with 'make tests' +ADD_CUSTOM_TARGET( tests ) +MACRO( ADD_MARLINUTIL_TEST _name ) + # MarlinUtil test + ADD_EXECUTABLE( ${_name} "${_name}.cc" ) + ADD_TEST( NAME ${_name} COMMAND ${_name}) + TARGET_LINK_LIBRARIES( ${_name} ${PROJECT_NAME} ) +ENDMACRO() + +ADD_MARLINUTIL_TEST( testmarlinutil ) + +#--- Unit test setup. Use existing Catch2 or fetch a suitable version and build it +if(USE_EXTERNAL_CATCH2) + FIND_PACKAGE(Catch2 3.0.0 REQUIRED) +else() + MESSAGE(STATUS "Fetching local copy of Catch2 library for unit-tests...") + # Build Catch2 with the default flags, to avoid generating warnings when we + # build it + SET(CXX_FLAGS_CMAKE_USED ${CMAKE_CXX_FLAGS}) + SET(CMAKE_CXX_FLAGS ${CXX_FLAGS_CMAKE_DEFAULTS}) + INCLUDE(FetchContent) + fETCHCONTENT_DECLARE( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.0.1 + ) + FETCHCONTENT_MAKEAVAILABLE(Catch2) + set(CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras ${CMAKE_MODULE_PATH}) + + # Disable clang-tidy on external contents + SET_TARGET_PROPERTIES(Catch2 PROPERTIES CXX_CLANG_TIDY "") + + # Hack around the fact, that the include directories are not declared as + # SYSTEM for the targets defined this way. Otherwise warnings can still occur + # in Catch2 code when templates are evaluated (which happens quite a bit) + GET_TARGET_PROPERTY(CATCH2_IF_INC_DIRS Catch2 INTERFACE_INCLUDE_DIRECTORIES) + SET_TARGET_PROPERTIES(Catch2 PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${CATCH2_IF_INC_DIRS}") + + # Reset the flags + SET(CMAKE_CXX_FLAGS ${CXX_FLAGS_CMAKE_USED}) +endif() + +INCLUDE(Catch) + +ADD_EXECUTABLE(unittests unittests/TestHelixClass.cpp) +TARGET_LINK_LIBRARIES(unittests PUBLIC ${PROJECT_NAME} PRIVATE Catch2::Catch2WithMain) +CATCH_DISCOVER_TESTS(unittests + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) diff --git a/source/tests/unittests/TestHelixClass.cpp b/source/tests/unittests/TestHelixClass.cpp new file mode 100644 index 0000000..6094325 --- /dev/null +++ b/source/tests/unittests/TestHelixClass.cpp @@ -0,0 +1,49 @@ +#include "HelixClass.h" +#include "HelixClass_double.h" + +#include "CLHEP/Units/PhysicalConstants.h" + +#include +#include +#include + +#include +#include +#include + +// The speed of light as used inside the Helix class +constexpr auto c_helix = CLHEP::c_light / (CLHEP::m / CLHEP::ps); + +// Using this type list and a TEMPLATE_LIST_TEST_CASE we can test both versions +// of the HelixClass with only one set of code. Inside the test case we can +// refer to the current HelixClass type with TestType +using HelixTypes = std::tuple; + +TEMPLATE_LIST_TEST_CASE("Initialize_VP", "[helix-init]", HelixTypes) { + TestType helix; + using FloatT = typename TestType::float_type; + /*const*/ std::array position = {0.1, 0.2, 0.3}; + /*const*/ std::array momentum = {10., 20., 30.}; + + const auto pt = std::hypot(momentum[0], momentum[1]); + const auto magField = 3.0; + const auto charge = -1.0; + + helix.Initialize_VP(position.data(), momentum.data(), charge, magField); + + REQUIRE(helix.getRadius() == Catch::Approx(pt / (c_helix * magField))); + REQUIRE(helix.getOmega() == Catch::Approx(charge / helix.getRadius())); + REQUIRE(helix.getTanLambda() == Catch::Approx(momentum[2] / pt)); + // etc... +} + +// TODO: add actually useful HelixClass tests, e.g. +// - Initialize with one of the methods and check whether the resulting Helix +// has the expected properties, like +// - calculating different distances to the Helix and check whether the +// conform to expecations +// - Calculating momenta and see whether that gives the expected values +// - essentially all non-trivial get functionality +// - Other usage examples as found in the "real-world" +// - Also add things that work slightly unexpectedly at the moment, e.g. things +// that are listed in https://github.com/iLCSoft/MarlinUtil/issues/24