Skip to content

Commit

Permalink
Kick-off project
Browse files Browse the repository at this point in the history
  • Loading branch information
aradi committed Feb 20, 2024
0 parents commit 03b2902
Show file tree
Hide file tree
Showing 29 changed files with 3,538 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/_*
/build
*.mod
47 changes: 47 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Copyright (c) 2024 Fortuno authors

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

Subject to the terms and conditions of this license, each copyright holder and
contributor hereby grants to those receiving rights under this license a
perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except for failure to satisfy the conditions of this license) patent license to
make, have made, use, offer to sell, sell, import, and otherwise transfer this
software, where such license applies only to those patent claims, already
acquired or hereafter acquired, licensable by such copyright holder or
contributor that are necessarily infringed by:

(a) their Contribution(s) (the licensed copyrights of copyright holders and
non-copyrightable additions of contributors, in source or binary form)
alone; or

(b) combination of their Contribution(s) with the work of authorship to which
such Contribution(s) was added by such copyright holder or contributor, if,
at the time the Contribution is added, such addition causes such combination
to be necessarily infringed. The patent license shall not apply to any other
combinations which include the Contribution.

Except as expressly stated above, no rights or licenses from any copyright
holder or contributor is granted under this license, whether expressly, by
implication, estoppel or otherwise.

DISCLAIMER

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 changes: 67 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
*******************************************************
Fortuno – extensible unit testing framework for Fortran
*******************************************************

The **Fortuno** (Fortran Unit Testing Objects) project offers a flexible,
modern, object oriented unit testing framework for the Fortran language. It puts
strong emphasis on the simplicity of the user interface (minimizing the amount
of boiler plate code when writing unit tests) as well as to modularity and
extensibility (offering building blocks for customized unit testing systems.)

It is written in Fortran 2018 and can be directly used without a need for a
special pre-processor.

**Fortuno** provides

- simple unit tests,

- fixtured tests,

- parameterized tests,

- serial unit testing,

- parallel unit testing for MPI- and coarray-parallel projects, and

- seamless integration with the CMake and Fpm build systems.

Detailed **documentation** is available on the `Fortuno documentation page
<https://fortuno.readthedocs.io>`_. You can also have a look at some of the
example files in the `example folder <example/>`_.

The development can be followed on the `Fortuno project page
<https://github.com/fortuno-repos/fortuno>`_ on GitHub.


Known issues
============

In order to be flexible, extensible and simple, Fortuno uses modern Fortran
constructs extensively. Unfortunately, this seems to be still challenging for
some compilers. The following table gives an overview over the compilers which
were tested for building Fortuno.

+------------------------+-----------------------------------------------------+
| Compiler | Status |
+========================+=====================================================+
| Intel 2024.0 | * serial: OK |
| x86_64/Linux | * mpi (with Intel MPI): OK |
+------------------------+-----------------------------------------------------+
| NAG 7.1 (build 7145) | * serial: OK |
| x86_64/Linux | * mpi (MPICH 4.1): OK |
+------------------------+-----------------------------------------------------+
| GNU 13.2 | * serial: Failed (Internal compiler error) |
| x86_64/Linux | |
+------------------------+-----------------------------------------------------+

If you are aware of other compilers being able to build Fortuno, open an issue
or a pull request, so that we can update the table accordingly.


License
=======

Fortuno is licensed under the `BSD-2-Clause Plus Patent License
<https://opensource.org/licenses/BSDplusPatent>`_. The SPDX license identifier
for this project is `BSD-2-Clause-Patent
<https://spdx.org/licenses/BSD-2-Clause-Patent.html>`_.
82 changes: 82 additions & 0 deletions config.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#
# Global config options
#

# MPI support
option(WITH_MPI "Whether MPI support should be enabled" FALSE)

# Coarray support
option(WITH_COARRAY "Whether coarray support should be enabled" FALSE)

# Type of the built libraries
option(BUILD_SHARED_LIBS "Whether libraries built should be shared" FALSE)

# Whether examples should be built
option(WITH_EXAMPLES "Whether examples should be built" TRUE)


#
# Compiler dependent config options
#

if("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU")

# Specific settings for the GNU compiler

set(Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -std=f2018"
CACHE STRING "General Fortran compiler flags")

set(Fortran_FLAGS_RELEASE "-O2 -funroll-all-loops"
CACHE STRING "Extra Fortran compiler flags for Release build")

set(Fortran_FLAGS_DEBUG "-g -Wall -pedantic -fbounds-check"
CACHE STRING "Extra Fortran compiler flags for Debug build")

set(Fortran_COARRAY_FLAG "-fcoarray=lib" CACHE STRING "Coarray flag of the Fortran compiler")

elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "IntelLLVM")

# Specific settings for the Intel compiler

set(Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -stand f18 -diag-error-limit 1"
CACHE STRING "General Fortran compiler flags")

set(Fortran_FLAGS_RELEASE "-O2"
CACHE STRING "Extra Fortran compiler flags for Release build")

set(Fortran_FLAGS_DEBUG "-g -warn all -check all,nouninit -traceback"
CACHE STRING "Extra Fortran compiler flags for Debug build")

set(Fortran_COARRAY_FLAG "-coarray" CACHE STRING "Coarray flag of the Fortran compiler")

