Skip to content

Commit

Permalink
Merge pull request #275 from Goddard-Fortran-Ecosystem/hotfix/add-pfu…
Browse files Browse the repository at this point in the history
…nit-ctest-fix

Fixed problems with add_pfunit_ctest() macro
  • Loading branch information
tclune authored Feb 5, 2021
2 parents 798e87d + a43ee50 commit eb51595
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 2 deletions.
14 changes: 14 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- The `add_pfunit_ctest()` macro could fail under several not-so-rare
circumstances. One way is for CMake to fail to build
`OTHER_SOURCES` before the driver as it cannot correctly analyze
the indirect Fortran `USE PFUNIT_EXTRA_INITIALIZE` statement. The
other is when using paralle builds with multiple test suites using
Intel and the `-save-temps` flag. Here the compiler would overwrite the
`driver.i90` in the build directory and produce confusing results.

The solution is to use Cmake `configure_file()` to preprocess the driver
directly on a per-suite basis. This will allow CMake+FPP to corretly
analyze dependencies and avoid reuse of `driver.i90`.

## [4.1.15] - 2020-01-06

### Added
Expand Down
2 changes: 1 addition & 1 deletion include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ file_compile_configuration()
# Perform the install.
#
install(
FILES driver.F90 add_pfunit_sources.cmake add_pfunit_ctest.cmake add_pfunit_test.cmake
FILES driver.F90 driver.F90.in add_pfunit_sources.cmake add_pfunit_ctest.cmake add_pfunit_test.cmake
DESTINATION ${dest}/include
)

Expand Down
9 changes: 8 additions & 1 deletion include/add_pfunit_ctest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ function (add_pfunit_ctest test_package_name)

endforeach()


if (PF_TEST_EXTRA_USE)
set(PFUNIT_EXTRA_USE ${PF_TEST_EXTRA_USE})
endif()
set(driver "${test_package_name}_driver.F90")
configure_file(${PFUNIT_DRIVER}.in ${driver})

add_executable (${test_package_name}
${test_sources_f90}
${PF_TEST_OTHER_SOURCES}
${PFUNIT_DRIVER}
${driver}
)

if (PF_TEST_REGISTRY)
Expand Down
84 changes: 84 additions & 0 deletions include/driver.F90.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
!---------------------------------------------------------------------------
! This file is external to the pfunit library and is used to represent
! information that cannot be determined at run-time. In particular,
! Fortran lacks reflection/introspection and therefore cannot automatically
! collect user-defined test suites.
!
!
! Typical usage is for the user to compile this file while leaving it in the
! pFUnit installation directory. Use "-D<_TEST_SUITES>" to specify a file
! that contains the list of test_suites to be builtlinked and executed.
!
!
! For serial runs, the user links with the FUnit library, while for parallel
! runs the user links with FUnit _and_ pFUnit.
!---------------------------------------------------------------------------

#cmakedefine PFUNIT_EXTRA_USE @PFUNIT_EXTRA_USE@
module loader
use FUnit, only: TestSuite
implicit none

contains

function load_tests() result(suite)

#define ADDULE_TEST_SUITE(m,s) use m, only: s
#define ADD_TEST_SUITE(s) ! do nothing
#include _TEST_SUITES
#undef ADDULE_TEST_SUITE
#undef ADD_TEST_SUITE

type (TestSuite) :: suite

#define ADDULE_TEST_SUITE(m,s) ! do nothing
#define ADD_TEST_SUITE(s) type (TestSuite), external :: s
# include _TEST_SUITES
#undef ADD_TEST_SUITE
#undef ADDULE_TEST_SUITE

suite = TestSuite()

#define ADD_TEST_SUITE(s) call suite%addTest(s())
#define ADDULE_TEST_SUITE(m,s) call suite%addTest(s())
# include _TEST_SUITES
#undef ADD_TEST_SUITE
#undef ADDULE_TEST_SUITE

end function load_tests

end module loader

program main
use FUnit, only : stub
use loader
#ifdef PFUNIT_EXTRA_USE
! Use external code for whatever suite-wide fixture is in use.
use @PFUNIT_EXTRA_USE@
#endif
implicit none

procedure(), pointer :: extra_initialize
procedure(), pointer :: extra_finalize

#ifdef PFUNIT_EXTRA_INITIALIZE
# ifndef PFUNIT_EXTRA_USE
external :: PFUNIT_EXTRA_INITIALIZE
# endif
extra_initialize => PFUNIT_EXTRA_INITIALIZE
#else
extra_initialize => stub
#endif

#ifdef PFUNIT_EXTRA_FINALIZE
# ifndef PFUNIT_EXTRA_USE
external :: PFUNIT_EXTRA_FINALIZE
# endif
extra_finalize => PFUNIT_EXTRA_FINALIZE
#else
extra_finalize => stub
#endif

call funit_main(load_tests, extra_initialize, extra_finalize)

end program main

0 comments on commit eb51595

Please sign in to comment.