From 7d9684cc3596053d437a1a8d2d913bc1e05fe288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Aradi?= Date: Thu, 3 Oct 2024 18:33:46 +0200 Subject: [PATCH] Add fpp macros to support automatic location info generation --- .github/workflows/ci.yml | 7 +- cmake/fortuno-coarray.pc.in | 2 +- cmake/fortuno-mpi.pc.in | 2 +- cmake/fortuno-serial.pc.in | 2 +- .../coarray/addons/.github/workflows/ci.yml | 2 +- devel/fpm-repo/coarray/repo.ignore | 1 + devel/fpm-repo/coarray/repo.include | 2 + .../mpi/addons/.github/workflows/ci.yml | 2 +- devel/fpm-repo/mpi/repo.ignore | 1 + devel/fpm-repo/mpi/repo.include | 2 + .../serial/addons/.github/workflows/ci.yml | 2 +- devel/fpm-repo/serial/repo.ignore | 1 + devel/fpm-repo/serial/repo.include | 2 + example/CMakeLists.txt | 3 + example/coarray-fpp/CMakeLists.txt | 33 ++++ example/coarray-fpp/meson.build | 26 +++ example/coarray-fpp/mylib.f90 | 30 ++++ example/coarray-fpp/test_simple_fpp.F90 | 57 +++++++ example/coarray-fpp/testapp.f90 | 13 ++ example/meson.build | 3 + example/mpi-fpp/CMakeLists.txt | 34 ++++ example/mpi-fpp/meson.build | 23 +++ example/mpi-fpp/mylib.f90 | 59 +++++++ example/mpi-fpp/test_simple_fpp.F90 | 55 +++++++ example/mpi-fpp/testapp.f90 | 13 ++ example/serial-fpp/CMakeLists.txt | 36 +++++ example/serial-fpp/meson.build | 26 +++ example/serial-fpp/mylib.f90 | 34 ++++ example/serial-fpp/test_fixtured_fpp.F90 | 109 +++++++++++++ .../serial-fpp/test_fixtured_module_fpp.F90 | 96 +++++++++++ .../serial-fpp/test_fixtured_suite_fpp.F90 | 149 ++++++++++++++++++ example/serial-fpp/test_parametrized_fpp.F90 | 76 +++++++++ example/serial-fpp/test_simple_fpp.F90 | 51 ++++++ example/serial-fpp/testapp.f90 | 23 +++ include/CMakeLists.txt | 12 +- include/fortuno_coarray.fpp | 30 ++++ include/fortuno_coarray.fypp | 2 +- include/fortuno_mpi.fpp | 34 ++++ include/fortuno_mpi.fypp | 2 +- include/fortuno_serial.fypp | 2 +- meson.build | 1 + src/CMakeLists.txt | 3 + test/export/coarray/app/CMakeLists.txt | 5 + test/export/coarray/app/meson.build | 3 + test/export/coarray/app/testapp_fpp.F90 | 49 ++++++ test/export/coarray/fpm.toml | 4 + test/export/coarray/meson.build | 10 ++ test/export/mpi/app/CMakeLists.txt | 4 + test/export/mpi/app/meson.build | 3 + test/export/mpi/app/testapp_fpp.F90 | 47 ++++++ test/export/mpi/fpm.toml | 6 +- test/export/mpi/meson.build | 9 ++ test/export/serial/app/CMakeLists.txt | 5 +- test/export/serial/app/meson.build | 3 + test/export/serial/app/testapp_fpp.F90 | 19 +-- test/export/serial/fpm.toml | 6 +- test/export/serial/meson.build | 8 + 57 files changed, 1215 insertions(+), 29 deletions(-) create mode 100644 example/coarray-fpp/CMakeLists.txt create mode 100644 example/coarray-fpp/meson.build create mode 100644 example/coarray-fpp/mylib.f90 create mode 100644 example/coarray-fpp/test_simple_fpp.F90 create mode 100644 example/coarray-fpp/testapp.f90 create mode 100644 example/mpi-fpp/CMakeLists.txt create mode 100644 example/mpi-fpp/meson.build create mode 100644 example/mpi-fpp/mylib.f90 create mode 100644 example/mpi-fpp/test_simple_fpp.F90 create mode 100644 example/mpi-fpp/testapp.f90 create mode 100644 example/serial-fpp/CMakeLists.txt create mode 100644 example/serial-fpp/meson.build create mode 100644 example/serial-fpp/mylib.f90 create mode 100644 example/serial-fpp/test_fixtured_fpp.F90 create mode 100644 example/serial-fpp/test_fixtured_module_fpp.F90 create mode 100644 example/serial-fpp/test_fixtured_suite_fpp.F90 create mode 100644 example/serial-fpp/test_parametrized_fpp.F90 create mode 100644 example/serial-fpp/test_simple_fpp.F90 create mode 100644 example/serial-fpp/testapp.f90 create mode 100644 include/fortuno_coarray.fpp create mode 100644 include/fortuno_mpi.fpp create mode 100644 test/export/coarray/app/testapp_fpp.F90 create mode 100644 test/export/mpi/app/testapp_fpp.F90 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efbe33d..a14f2e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,8 @@ jobs: run: | echo "FC=${{ env.FC }}" >> ${GITHUB_ENV} echo "FPM_FC=${{ env.FC }}" >> ${GITHUB_ENV} + echo "FFLAGS=-ffree-line-length-none" >> ${GITHUB_ENV} + echo "FPM_FFLAGS=-ffree-line-length-none" >> ${GITHUB_ENV} - name: Setup MPICH on Ubuntu if: ${{ contains(matrix.os, 'ubuntu') && contains(matrix.mpi, 'mpich') }} @@ -168,13 +170,14 @@ jobs: CMAKE_PREFIX_PATH=${INSTALL_DIR} cmake -B ${BUILD_DIR} -G Ninja test/export/${INTERFACE} cmake --build ${BUILD_DIR} ${RUN_PREFIX} ${BUILD_DIR}/app/testapp + ${RUN_PREFIX} ${BUILD_DIR}/app/testapp_fpp ${RUN_PREFIX} ${BUILD_DIR}/app/testapp_fypp rm -rf ${BUILD_DIR} - name: Test fpm export run: | ./devel/fpm-repo/export-fpm-repo.sh ${INTERFACE} ${FPM_EXPORT_DIR} - fpm run -C ${FPM_EXPORT_DIR}/test/export/${INTERFACE} testapp + fpm run -C ${FPM_EXPORT_DIR}/test/export/${INTERFACE} --runner "${RUN_PREFIX}" testapp testapp_fpp rm -rf ${FPM_EXPORT_DIR} - name: Test Meson pkgconfig export @@ -186,6 +189,7 @@ jobs: meson setup ${MESON_OPTIONS_NOFALLBACK} --wrap-mode nofallback ${BUILD_DIR} ninja -C ${BUILD_DIR} ${RUN_PREFIX} ${BUILD_DIR}/testapp + ${RUN_PREFIX} ${BUILD_DIR}/testapp_fpp rm -rf ./${BUILD_DIR} - name: Test Meson subproject export @@ -201,6 +205,7 @@ jobs: meson setup ${MESON_OPTIONS_FALLBACK} --wrap-mode forcefallback ${BUILD_DIR} ninja -C ${BUILD_DIR} ${RUN_PREFIX} ${BUILD_DIR}/testapp + ${RUN_PREFIX} ${BUILD_DIR}/testapp_fpp rm -rf subprojects ${BUILD_DIR} deploy-fpm: diff --git a/cmake/fortuno-coarray.pc.in b/cmake/fortuno-coarray.pc.in index 691577e..c2d0cf4 100644 --- a/cmake/fortuno-coarray.pc.in +++ b/cmake/fortuno-coarray.pc.in @@ -3,5 +3,5 @@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Requires: fortuno -Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_COA_INSTALL_MODULEDIR@ +Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_INSTALL_MODULEDIR@ -I@CMAKE_INSTALL_FULL_INCLUDEDIR@ Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lfortuno-coarray diff --git a/cmake/fortuno-mpi.pc.in b/cmake/fortuno-mpi.pc.in index b48e12a..59b91d5 100644 --- a/cmake/fortuno-mpi.pc.in +++ b/cmake/fortuno-mpi.pc.in @@ -3,5 +3,5 @@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Requires: fortuno -Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_MPI_INSTALL_MODULEDIR@ +Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_INSTALL_MODULEDIR@ -I@CMAKE_INSTALL_FULL_INCLUDEDIR@ Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lfortuno-mpi diff --git a/cmake/fortuno-serial.pc.in b/cmake/fortuno-serial.pc.in index ca8c0c1..9fc4a5c 100644 --- a/cmake/fortuno-serial.pc.in +++ b/cmake/fortuno-serial.pc.in @@ -3,5 +3,5 @@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Requires: fortuno -Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_INSTALL_MODULEDIR@ +Cflags: -I@CMAKE_INSTALL_FULL_LIBDIR@/@FORTUNO_INSTALL_MODULEDIR@ -I@CMAKE_INSTALL_FULL_INCLUDEDIR@ Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lfortuno-serial diff --git a/devel/fpm-repo/coarray/addons/.github/workflows/ci.yml b/devel/fpm-repo/coarray/addons/.github/workflows/ci.yml index 5a6390a..e07b13f 100644 --- a/devel/fpm-repo/coarray/addons/.github/workflows/ci.yml +++ b/devel/fpm-repo/coarray/addons/.github/workflows/ci.yml @@ -44,4 +44,4 @@ jobs: - name: Test fpm export run: | - fpm run -C test/export/${INTERFACE} testapp + fpm run -C test/export/${INTERFACE} testapp testapp_fpp diff --git a/devel/fpm-repo/coarray/repo.ignore b/devel/fpm-repo/coarray/repo.ignore index 4655971..ac1b9c4 100644 --- a/devel/fpm-repo/coarray/repo.ignore +++ b/devel/fpm-repo/coarray/repo.ignore @@ -5,3 +5,4 @@ CMakeLists.txt meson.build meson.options +*.fypp diff --git a/devel/fpm-repo/coarray/repo.include b/devel/fpm-repo/coarray/repo.include index 53290e9..380d5dc 100644 --- a/devel/fpm-repo/coarray/repo.include +++ b/devel/fpm-repo/coarray/repo.include @@ -1,4 +1,6 @@ LICENSE +include/ +include/fortuno_coarray.fpp src/ src/fortuno.f90 src/fortuno/ diff --git a/devel/fpm-repo/mpi/addons/.github/workflows/ci.yml b/devel/fpm-repo/mpi/addons/.github/workflows/ci.yml index c668751..c841631 100644 --- a/devel/fpm-repo/mpi/addons/.github/workflows/ci.yml +++ b/devel/fpm-repo/mpi/addons/.github/workflows/ci.yml @@ -47,4 +47,4 @@ jobs: - name: Test fpm export run: | - fpm run -C test/export/${INTERFACE} --runner 'mpirun -n 2' testapp + fpm run -C test/export/${INTERFACE} --runner 'mpirun -n 2' testapp testapp_fpp diff --git a/devel/fpm-repo/mpi/repo.ignore b/devel/fpm-repo/mpi/repo.ignore index 4655971..a1859a0 100644 --- a/devel/fpm-repo/mpi/repo.ignore +++ b/devel/fpm-repo/mpi/repo.ignore @@ -5,3 +5,4 @@ CMakeLists.txt meson.build meson.options +*.fypp \ No newline at end of file diff --git a/devel/fpm-repo/mpi/repo.include b/devel/fpm-repo/mpi/repo.include index ddd0a97..7e0943b 100644 --- a/devel/fpm-repo/mpi/repo.include +++ b/devel/fpm-repo/mpi/repo.include @@ -1,4 +1,6 @@ LICENSE +include/ +include/fortuno_mpi.fpp src/ src/fortuno.f90 src/fortuno/ diff --git a/devel/fpm-repo/serial/addons/.github/workflows/ci.yml b/devel/fpm-repo/serial/addons/.github/workflows/ci.yml index 3508782..f80afa8 100644 --- a/devel/fpm-repo/serial/addons/.github/workflows/ci.yml +++ b/devel/fpm-repo/serial/addons/.github/workflows/ci.yml @@ -42,4 +42,4 @@ jobs: - name: Test fpm export run: | - fpm run -C test/export/${INTERFACE} testapp + fpm run -C test/export/${INTERFACE} testapp testapp_fpp diff --git a/devel/fpm-repo/serial/repo.ignore b/devel/fpm-repo/serial/repo.ignore index 4655971..a1859a0 100644 --- a/devel/fpm-repo/serial/repo.ignore +++ b/devel/fpm-repo/serial/repo.ignore @@ -5,3 +5,4 @@ CMakeLists.txt meson.build meson.options +*.fypp \ No newline at end of file diff --git a/devel/fpm-repo/serial/repo.include b/devel/fpm-repo/serial/repo.include index 6cc107b..592d370 100644 --- a/devel/fpm-repo/serial/repo.include +++ b/devel/fpm-repo/serial/repo.include @@ -1,4 +1,6 @@ LICENSE +include/ +include/fortuno_serial.fpp src/ src/fortuno.f90 src/fortuno/ diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 450e7de..d8f5c24 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -6,6 +6,7 @@ list(APPEND CMAKE_MESSAGE_CONTEXT Example) if (FORTUNO_WITH_SERIAL) add_subdirectory(serial) + add_subdirectory(serial-fpp) if (FYPP) add_subdirectory(serial-fypp) endif () @@ -13,6 +14,7 @@ endif () if (FORTUNO_WITH_MPI) add_subdirectory(mpi) + add_subdirectory(mpi-fpp) if (FYPP) add_subdirectory(mpi-fypp) endif () @@ -20,6 +22,7 @@ endif () if (FORTUNO_WITH_COARRAY) add_subdirectory(coarray) + add_subdirectory(coarray-fpp) if (FYPP) add_subdirectory(coarray-fypp) endif () diff --git a/example/coarray-fpp/CMakeLists.txt b/example/coarray-fpp/CMakeLists.txt new file mode 100644 index 0000000..d1f1383 --- /dev/null +++ b/example/coarray-fpp/CMakeLists.txt @@ -0,0 +1,33 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +list(APPEND CMAKE_MESSAGE_CONTEXT CoarrayFpp) + +add_library(fortuno_example_coarray_fpp_mylib) +set_target_properties( + fortuno_example_coarray_fpp_mylib PROPERTIES + OUTPUT_NAME mylib +) +target_sources( + fortuno_example_coarray_fpp_mylib PRIVATE + mylib.f90 +) +fortuno_add_coarray_build_flags(fortuno_example_coarray_fpp_mylib) + +add_executable(fortuno_example_coarray_fpp_testapp) +set_target_properties( + fortuno_example_coarray_fpp_testapp PROPERTIES + OUTPUT_NAME testapp +) +target_sources( + fortuno_example_coarray_fpp_testapp PRIVATE + test_simple_fpp.F90 + testapp.f90 +) +target_link_libraries( + fortuno_example_coarray_fpp_testapp PRIVATE + fortuno_example_coarray_fpp_mylib + Fortuno::fortuno_coarray +) +fortuno_add_coarray_build_flags(fortuno_example_coarray_fpp_testapp) diff --git a/example/coarray-fpp/meson.build b/example/coarray-fpp/meson.build new file mode 100644 index 0000000..97ae6d4 --- /dev/null +++ b/example/coarray-fpp/meson.build @@ -0,0 +1,26 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +example_mylib_fpp_lib = library( + 'mylib', + sources: ['mylib.f90'], + install: false, + fortran_args: fflags_coarray, + link_args: ldflags_coarray, +) +example_mylib_fpp_dep = declare_dependency( + link_with: example_mylib_fpp_lib, +) + +example_testapp_exe = executable( + 'testapp', + sources: [ + 'test_simple_fpp.F90', + 'testapp.f90', + ], + dependencies: [example_mylib_fpp_dep, fortuno_coarray_dep], + install: false, + fortran_args: fflags_coarray, + link_args: ldflags_coarray, +) diff --git a/example/coarray-fpp/mylib.f90 b/example/coarray-fpp/mylib.f90 new file mode 100644 index 0000000..920f389 --- /dev/null +++ b/example/coarray-fpp/mylib.f90 @@ -0,0 +1,30 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Demo module/library to be tested +module mylib + implicit none + + private + public :: broadcast + +contains + + + !> Broadcasts a scalar integer. + subroutine broadcast(buffer, source) + + !> Buffer to broadcast + integer, intent(inout) :: buffer + + !> Source image + integer, intent(in) :: source + + integer :: stat + + call co_broadcast(buffer, source) + + end subroutine broadcast + +end module mylib diff --git a/example/coarray-fpp/test_simple_fpp.F90 b/example/coarray-fpp/test_simple_fpp.F90 new file mode 100644 index 0000000..f9d8827 --- /dev/null +++ b/example/coarray-fpp/test_simple_fpp.F90 @@ -0,0 +1,57 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_coarray.fpp" + +module test_simple_fpp + use mylib, only : broadcast + use fortuno_coarray, only : as_char, test => coa_pure_case_item, context => coa_context,& + & is_equal, test_list + implicit none + +contains + + + !> Returns the tests from this module + function tests() + type(test_list) :: tests + + tests = test_list([& + test("broadcast", test_broadcast)& + ]) + + end function tests + + + !> Broadcast test with collective communication + subroutine test_broadcast(ctx) + class(context), intent(inout) :: ctx + + integer, parameter :: sourceimg = 1, sourceval = 100, otherval = -1 + integer :: buffer + + character(:), allocatable :: msg + + ! GIVEN source rank contains a different integer value as all other ranks + if (this_image() == sourceimg) then + buffer = sourceval + else + buffer = otherval + end if + + ! WHEN source rank broadcasts its value + call broadcast(buffer, sourceimg) + + ! Make every third rank fail for demonstration purposes + if (mod(this_image() - 1, 3) == 2) then + buffer = sourceval + 1 + msg = "Failing on image " // as_char(this_image()) // " on purpose" + end if + + ! THEN each rank must contain source rank's value + CHECK_MSG(ctx, is_equal(buffer, sourceval), msg) + + end subroutine test_broadcast + +end module test_simple_fpp diff --git a/example/coarray-fpp/testapp.f90 b/example/coarray-fpp/testapp.f90 new file mode 100644 index 0000000..2c5f084 --- /dev/null +++ b/example/coarray-fpp/testapp.f90 @@ -0,0 +1,13 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Test app, collecting and executing the tests +program testapp + use fortuno_coarray, only : execute_coa_cmd_app + use test_simple_fpp, only : tests + implicit none + + call execute_coa_cmd_app(tests()) + +end program testapp diff --git a/example/meson.build b/example/meson.build index 9dd5722..ada9b9f 100644 --- a/example/meson.build +++ b/example/meson.build @@ -4,12 +4,15 @@ if with_serial subdir('serial') + subdir('serial-fpp') endif if with_mpi subdir('mpi') + subdir('mpi-fpp') endif if with_coarray subdir('coarray') + subdir('coarray-fpp') endif diff --git a/example/mpi-fpp/CMakeLists.txt b/example/mpi-fpp/CMakeLists.txt new file mode 100644 index 0000000..61bdbde --- /dev/null +++ b/example/mpi-fpp/CMakeLists.txt @@ -0,0 +1,34 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +list(APPEND CMAKE_MESSAGE_CONTEXT MpiFpp) + +add_library(fortuno_example_mpi_fpp_mylib) +set_target_properties( + fortuno_example_mpi_fpp_mylib PROPERTIES + OUTPUT_NAME mylib +) +target_sources( + fortuno_example_mpi_fpp_mylib PRIVATE + mylib.f90 +) +target_link_libraries(fortuno_example_mpi_fpp_mylib PRIVATE MPI::MPI_Fortran) + +add_executable(fortuno_example_mpi_fpp_testapp) +set_target_properties( + fortuno_example_mpi_fpp_testapp PROPERTIES + OUTPUT_NAME testapp +) +target_sources( + fortuno_example_mpi_fpp_testapp PRIVATE + test_simple_fpp.F90 + testapp.f90 +) +target_link_libraries( + fortuno_example_mpi_fpp_testapp + PRIVATE + fortuno_example_mpi_fpp_mylib + Fortuno::fortuno_mpi + MPI::MPI_Fortran +) diff --git a/example/mpi-fpp/meson.build b/example/mpi-fpp/meson.build new file mode 100644 index 0000000..7f618db --- /dev/null +++ b/example/mpi-fpp/meson.build @@ -0,0 +1,23 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +example_mylib_fpp_lib = library( + 'mylib', + sources: ['mylib.f90'], + dependencies: [mpi_fortran_dep], + install: false, +) +example_mylib_fpp_dep = declare_dependency( + link_with: example_mylib_fpp_lib, +) + +example_testapp_exe = executable( + 'testapp', + sources: [ + 'test_simple_fpp.F90', + 'testapp.f90', + ], + dependencies: [example_mylib_fpp_dep, fortuno_mpi_dep], + install: false, +) diff --git a/example/mpi-fpp/mylib.f90 b/example/mpi-fpp/mylib.f90 new file mode 100644 index 0000000..b7e5a77 --- /dev/null +++ b/example/mpi-fpp/mylib.f90 @@ -0,0 +1,59 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Demo module/library to be tested +module mylib + use mpi_f08, only : MPI_Allreduce, MPI_Bcast, MPI_Comm, MPI_COMM_WORLD, MPI_IN_PLACE,& + & MPI_INTEGER, MPI_SUM + implicit none + + private + public :: allreduce_sum, broadcast + +contains + + + !> Broadcasts a scalar integer + subroutine broadcast(comm, buffer, source) + + !> MPI communicator to use + type(MPI_Comm), intent(in) :: comm + + !> Item to broadcast + integer, intent(inout) :: buffer + + !> Source rank (default = 0) + integer, optional, intent(in) :: source + + integer :: source_ + integer :: ierror + + if (present(source)) then + source_ = source + else + source_ = 0 + end if + call MPI_Bcast(buffer, 1, MPI_INTEGER, source_, comm, ierror) + if (ierror /= 0) error stop "MPI_Bcast failed in mylib/broadcast" + + end subroutine broadcast + + + !> Reduces a scalar integer by summation on all ranks + subroutine allreduce_sum(comm, val) + + !> MPI communicator + type(MPI_Comm), intent(in) :: comm + + !> Value to reduce by summation + integer, intent(inout) :: val + + integer :: ierror + + call MPI_Allreduce(MPI_IN_PLACE, val, 1, MPI_INTEGER, MPI_SUM, comm, ierror) + if (ierror /= 0) error stop "MPI_Allreduce failed in mylib/allreduce_sum" + + end subroutine allreduce_sum + +end module mylib diff --git a/example/mpi-fpp/test_simple_fpp.F90 b/example/mpi-fpp/test_simple_fpp.F90 new file mode 100644 index 0000000..7a63991 --- /dev/null +++ b/example/mpi-fpp/test_simple_fpp.F90 @@ -0,0 +1,55 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_mpi.fpp" + +module test_simple_fpp + use mylib, only : broadcast + use fortuno_mpi, only : as_char, global_comm, is_equal, test => mpi_case_item,& + & test_list, this_rank + implicit none + +contains + + + !> Returns the tests from this module + function tests() + type(test_list) :: tests + + tests = test_list([& + test("broadcast", test_broadcast)& + ]) + + end function tests + + + !> Simple test with collective communication + subroutine test_broadcast() + integer, parameter :: sourcerank = 0, sourceval = 1, otherval = -1 + integer :: buffer + + character(:), allocatable :: msg + + ! GIVEN source rank contains a different integer value as all other ranks + if (this_rank() == sourcerank) then + buffer = sourceval + else + buffer = otherval + end if + + ! WHEN source rank broadcasts its value + call broadcast(global_comm(), buffer, sourcerank) + + ! Make every third rank fail for demonstration purposes + if (mod(this_rank(), 3) == 2) then + buffer = sourceval + 1 + msg = "Failing on rank " // as_char(this_rank()) // " on purpose" + end if + + ! THEN each rank must contain source rank's value + CHECK_MSG(is_equal(buffer, sourceval), msg) + + end subroutine test_broadcast + +end module test_simple_fpp diff --git a/example/mpi-fpp/testapp.f90 b/example/mpi-fpp/testapp.f90 new file mode 100644 index 0000000..65cbfb9 --- /dev/null +++ b/example/mpi-fpp/testapp.f90 @@ -0,0 +1,13 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Test app, collecting and executing the tests +program testapp + use fortuno_mpi, only : execute_mpi_cmd_app + use test_simple_fpp, only : simple_fpp_tests => tests + implicit none + + call execute_mpi_cmd_app(simple_fpp_tests()) + +end program testapp diff --git a/example/serial-fpp/CMakeLists.txt b/example/serial-fpp/CMakeLists.txt new file mode 100644 index 0000000..8ba47ee --- /dev/null +++ b/example/serial-fpp/CMakeLists.txt @@ -0,0 +1,36 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +list(APPEND CMAKE_MESSAGE_CONTEXT SerialFpp) + +add_library(fortuno_example_serial_fpp_mylib) +set_target_properties( + fortuno_example_serial_fpp_mylib PROPERTIES + OUTPUT_NAME mylib +) +target_sources( + fortuno_example_serial_fpp_mylib PRIVATE + mylib.f90 +) + +add_executable(fortuno_example_serial_fpp_testapp) +set_target_properties( + fortuno_example_serial_fpp_testapp PROPERTIES + OUTPUT_NAME testapp +) +target_sources( + fortuno_example_serial_fpp_testapp PRIVATE + testapp.f90 + test_fixtured_fpp.F90 + test_fixtured_module_fpp.F90 + test_fixtured_suite_fpp.F90 + test_parametrized_fpp.F90 + test_simple_fpp.F90 +) +target_link_libraries( + fortuno_example_serial_fpp_testapp + PRIVATE + fortuno_example_serial_fpp_mylib + Fortuno::fortuno_serial +) diff --git a/example/serial-fpp/meson.build b/example/serial-fpp/meson.build new file mode 100644 index 0000000..5006dbe --- /dev/null +++ b/example/serial-fpp/meson.build @@ -0,0 +1,26 @@ +# This file is part of Fortuno. +# Licensed under the BSD-2-Clause Plus Patent license. +# SPDX-License-Identifier: BSD-2-Clause-Patent + +example_mylib_fpp_lib = library( + 'mylib', + sources: ['mylib.f90'], + install: false +) +example_mylib_fpp_dep = declare_dependency( + link_with: example_mylib_fpp_lib, +) + +example_testapp_exe = executable( + 'testapp', + sources: [ + 'test_fixtured_module_fpp.F90', + 'test_fixtured_suite_fpp.F90', + 'test_fixtured_fpp.F90', + 'test_parametrized_fpp.F90', + 'test_simple_fpp.F90', + 'testapp.f90', + ], + dependencies: [example_mylib_fpp_dep, fortuno_serial_dep], + install: false, +) diff --git a/example/serial-fpp/mylib.f90 b/example/serial-fpp/mylib.f90 new file mode 100644 index 0000000..7b8dbd5 --- /dev/null +++ b/example/serial-fpp/mylib.f90 @@ -0,0 +1,34 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Demo module/library to be tested +module mylib + implicit none + + private + public :: factorial + +contains + + !> Calculates the factorial of a number + function factorial(nn) result(fact) + + !> Number to calculate the factorial of + integer, intent(in) :: nn + + !> Factorial (note, there is no check made for integer overflow!) + integer :: fact + + integer :: ii + + fact = 1 + do ii = 2, nn + fact = fact * ii + end do + ! We create a "bug" which manifests only for certain input values + if (nn == 2 .or. nn > 10) fact = fact - 1 + + end function factorial + +end module mylib diff --git a/example/serial-fpp/test_fixtured_fpp.F90 b/example/serial-fpp/test_fixtured_fpp.F90 new file mode 100644 index 0000000..f58efd7 --- /dev/null +++ b/example/serial-fpp/test_fixtured_fpp.F90 @@ -0,0 +1,109 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_serial.fpp" + +!> Demo for realizing fixtured tests by overriding the run() method of the test_case object. +module test_fixtured_fpp + use mylib, only : factorial + use fortuno_serial, only : char_rep_int, is_equal, named_state, named_item,& + & suite => serial_suite_item, store_state => serial_store_state, serial_case_base, test_item,& + & test_list + implicit none + + private + public :: tests + + + ! Fixtured test case creating a random number before running a test procedure. + type, extends(serial_case_base) :: random_test_case + + ! Test procedure to be called after fixture setup had finished. + procedure(test_recursion_down), pointer, nopass :: proc + + contains + + ! Overrides run procedure to set up fixture before test procedure is invoked. + procedure :: run => random_test_case_run + + end type random_test_case + +contains + + + ! Returns the tests from this module. + function tests() + type(test_list) :: tests + + integer :: ii + + tests = test_list([& + suite("fixtured", test_list([& + [(random_test("recursion_down", test_recursion_down), ii = 1, 5)],& + [(random_test("recursion_up", test_recursion_up), ii = 1, 5)]& + ]))& + ]) + + end function tests + + + ! TEST n! = n * (n - 1)! + subroutine test_recursion_down(nn) + integer, intent(in) :: nn + CHECK(is_equal(factorial(nn), nn * factorial(nn - 1))) + end subroutine test_recursion_down + + + ! TEST (n + 1)! = (n + 1) * n! + subroutine test_recursion_up(nn) + integer, intent(in) :: nn + CHECK(is_equal(factorial(nn + 1), (nn + 1) * factorial(nn))) + end subroutine test_recursion_up + + + ! Returns a random_test_case instance wrapped as test_item to be used in an array constructor. + function random_test(name, proc) result(testitem) + character(*), intent(in) :: name + procedure(test_recursion_down) :: proc + type(test_item) :: testitem + + testitem = test_item(random_test_case(name=name, proc=proc)) + + end function random_test + + + ! Runs procedure of the random_test_case class. + subroutine random_test_case_run(this) + class(random_test_case), intent(in) :: this + + real :: rand + integer :: nn + + ! Set-up fixture by creating a random number + call random_number(rand) + + ! Note: factorial(n) with n > 13 overflows with 32 bit integers + nn = int(13 * rand) + 1 + + ! Store internal state (actual value of nn) to aid introspection/identification later + ! Workaround:gfortran:14.1 (bug 116679) + ! Omit array expression to avoid memory leak + ! {- + ! call store_state(& + ! named_state([& + ! named_item("n", char_rep_int(nn))& + ! &])& + ! ) + ! -}{+ + block + type(named_item) :: nameditems(1) + nameditems(1) = named_item("n", char_rep_int(nn)) + call store_state(named_state(nameditems)) + end block + call this%proc(nn) + ! +} + + end subroutine random_test_case_run + +end module test_fixtured_fpp diff --git a/example/serial-fpp/test_fixtured_module_fpp.F90 b/example/serial-fpp/test_fixtured_module_fpp.F90 new file mode 100644 index 0000000..88c5b74 --- /dev/null +++ b/example/serial-fpp/test_fixtured_module_fpp.F90 @@ -0,0 +1,96 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_serial.fpp" + +!> Demonstrates the realization of a global module wide fixture (not really recommended). +!! +!! Note: The test procedures in this example access the module variable containing the fixture data +!! directly via host association. This is a trade-off for more simplicity (in implementation) versus +!! less robustness. It must be ensured, that all tests accessing the module variable are within the +!! suite which sets up the global data. Additionally, none of the tests should the global module +!! variable to ensure the indepence of the tests. Latter could be automatically ensured by deriving +!! a new test case class from type(serial_case_base) which reads the module fixture and passes it to +!! test procedures as "intent(in)" argument(s). See the example on fixtured tests for more details. +!! +module test_fixtured_module_fpp + use mylib, only : factorial + use fortuno_serial, only : is_equal, test => serial_case_item, serial_suite_base, test_item,& + & test_list + implicit none + + private + public :: tests + + + ! Test suite initializing the global module variables during its setup. + type, extends(serial_suite_base) :: random_test_suite + contains + procedure :: set_up => random_test_suite_set_up + end type random_test_suite + + + ! Global module fixture variable + integer :: nn = 0 + +contains + + + ! Returns the tests from this module. + function tests() + type(test_list) :: tests + + tests = test_list([& + random_suite("fixtured_module", test_list([& + test("recursion_down", test_recursion_down),& + test("recursion_up", test_recursion_up)& + ]))& + ]) + + end function tests + + + ! TEST n! = n * (n - 1)! + ! + ! Note: uses the global module variable nn + ! + subroutine test_recursion_down() + CHECK(is_equal(factorial(nn), nn * factorial(nn - 1))) + end subroutine test_recursion_down + + + ! TEST (n + 1)! = (n + 1) * n! + ! + ! Note: uses the global module variable nn + ! + subroutine test_recursion_up() + CHECK(is_equal(factorial(nn + 1), (nn + 1) * factorial(nn))) + end subroutine test_recursion_up + + + ! Returns a random_test_suite instance wrapped as test_item to be used in array constructors. + function random_suite(name, tests) result(testitem) + character(*), intent(in) :: name + type(test_list), intent(in) :: tests + type(test_item) :: testitem + + testitem = test_item(random_test_suite(name=name, tests=tests)) + + end function random_suite + + + ! Initializes the test suite by generating and storing a random number in a module variable. + subroutine random_test_suite_set_up(this) + class(random_test_suite), intent(inout) :: this + + real :: rand + + call random_number(rand) + + ! Note: factorial(n) with n > 13 overflows with 32 bit integers + nn = int(13 * rand) + 1 + + end subroutine random_test_suite_set_up + +end module test_fixtured_module_fpp diff --git a/example/serial-fpp/test_fixtured_suite_fpp.F90 b/example/serial-fpp/test_fixtured_suite_fpp.F90 new file mode 100644 index 0000000..f813201 --- /dev/null +++ b/example/serial-fpp/test_fixtured_suite_fpp.F90 @@ -0,0 +1,149 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_serial.fpp" + +!> Demo for realizing fixtured suites providing common data for all tests within the suite. +module test_fixtured_suite_fpp + use mylib, only : factorial + use fortuno_serial, only : char_rep_int, is_equal, named_state, named_item, serial_case_base,& + & scope_pointers => serial_scope_pointers, store_state => serial_store_state,& + & serial_suite_base, test_item, test_list, test_ptr_item + implicit none + + private + public :: tests + + + ! Test suite containing data initialized through the set_up() procedure + type, extends(serial_suite_base) :: random_test_suite + integer :: nn = -1 + contains + procedure :: set_up => random_test_suite_set_up + end type random_test_suite + + + ! Customized test case reading the suite's data and passing it to the test procedure. + type, extends(serial_case_base) :: random_test_case + + ! Test procedure to be invoked for testing + procedure(test_recursion_down), pointer, nopass :: proc + + contains + + ! Overrides run procedure to pass hosting suite's data to test procedure + procedure :: run => random_test_case_run + + end type random_test_case + +contains + + + ! Returns the tests from this module. + function tests() + type(test_list) :: tests + + tests = test_list([& + random_suite("fixtured_suite", test_list([& + random_test("recursion_down", test_recursion_down),& + random_test("recursion_up", test_recursion_up)& + ]))& + ]) + + end function tests + + + ! TEST n! = n * (n - 1)! + subroutine test_recursion_down(nn) + integer, intent(in) :: nn + CHECK(is_equal(factorial(nn), nn * factorial(nn - 1))) + end subroutine test_recursion_down + + + ! TEST (n + 1)! = (n + 1) * n! + subroutine test_recursion_up(nn) + integer, intent(in) :: nn + CHECK(is_equal(factorial(nn + 1), (nn + 1) * factorial(nn))) + end subroutine test_recursion_up + + + ! Returns a random_test_suite instance wrapped as test_item to be used in array constructors. + function random_suite(name, tests) result(testitem) + character(*), intent(in) :: name + type(test_list), intent(in) :: tests + type(test_item) :: testitem + + testitem = test_item(random_test_suite(name=name, tests=tests)) + + end function random_suite + + + ! Initializes the test suite by generating and storing a random number. + subroutine random_test_suite_set_up(this) + class(random_test_suite), intent(inout) :: this + + real :: rand + + call random_number(rand) + + ! Note: factorial(n) with n > 13 overflows with 32 bit integers + this%nn = int(13 * rand) + 1 + + ! Store internal state to aid introspection/identification later + ! Workaround:gfortran:14.1 (bug 116679) + ! Omit array expression to avoid memory leak + ! {- + ! call store_state(& + ! named_state([& + ! named_item("n", char_rep_int(this%nn))& + ! &])& + ! ) + ! -}{+ + block + type(named_item) :: nameditems(1) + nameditems(1) = named_item("n", char_rep_int(this%nn)) + call store_state(named_state(nameditems)) + end block + ! +} + + end subroutine random_test_suite_set_up + + + ! Returns a random_test_case instance wrapped as test_item to be used in array constructors. + function random_test(name, proc) result(testitem) + character(*), intent(in) :: name + procedure(test_recursion_down) :: proc + type(test_item) :: testitem + + testitem = test_item(random_test_case(name=name, proc=proc)) + + end function random_test + + + ! Customize run procedure of the random_test_case class reading the hosting suite's data. + subroutine random_test_case_run(this) + class(random_test_case), intent(in) :: this + + type(test_ptr_item), allocatable :: scopeptrs(:) + integer :: nn + + nn = -1 + scopeptrs = scope_pointers() + ! scopeptrs(1): current scope - random_test_case instance + ! scopeptrs(2): first enclosing scope - random_test_suite instance + if (size(scopeptrs) < 2)& + & error stop "test_fixtured_suite_fpp::random_test_case_run: Size of scopeptrs too small" + select type (suite => scopeptrs(2)%item) + type is (random_test_suite) + nn = suite%nn + class default + error stop "test_fixtured_suite_fpp::random_test_case_run: Expected random_test_suite& + & instance, but obtained something else" + end select + + call this%proc(nn) + + end subroutine random_test_case_run + +end module test_fixtured_suite_fpp diff --git a/example/serial-fpp/test_parametrized_fpp.F90 b/example/serial-fpp/test_parametrized_fpp.F90 new file mode 100644 index 0000000..8335852 --- /dev/null +++ b/example/serial-fpp/test_parametrized_fpp.F90 @@ -0,0 +1,76 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_serial.fpp" + +!> Demonstrates a possible realization of parametrized tests. +module test_parametrized_fpp + use mylib, only : factorial + use fortuno_serial, only : as_char, is_equal, serial_case_base, suite => serial_suite_item,& + & test_item, test_list + implicit none + + private + public :: tests + + + !> Contains argument and expected result of a factorial() invokation + type :: arg_res + integer :: arg, res + end type + + !> Argument/result pairs to check for + type(arg_res), parameter :: testcaseparams(*) = [& + & arg_res(1, 1), arg_res(2, 2), arg_res(3, 6), arg_res(4, 24), arg_res(5, 120)& + & ] + + + !> Parametrized test checking for an individual argument/result pair. + type, extends(serial_case_base) :: parametrized_test_case + type(arg_res) :: argres + contains + procedure :: run => parametrized_test_case_run + end type parametrized_test_case + +contains + + + !> Returns the tests of this module. + function tests() + type(test_list) :: tests + + integer :: ii + + tests = test_list([& + suite("parametrized", test_list([& + (parametrized_test("factorial", testcaseparams(ii)), ii = 1, size(testcaseparams))& + ]))& + ]) + + end function tests + + + !> Convenience function to generate a parametrized test item (to be used in an array constructor) + function parametrized_test(prefix, argres) result(testitem) + character(*), intent(in) :: prefix + type(arg_res), intent(in) :: argres + type(test_item) :: testitem + + character(:), allocatable :: name + + name = prefix // "_" // as_char(argres%arg) + testitem = test_item(parametrized_test_case(name=name, argres=argres)) + + end function parametrized_test + + + !> Run method of the parametrized test (executing the check directly) + subroutine parametrized_test_case_run(this) + class(parametrized_test_case), intent(in) :: this + + CHECK(is_equal(factorial(this%argres%arg), this%argres%res)) + + end subroutine parametrized_test_case_run + +end module test_parametrized_fpp diff --git a/example/serial-fpp/test_simple_fpp.F90 b/example/serial-fpp/test_simple_fpp.F90 new file mode 100644 index 0000000..73c9e14 --- /dev/null +++ b/example/serial-fpp/test_simple_fpp.F90 @@ -0,0 +1,51 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_serial.fpp" + +!> Demonstrates the simplest possible testing scenario +module test_simple_fpp + use mylib, only : factorial + use fortuno_serial, only : is_equal, test => serial_case_item, suite => serial_suite_item,& + & test_list + implicit none + + private + public :: tests + +contains + + + ! Returns the tests from this module. + function tests() + type(test_list) :: tests + + tests = test_list([& + test("factorial_0", test_factorial_0),& + suite("simple", test_list([& + test("factorial_1", test_factorial_1),& + test("factorial_2", test_factorial_2)& + ]))& + ]) + + end function tests + + ! Test: 0! = 1 + subroutine test_factorial_0() + CHECK(factorial(0) == 1) + end subroutine test_factorial_0 + + ! Test: 1! = 1 + subroutine test_factorial_1() + CHECK(factorial(1) == 1) + end subroutine test_factorial_1 + + ! Test: 2! = 2 (will fail due to the bug in the implementation of the factorial function) + subroutine test_factorial_2() + ! Two failing checks, you should see info about both in the output + CHECK_MSG(is_equal(factorial(2), 2), "Test failed for demonstration purposes") + CHECK(factorial(2) == 2) + end subroutine test_factorial_2 + +end module test_simple_fpp diff --git a/example/serial-fpp/testapp.f90 b/example/serial-fpp/testapp.f90 new file mode 100644 index 0000000..f50eeae --- /dev/null +++ b/example/serial-fpp/testapp.f90 @@ -0,0 +1,23 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +!> Test app with command line interface, collecting and executing the tests. +program testapp + use fortuno_serial, only : execute_serial_cmd_app, test_list + use test_fixtured_fpp, only : fixtured_fpp_tests => tests + use test_parametrized_fpp, only : parametrized_fpp_tests => tests + use test_simple_fpp, only : simple_fpp_tests => tests + use test_fixtured_suite_fpp, only : fixtured_suite_fpp_tests => tests + use test_fixtured_module_fpp, only : fixtured_module_fpp_tests => tests + implicit none + + call execute_serial_cmd_app(test_list([& + simple_fpp_tests(),& + parametrized_fpp_tests(),& + fixtured_fpp_tests(),& + fixtured_suite_fpp_tests(),& + fixtured_module_fpp_tests()& + ])) + +end program testapp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 2a2ff81..64c1351 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -2,8 +2,10 @@ # Licensed under the BSD-2-Clause Plus Patent license. # SPDX-License-Identifier: BSD-2-Clause-Patent -# Introduce a fake target associated with the location of the folder containing the include file. -# Query the INTERFACE_INCLUDE_DIRECTORIES of the target to obtain the include folder location. +# Introduce a fake target associated with the location of the folder containing the include files. +# Link the target with target_link_libraries() to pass the folder as an additional search path for +# include files to the compiler.. Alternatively, query the INTERFACE_INCLUDE_DIRECTORIES of the +# target to extract the include folder location. add_library(fortuno_include_dir INTERFACE) target_include_directories( fortuno_include_dir INTERFACE @@ -19,21 +21,21 @@ if (FORTUNO_INSTALL) ) if (FORTUNO_WITH_SERIAL) install( - FILES fortuno_serial.fypp + FILES fortuno_serial.fpp fortuno_serial.fypp DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT Fortuno_development ) endif () if (FORTUNO_WITH_MPI) install( - FILES fortuno_mpi.fypp + FILES fortuno_mpi.fpp fortuno_mpi.fypp DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT Fortuno_development ) endif () if (FORTUNO_WITH_COARRAY) install( - FILES fortuno_coarray.fypp + FILES fortuno_coarray.fpp fortuno_coarray.fypp DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT Fortuno_development ) diff --git a/include/fortuno_coarray.fpp b/include/fortuno_coarray.fpp new file mode 100644 index 0000000..42094fc --- /dev/null +++ b/include/fortuno_coarray.fpp @@ -0,0 +1,30 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#ifndef __FORTUNO_COARRAY_FPP__ +#define __FORTUNO_COARRAY_FPP__ + +#define CHECK(ctx, cond)\ + block;\ + call ctx%check(cond, file=__FILE__, line=__LINE__);\ + end block; + +#define CHECK_MSG(ctx, cond, msg)\ + block;\ + call ctx%check(cond, msg, file=__FILE__, line=__LINE__);\ + end block; + +#define ASSERT(ctx, cond)\ + block;\ + call ctx%check(cond, file=__FILE__, line=__LINE__);\ + if (ctx%check_failed()) return;\ + end block; + +#define ASSERT_MSG(ctx, cond, msg)\ + block;\ + call ctx%check(cond, msg, file=__FILE__, line=__LINE__);\ + if (ctx%check_failed()) return;\ + end block; + +#endif diff --git a/include/fortuno_coarray.fypp b/include/fortuno_coarray.fypp index 62d050d..3ff1d43 100644 --- a/include/fortuno_coarray.fypp +++ b/include/fortuno_coarray.fypp @@ -86,7 +86,7 @@ #! #:def ASSERT(cond, **kwargs) $:CHECK(cond, ctxvar="ctx", **kwargs) -if (${ctxvar}$%failed()) return +if (${ctxvar}$%check_failed()) return #:enddef diff --git a/include/fortuno_mpi.fpp b/include/fortuno_mpi.fpp new file mode 100644 index 0000000..758472e --- /dev/null +++ b/include/fortuno_mpi.fpp @@ -0,0 +1,34 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#ifndef __FORTUNO_MPI_FPP__ +#define __FORTUNO_MPI_FPP__ + +#define CHECK(cond)\ + block;\ + use fortuno_mpi, only : mpi_check;\ + call mpi_check(cond, file=__FILE__, line=__LINE__);\ + end block; + +#define CHECK_MSG(cond, msg)\ + block;\ + use fortuno_mpi, only : mpi_check;\ + call mpi_check(cond, msg, file=__FILE__, line=__LINE__);\ + end block; + +#define ASSERT(cond)\ + block;\ + use fortuno_mpi, only : mpi_check, mpi_check_failed;\ + call mpi_check(cond, file=__FILE__, line=__LINE__);\ + if (mpi_check_failed()) return;\ + end block; + +#define ASSERT_MSG(cond, msg)\ + block;\ + use fortuno_mpi, only : mpi_check, mpi_check_failed;\ + call mpi_check(cond, msg, file=__FILE__, line=__LINE__);\ + if (mpi_check_failed()) return;\ + end block; + +#endif diff --git a/include/fortuno_mpi.fypp b/include/fortuno_mpi.fypp index 1aa8a68..746bea4 100644 --- a/include/fortuno_mpi.fypp +++ b/include/fortuno_mpi.fypp @@ -81,7 +81,7 @@ #! #:def ASSERT(cond, **kwargs) $:CHECK(cond, **kwargs) -if (mpi_failed()) return +if (mpi_check_failed()) return #:enddef diff --git a/include/fortuno_serial.fypp b/include/fortuno_serial.fypp index e0d0fc7..76126c2 100644 --- a/include/fortuno_serial.fypp +++ b/include/fortuno_serial.fypp @@ -81,7 +81,7 @@ #! #:def ASSERT(cond, **kwargs) $:CHECK(cond, **kwargs) -if (serial_failed()) return +if (serial_check_failed()) return #:enddef diff --git a/meson.build b/meson.build index ac3e131..ac1599d 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ fortuno_lib = library( fortuno_dep = declare_dependency( link_with: fortuno_lib, + include_directories: 'include', ) if with_serial diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e15670..4696b9f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,9 @@ add_subdirectory(fortuno) add_library(Fortuno::fortuno ALIAS fortuno) list(APPEND _installed_targets "fortuno") +# Propagate include directory, so that all user projects using Fortuno can automatically access it +target_link_libraries(fortuno PUBLIC Fortuno::fortuno_include_dir) + if (FORTUNO_WITH_SERIAL) diff --git a/test/export/coarray/app/CMakeLists.txt b/test/export/coarray/app/CMakeLists.txt index c4e4b6a..0c5c28f 100644 --- a/test/export/coarray/app/CMakeLists.txt +++ b/test/export/coarray/app/CMakeLists.txt @@ -13,6 +13,11 @@ target_link_libraries(testapp PRIVATE Fortuno::fortuno_coarray) target_compile_options(testapp PRIVATE "${fflags_coarray}") target_link_options(testapp PRIVATE "${ldflags_coarray}") +add_executable(testapp_fpp) +target_sources(testapp_fpp PRIVATE testapp_fpp.F90) +target_link_libraries(testapp_fpp PRIVATE Fortuno::fortuno_coarray) +target_compile_options(testapp_fpp PRIVATE "${fflags_coarray}") +target_link_options(testapp_fpp PRIVATE "${ldflags_coarray}") if (FYPP) add_executable(testapp_fypp) diff --git a/test/export/coarray/app/meson.build b/test/export/coarray/app/meson.build index ac041e5..f52464c 100644 --- a/test/export/coarray/app/meson.build +++ b/test/export/coarray/app/meson.build @@ -5,3 +5,6 @@ testapp_srcs += files( 'testapp.f90' ) +testapp_fpp_srcs += files( + 'testapp_fpp.F90' +) diff --git a/test/export/coarray/app/testapp_fpp.F90 b/test/export/coarray/app/testapp_fpp.F90 new file mode 100644 index 0000000..2ebdf17 --- /dev/null +++ b/test/export/coarray/app/testapp_fpp.F90 @@ -0,0 +1,49 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_coarray.fpp" + +!> Unit tests +module testapp_coarray_fpp_tests + use fortuno_coarray, only : context => coa_context, test => coa_pure_case_item, is_equal,& + & test_list + implicit none + +contains + + + function tests() + type(test_list) :: tests + + tests = test_list([& + test("success", test_success)& + ]) + + end function tests + + + subroutine test_success(ctx) + class(context), intent(inout) :: ctx + + integer :: buffer + + buffer = 0 + if (this_image() == 1) buffer = 1 + call co_broadcast(buffer, 1) + CHECK(ctx, is_equal(buffer, 1)) + + end subroutine test_success + +end module testapp_coarray_fpp_tests + + +!> Test app driving Fortuno unit tests +program testapp + use fortuno_coarray, only : execute_coa_cmd_app + use testapp_coarray_fpp_tests, only : tests + implicit none + + call execute_coa_cmd_app(tests()) + +end program testapp diff --git a/test/export/coarray/fpm.toml b/test/export/coarray/fpm.toml index 54bf03a..7d00bbc 100644 --- a/test/export/coarray/fpm.toml +++ b/test/export/coarray/fpm.toml @@ -25,3 +25,7 @@ fortuno-coarray = { path = "../../../" } [[executable]] name = "testapp" main = "testapp.f90" + +[[executable]] +name = "testapp_fpp" +main = "testapp_fpp.F90" diff --git a/test/export/coarray/meson.build b/test/export/coarray/meson.build index 86961d3..9ef6452 100644 --- a/test/export/coarray/meson.build +++ b/test/export/coarray/meson.build @@ -16,6 +16,7 @@ fflags_coarray = get_option('fflags_coarray') ldflags_coarray = get_option('ldflags_coarray') testapp_deps = [] +testapp_fpp_deps = [] fortuno_coarray_dep = dependency( 'fortuno-coarray', @@ -23,10 +24,12 @@ fortuno_coarray_dep = dependency( default_options: {'fflags_coarray': fflags_coarray, 'ldflags_coarray': ldflags_coarray}, ) testapp_deps += fortuno_coarray_dep +testapp_fpp_deps += fortuno_coarray_dep ### Building the app ### testapp_srcs = [] +testapp_fpp_srcs = [] subdir('app') testapp_exe = executable( @@ -36,3 +39,10 @@ testapp_exe = executable( fortran_args: fflags_coarray, link_args: ldflags_coarray, ) +testapp_fpp_exe = executable( + 'testapp_fpp', + sources: testapp_fpp_srcs, + dependencies: testapp_fpp_deps, + fortran_args: fflags_coarray, + link_args: ldflags_coarray, +) diff --git a/test/export/mpi/app/CMakeLists.txt b/test/export/mpi/app/CMakeLists.txt index faedf8d..3ecdfe0 100644 --- a/test/export/mpi/app/CMakeLists.txt +++ b/test/export/mpi/app/CMakeLists.txt @@ -6,6 +6,10 @@ add_executable(testapp) target_sources(testapp PRIVATE testapp.f90) target_link_libraries(testapp PRIVATE Fortuno::fortuno_mpi MPI::MPI_Fortran) +add_executable(testapp_fpp) +target_sources(testapp_fpp PRIVATE testapp_fpp.F90) +target_link_libraries(testapp_fpp PRIVATE Fortuno::fortuno_mpi MPI::MPI_Fortran) + if (FYPP) add_executable(testapp_fypp) diff --git a/test/export/mpi/app/meson.build b/test/export/mpi/app/meson.build index ac041e5..f52464c 100644 --- a/test/export/mpi/app/meson.build +++ b/test/export/mpi/app/meson.build @@ -5,3 +5,6 @@ testapp_srcs += files( 'testapp.f90' ) +testapp_fpp_srcs += files( + 'testapp_fpp.F90' +) diff --git a/test/export/mpi/app/testapp_fpp.F90 b/test/export/mpi/app/testapp_fpp.F90 new file mode 100644 index 0000000..62639a3 --- /dev/null +++ b/test/export/mpi/app/testapp_fpp.F90 @@ -0,0 +1,47 @@ +! This file is part of Fortuno. +! Licensed under the BSD-2-Clause Plus Patent license. +! SPDX-License-Identifier: BSD-2-Clause-Patent + +#include "fortuno_mpi.fpp" + +!> Unit tests +module testapp_mpi_fpp_tests + use mpi_f08, only : mpi_bcast, MPI_INTEGER + use fortuno_mpi, only : global_comm, is_equal, test => mpi_case_item, test_list, this_rank + implicit none + +contains + + subroutine test_success() + + integer :: buffer + + buffer = 0 + if (this_rank() == 0) buffer = 1 + call mpi_bcast(buffer, 1, MPI_INTEGER, 0, global_comm()) + CHECK(is_equal(buffer, 1)) + + end subroutine test_success + + + function tests() + type(test_list) :: tests + + tests = test_list([& + test("success", test_success)& + ]) + + end function tests + +end module testapp_mpi_fpp_tests + + +!> Test app driving Fortuno unit tests +program testapp + use fortuno_mpi, only : execute_mpi_cmd_app + use testapp_mpi_fpp_tests, only : tests + implicit none + + call execute_mpi_cmd_app(tests()) + +end program testapp diff --git a/test/export/mpi/fpm.toml b/test/export/mpi/fpm.toml index 9a822db..ff621dc 100644 --- a/test/export/mpi/fpm.toml +++ b/test/export/mpi/fpm.toml @@ -25,4 +25,8 @@ mpi = "*" [[executable]] name = "testapp" -main = "testapp.f90" \ No newline at end of file +main = "testapp.f90" + +[[executable]] +name = "testapp_fpp" +main = "testapp_fpp.F90" \ No newline at end of file diff --git a/test/export/mpi/meson.build b/test/export/mpi/meson.build index 5ff2066..0b4d33c 100644 --- a/test/export/mpi/meson.build +++ b/test/export/mpi/meson.build @@ -9,14 +9,18 @@ project( ) testapp_deps = [] +testapp_fpp_deps = [] fortran_mpi_dep = dependency('mpi', language: 'fortran', required: true) testapp_deps += fortran_mpi_dep +testapp_fpp_deps += fortran_mpi_dep fortuno_mpi_dep = dependency('fortuno-mpi', fallback: ['fortuno', 'fortuno_mpi_dep']) testapp_deps += fortuno_mpi_dep +testapp_fpp_deps += fortuno_mpi_dep testapp_srcs = [] +testapp_fpp_srcs = [] subdir('app') testapp_exe = executable( @@ -24,3 +28,8 @@ testapp_exe = executable( sources: testapp_srcs, dependencies: testapp_deps, ) +testapp_exe = executable( + 'testapp_fpp', + sources: testapp_fpp_srcs, + dependencies: testapp_fpp_deps, +) diff --git a/test/export/serial/app/CMakeLists.txt b/test/export/serial/app/CMakeLists.txt index f55fe28..3ff32e8 100644 --- a/test/export/serial/app/CMakeLists.txt +++ b/test/export/serial/app/CMakeLists.txt @@ -3,10 +3,13 @@ # SPDX-License-Identifier: BSD-2-Clause-Patent add_executable(testapp) - target_sources(testapp PRIVATE testapp.f90) target_link_libraries(testapp PRIVATE Fortuno::fortuno_serial) +add_executable(testapp_fpp) +target_sources(testapp_fpp PRIVATE testapp_fpp.F90) +target_link_libraries(testapp_fpp PRIVATE Fortuno::fortuno_serial) + if (FYPP) add_executable(testapp_fypp) diff --git a/test/export/serial/app/meson.build b/test/export/serial/app/meson.build index cadf8da..667d270 100644 --- a/test/export/serial/app/meson.build +++ b/test/export/serial/app/meson.build @@ -5,3 +5,6 @@ testapp_sources += files( 'testapp.f90' ) +testapp_fpp_sources += files( + 'testapp_fpp.F90' +) \ No newline at end of file diff --git a/test/export/serial/app/testapp_fpp.F90 b/test/export/serial/app/testapp_fpp.F90 index 4b36ebc..114d72a 100644 --- a/test/export/serial/app/testapp_fpp.F90 +++ b/test/export/serial/app/testapp_fpp.F90 @@ -6,12 +6,9 @@ !> Unit tests module testapp_fpp_tests - use fortuno_serial, only : is_equal, test => serial_case_item, test_item + use fortuno_serial, only : is_equal, test => serial_case_item, test_list implicit none - private - public :: test_items - contains @@ -20,24 +17,24 @@ subroutine test_success() end subroutine test_success - function test_items() result(testitems) - type(test_item), allocatable :: testitems(:) + function tests() + type(test_list) :: tests - testitems = [& + tests = test_list([& test("success", test_success)& - ] + ]) - end function test_items + end function tests end module testapp_fpp_tests !> Test app driving Fortuno unit tests program testapp_fpp - use testapp_fpp_tests, only : test_items use fortuno_serial, only : execute_serial_cmd_app + use testapp_fpp_tests, only : tests implicit none - call execute_serial_cmd_app(testitems=test_items()) + call execute_serial_cmd_app(tests()) end program testapp_fpp diff --git a/test/export/serial/fpm.toml b/test/export/serial/fpm.toml index c8fa96a..a306c72 100644 --- a/test/export/serial/fpm.toml +++ b/test/export/serial/fpm.toml @@ -24,4 +24,8 @@ fortuno = { path = "../../../" } [[executable]] name = "testapp" -main = "testapp.f90" \ No newline at end of file +main = "testapp.f90" + +[[executable]] +name = "testapp_fpp" +main = "testapp_fpp.F90" \ No newline at end of file diff --git a/test/export/serial/meson.build b/test/export/serial/meson.build index 5ea3d99..c7097c7 100644 --- a/test/export/serial/meson.build +++ b/test/export/serial/meson.build @@ -9,11 +9,14 @@ project( ) testapp_deps = [] +testapp_fpp_deps = [] fortuno_serial_dep = dependency('fortuno-serial', fallback: ['fortuno', 'fortuno_serial_dep']) testapp_deps += fortuno_serial_dep +testapp_fpp_deps += fortuno_serial_dep testapp_sources = [] +testapp_fpp_sources = [] subdir('app') testapp_exe = executable( @@ -21,3 +24,8 @@ testapp_exe = executable( sources: testapp_sources, dependencies: testapp_deps, ) +testapp_fpp_exe = executable( + 'testapp_fpp', + sources: testapp_fpp_sources, + dependencies: testapp_fpp_deps, +)