elseif("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "NAG")

# Specific settings for the NAG compiler

set(Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -f2018"
CACHE STRING "General Fortran compiler flags")

set(Fortran_FLAGS_RELEASE "-O3"
CACHE STRING "Extra Fortran compiler flags for Release build")

set(Fortran_FLAGS_DEBUG "-g -nan -C=all"
CACHE STRING "Extra Fortran compiler flags for Debug build")

set(Fortran_COARRAY_FLAG "-coarray" CACHE STRING "Coarray flag of the Fortran compiler")

else()

# Generic compiler settings (using CMake's default values)

set(Fortran_FLAGS "${CMAKE_Fortran_FLAGS}"
CACHE STRING "General Fortran compiler flags")

set(Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}"
CACHE STRING "Extra Fortran compiler flags for Release build")

set(Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}"
CACHE STRING "Extra compiler flags for Debug build")

set(Fortran_COARRAY_FLAG "" CACHE STRING "Coarray flag of the Fortran compiler")

endif()
87 changes: 87 additions & 0 deletions example/fixtured_tests.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
! This file is part of Fortuno.
! Licensed under the BSD-2-Clause Plus Patent license.
! SPDX-License-Identifier: BSD-2-Clause-Patent

module fixtured_tests
use mylib, only : factorial
use fortuno, only : check => serial_check, test => serial_case_item,&
& suite => serial_suite_item, test_item, test_ptr_item,&
& serial_suite, serial_case_base
implicit none

private
public :: get_fixtured_tests

type, extends(serial_case_base) :: random_test_case
integer :: nn = -1
procedure(test_recursion_down), pointer, nopass :: proc
contains
procedure :: run => random_test_case_run
procedure :: get_as_char => random_test_case_get_as_char
end type random_test_case

contains

! Returns the tests from this module.
function get_fixtured_tests() result(testitems)
type(test_item), allocatable :: testitems(:)

integer :: ii

testitems = [&
suite("fixtured", [&
[(random_test("recursion_down", test_recursion_down), ii = 1, 5)],&
[(random_test("recursion_up", test_recursion_up), ii = 1, 5)]&
])&
]

end function get_fixtured_tests


subroutine test_recursion_down(nn)
integer, intent(in) :: nn
call check(factorial(nn) == nn * factorial(nn - 1))
end subroutine test_recursion_down


subroutine test_recursion_up(nn)
integer, intent(in) :: nn
call check(factorial(nn + 1) == (nn + 1) * factorial(nn))
end subroutine test_recursion_up



function random_test(name, proc) result(testitem)
character(*), intent(in) :: name
procedure(test_recursion_down) :: proc
type(test_item) :: testitem

testitem%item = random_test_case(name=name, proc=proc)

end function random_test


subroutine random_test_case_run(this)
class(random_test_case), intent(inout) :: this

real :: rand

call random_number(rand)
this%nn = int(20.0 * rand) + 1
call this%proc(this%nn)

end subroutine random_test_case_run


subroutine random_test_case_get_as_char(this, repr)
class(random_test_case), intent(in) :: this
character(:), allocatable, intent(out) :: repr

character(4) :: buffer

write(buffer, "(a2, i2.2)") "n=", this%nn
repr = buffer

end subroutine random_test_case_get_as_char

end module fixtured_tests
32 changes: 32 additions & 0 deletions example/mylib.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
! 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

end function factorial

end module mylib
54 changes: 54 additions & 0 deletions example/simple_tests.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
! This file is part of Fortuno.
! Licensed under the BSD-2-Clause Plus Patent license.
! SPDX-License-Identifier: BSD-2-Clause-Patent

module simple_tests
use mylib, only : factorial
use fortuno, only : is_equal, test => serial_case_item, check => serial_check,&
& suite => serial_suite_item, test_item
implicit none

private
public :: get_simple_tests

contains

! Returns the tests from this module.
function get_simple_tests() result(testitems)
type(test_item), allocatable :: testitems(:)

testitems = [&
! Adding a single test
test("factorial_0", test_factorial_0),&

! Packing further tests into a suite in order to introduce more structure
! (e.g. running only tests being part of a given suite)
suite("mysuite", [&
test("factorial_1", test_factorial_1),&
test("factorial_2", test_factorial_2)&
])&
]

end function get_simple_tests

! Test: 0! = 1
subroutine test_factorial_0()
call check(factorial(0) == 1)
end subroutine test_factorial_0

! Test: 1! = 1
subroutine test_factorial_1()
call check(factorial(1) == 1)
end subroutine test_factorial_1

! Test: 2! = 2 (will fail to demonstrate the output of a failing test)
subroutine test_factorial_2()
! Two failing checks, you should see info about both in the output
call check(is_equal(factorial(2), 3),&
& msg="Test failed for demonstration purposes",&
& file="simple_tests.f90",&
& line=43)
call check(factorial(2) == 3)
end subroutine test_factorial_2

end module simple_tests
19 changes: 19 additions & 0 deletions example/testapp.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
! 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, only : execute_serial_cmd_app
use simple_tests, only : get_simple_tests
use fixtured_tests, only : get_fixtured_tests
implicit none

call execute_serial_cmd_app(&
testitems=[&
get_simple_tests(),&
get_fixtured_tests()&
]&
)

end program testapp
Loading

0 comments on commit 03b2902

Please sign in to comment.