From fa95858d9c5b9132a812c1d82a9a3760e95c680c Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 18:48:12 +0200 Subject: [PATCH] Implementing ctest-friendly tests for /maths --- .github/workflows/ci.yml | 2 +- modules/maths/euclid_gcd.f90 | 12 ++++ modules/maths/fibonacci.f90 | 16 ++++- tests/maths/eculid_gcd.f90 | 94 +++++++++++++++++++++++++++ tests/maths/factorial.f90 | 87 +++++++++++++++++++++++++ tests/maths/fibonacci.f90 | 121 +++++++++++++++++++++++++++++++++++ 6 files changed, 329 insertions(+), 3 deletions(-) create mode 100644 tests/maths/eculid_gcd.f90 create mode 100644 tests/maths/factorial.f90 create mode 100644 tests/maths/fibonacci.f90 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c0fbb9..55b0e37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: - name: Test working-directory: ${{env.build_path}} - run: ctest + run: ctest --output-on-failure - name: Run examples working-directory: ${{env.build_path}} diff --git a/modules/maths/euclid_gcd.f90 b/modules/maths/euclid_gcd.f90 index 0c2990f..24dba82 100644 --- a/modules/maths/euclid_gcd.f90 +++ b/modules/maths/euclid_gcd.f90 @@ -1,4 +1,12 @@ !> Module implementing the Euclidean Algorithm for GCD +!! +!! Modified by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #31 +!! https://github.com/TheAlgorithms/Fortran/pull/31 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! !! Reference: https://en.wikipedia.org/wiki/Euclidean_algorithm module gcd_module @@ -10,6 +18,10 @@ function gcd(a, b) result(val) integer, value :: a, b integer :: t, val + ! Ensure the GCD is non-negative + a = abs(a) + b = abs(b) + ! Euclidean algorithm for GCD do while (b /= 0) t = b diff --git a/modules/maths/fibonacci.f90 b/modules/maths/fibonacci.f90 index 606e483..9a36358 100644 --- a/modules/maths/fibonacci.f90 +++ b/modules/maths/fibonacci.f90 @@ -1,4 +1,12 @@ !> Module for Fibonacci series calculations +!! +!! Modified by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #31 +!! https://github.com/TheAlgorithms/Fortran/pull/31 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! !! Provides both recursive and iterative implementations. !! Reference: https://en.wikipedia.org/wiki/Fibonacci_number @@ -10,7 +18,9 @@ module fibonacci_module recursive function fib_rec(n) result(f) integer, intent(in), value :: n integer :: f - if (n <= 1) then + if (n < 0) then + f = -1 ! signal error condition + else if (n <= 1) then f = n else f = fib_rec(n - 1) + fib_rec(n - 2) @@ -22,7 +32,9 @@ function fib_itr(n) result(f) integer, intent(in) :: n integer :: f, tmp, f_1 integer :: i - if (n <= 1) then + if (n < 0) then + f = -1 ! signal error condition + else if (n <= 1) then f = n else f_1 = 0 diff --git a/tests/maths/eculid_gcd.f90 b/tests/maths/eculid_gcd.f90 new file mode 100644 index 0000000..29f034d --- /dev/null +++ b/tests/maths/eculid_gcd.f90 @@ -0,0 +1,94 @@ +!> Test program for the GCD module +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #31 +!! https://github.com/TheAlgorithms/Fortran/pull/31 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides test cases to validate the GCD function in the gcd_module. + +program tests_gcd_module + use gcd_module + implicit none + integer :: result, expected + + ! Run test cases + call test_gcd_positive_numbers() + call test_gcd_with_zero() + call test_gcd_negative_numbers() + call test_gcd_same_numbers() + call test_gcd_large_numbers() + + print *, "All tests completed." + +contains + + ! Test case 1: GCD of two positive numbers + subroutine test_gcd_positive_numbers() + integer :: a, b + a = 48 + b = 18 + expected = 6 + result = gcd(a, b) + call assert_test(result, expected, "Test 1: GCD of two positive numbers") + end subroutine test_gcd_positive_numbers + + ! Test case 2: GCD with one number as zero + subroutine test_gcd_with_zero() + integer :: a, b + a = 0 + b = 5 + expected = 5 + result = gcd(a, b) + call assert_test(result, expected, "Test 2: GCD with one number as zero") + end subroutine test_gcd_with_zero + + ! Test case 3: GCD of two negative numbers + subroutine test_gcd_negative_numbers() + integer :: a, b + a = -48 + b = -18 + expected = 6 + result = gcd(a, b) + call assert_test(result, expected, "Test 3: GCD of two negative numbers") + end subroutine test_gcd_negative_numbers + + ! Test case 4: GCD of the same number + subroutine test_gcd_same_numbers() + integer :: a, b + a = 42 + b = 42 + expected = 42 + result = gcd(a, b) + call assert_test(result, expected, "Test 4: GCD of the same number") + end subroutine test_gcd_same_numbers + + ! Test case 5: GCD of large numbers + subroutine test_gcd_large_numbers() + integer :: a, b + a = 123456 + b = 789012 + expected = 12 + result = gcd(a, b) + call assert_test(result, expected, "Test 5: GCD of large numbers") + end subroutine test_gcd_large_numbers + + !> Subroutine to assert the test results + subroutine assert_test(actual, expected, test_name) + integer, intent(in) :: actual, expected + character(len=*), intent(in) :: test_name + + if (actual == expected) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", actual + stop 1 + end if + + end subroutine assert_test + +end program tests_gcd_module diff --git a/tests/maths/factorial.f90 b/tests/maths/factorial.f90 new file mode 100644 index 0000000..1e5d497 --- /dev/null +++ b/tests/maths/factorial.f90 @@ -0,0 +1,87 @@ +!> Test program for factorial functions +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #31 +!! https://github.com/TheAlgorithms/Fortran/pull/31 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides test cases to validate the two facotrial functions in the factorial_module. + +program tests_factorial + use factorial_module + implicit none + + integer :: result, expected + + ! Run test cases + call test_factorial() + call test_recursive_factorial() + + print *, "All tests completed." + +contains + + ! Test case for iterative factorial for known values + subroutine test_factorial() + expected = 120 + result = factorial(5) + call assert_test(result, expected, "Test 1: Iterative Factorial of 5") + + expected = 1 + result = factorial(0) + call assert_test(result, expected, "Test 2: Iterative Factorial of edge case: 0") + + expected = 1 + result = factorial(1) + call assert_test(result, expected, "Test 3: Iterative Factorial of edge case: 1") + + expected = 40320 + result = factorial(8) + call assert_test(result, expected, "Test 4: Iterative Factorial of 8") + + expected = 720 + result = factorial(6) + call assert_test(result, expected, "Test 5: Iterative Factorial of 6") + end subroutine test_factorial + + ! Test case for recursive factorial for known values + subroutine test_recursive_factorial() + expected = 120 + result = recursive_factorial(5) + call assert_test(result, expected, "Test 1: Recursive Factorial of 5") + + expected = 1 + result = recursive_factorial(0) + call assert_test(result, expected, "Test 2: Recursive Factorial of edge case: 0") + + expected = 1 + result = recursive_factorial(1) + call assert_test(result, expected, "Test 3: Recursive Factorial of edge case: 1") + + expected = 40320 + result = recursive_factorial(8) + call assert_test(result, expected, "Test 4: Recursive Factorial of 8") + + expected = 720 + result = recursive_factorial(6) + call assert_test(result, expected, "Test 5: Recursive Factorial of 6") + end subroutine test_recursive_factorial + + !> Subroutine to assert the test results + subroutine assert_test(actual, expected, test_name) + integer, intent(in) :: actual, expected + character(len=*), intent(in) :: test_name + + if (actual == expected) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", actual + stop 1 + end if + end subroutine assert_test + +end program tests_factorial diff --git a/tests/maths/fibonacci.f90 b/tests/maths/fibonacci.f90 new file mode 100644 index 0000000..bf4b086 --- /dev/null +++ b/tests/maths/fibonacci.f90 @@ -0,0 +1,121 @@ +!> Test program for Fibonacci functions +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #31 +!! https://github.com/TheAlgorithms/Fortran/pull/31 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides test cases to validate the two fibonacci functions in the fibonacci_module. + +program tests_fibonacci + use fibonacci_module + implicit none + + integer :: result, expected + + ! Run test cases + call test_fib_zero() + call test_fib_one() + call test_fib_two() + call test_fib_three() + call test_fib_five() + call test_fib_thirty() + call test_fib_negative_one() + call test_fib_negative_five() + + print *, "All tests completed." + +contains + + ! Test case 1: Fibonacci of 0 + subroutine test_fib_zero() + expected = 0 + result = fib_rec(0) + call assert_test(result, expected, "Test 1: Fibonacci of 0 (Recursive)") + result = fib_itr(0) + call assert_test(result, expected, "Test 1: Fibonacci of 0 (Iterative)") + end subroutine test_fib_zero + + ! Test case 2: Fibonacci of 1 + subroutine test_fib_one() + expected = 1 + result = fib_rec(1) + call assert_test(result, expected, "Test 2: Fibonacci of 1 (Recursive)") + result = fib_itr(1) + call assert_test(result, expected, "Test 2: Fibonacci of 1 (Iterative)") + end subroutine test_fib_one + + ! Test case 3: Fibonacci of 2 + subroutine test_fib_two() + expected = 1 + result = fib_rec(2) + call assert_test(result, expected, "Test 3: Fibonacci of 2 (Recursive)") + result = fib_itr(2) + call assert_test(result, expected, "Test 3: Fibonacci of 2 (Iterative)") + end subroutine test_fib_two + + ! Test case 4: Fibonacci of 3 + subroutine test_fib_three() + expected = 2 + result = fib_rec(3) + call assert_test(result, expected, "Test 4: Fibonacci of 3 (Recursive)") + result = fib_itr(3) + call assert_test(result, expected, "Test 4: Fibonacci of 3 (Iterative)") + end subroutine test_fib_three + + ! Test case 5: Fibonacci of 5 + subroutine test_fib_five() + expected = 5 + result = fib_rec(5) + call assert_test(result, expected, "Test 5: Fibonacci of 5 (Recursive)") + result = fib_itr(5) + call assert_test(result, expected, "Test 5: Fibonacci of 5 (Iterative)") + end subroutine test_fib_five + + ! Test case 6: Fibonacci of 30 + subroutine test_fib_thirty() + expected = 832040 + result = fib_rec(30) + call assert_test(result, expected, "Test 5: Fibonacci of 30 (Recursive)") + result = fib_itr(30) + call assert_test(result, expected, "Test 5: Fibonacci of 30 (Iterative)") + end subroutine test_fib_thirty + + ! Test case 7: Fibonacci of negative input + subroutine test_fib_negative_one() + expected = -1 + result = fib_rec(-9) + call assert_test(result, expected, "Test 6: Fibonacci of -1 (Recursive)") + result = fib_itr(-9) + call assert_test(result, expected, "Test 6: Fibonacci of -1 (Iterative)") + end subroutine test_fib_negative_one + + ! Test case 8: Fibonacci of negative input + subroutine test_fib_negative_five() + expected = -1 + result = fib_rec(-9) + call assert_test(result, expected, "Test 7: Fibonacci of -5 (Recursive)") + result = fib_itr(-9) + call assert_test(result, expected, "Test 7: Fibonacci of -5 (Iterative)") + end subroutine test_fib_negative_five + + !> Subroutine to assert the test results + subroutine assert_test(actual, expected, test_name) + integer, intent(in) :: actual, expected + character(len=*), intent(in) :: test_name + + if (actual == expected) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", actual + stop 1 + end if + + end subroutine assert_test + +end program tests_fibonacci +