From 86220c98d1802209009bbdb32f0b3ff701cac896 Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 13:20:06 +0200 Subject: [PATCH 1/6] Implementing ctest friendly tests --- tests/sorts/tests_heap_sort.f90 | 161 +++++++++++++++++-------------- tests/sorts/tests_merge_sort.f90 | 159 ++++++++++++++++-------------- 2 files changed, 176 insertions(+), 144 deletions(-) diff --git a/tests/sorts/tests_heap_sort.f90 b/tests/sorts/tests_heap_sort.f90 index 18b2794..97e7fcb 100644 --- a/tests/sorts/tests_heap_sort.f90 +++ b/tests/sorts/tests_heap_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Heap Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #8 -!! https://github.com/TheAlgorithms/Fortran/pull/8 +!! in Pull Request: #29 +!! https://github.com/TheAlgorithms/Fortran/pull/29 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! @@ -13,86 +13,103 @@ program tests_heap_sort use heap_sort_module implicit none - integer, dimension(:), allocatable :: array - - ! Test 1: Repeated elements - print *, "Test 1: Array with repeated elements" - array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) - call run_test(array) - - ! Test 2: Already sorted array - print *, "Test 2: Already sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/1, 2, 3, 4, 5, 6, 7, 8/) - call run_test(array) - - ! Test 3: Reverse sorted array - print *, "Test 3: Reverse sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/8, 7, 6, 5, 4, 3, 2, 1/) - call run_test(array) - - ! Test 4: Array with all negative numbers - print *, "Test 4: Array with all negative numbers" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/-1, -5, -3, -7, -2, -12, -15, -4/) - call run_test(array) - - ! Test 5: Single element array - print *, "Test 5: Single element array" - if (allocated(array)) deallocate (array) - allocate (array(1)) - array = (/42/) - call run_test(array) - - ! Test 6: Array with identical elements - print *, "Test 6: Array with identical elements" - if (allocated(array)) deallocate (array) - allocate (array(5)) - array = (/7, 7, 7, 7, 7/) - call run_test(array) - - ! Test 7: Array with alternating high and low values - print *, "Test 7: Array with alternating high and low values" - if (allocated(array)) deallocate (array) - allocate (array(6)) - array = (/1, 1000, 2, 999, 3, 998/) - call run_test(array) - - ! Test 8: Empty array - print *, "Test 8: Empty array" - if (allocated(array)) deallocate (array) - allocate (array(0)) - call run_test(array) + integer, dimension(:), allocatable :: array, expected + + ! Run test cases + call test_repeated_elements() + call test_already_sorted() + call test_reverse_sorted() + call test_negative_numbers() + call test_single_element() + call test_identical_elements() + call test_alternating_values() + call test_empty_array() + + print *, "All tests completed." contains - !> Subroutine to run and print the heap sort test - subroutine run_test(array) + ! Test case 1: Array with repeated elements + subroutine test_repeated_elements() + array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) + expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 100/) + call run_test(array, expected, "Test 1: Array with repeated elements") + end subroutine test_repeated_elements + + ! Test case 2: Already sorted array + subroutine test_already_sorted() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + call run_test(array, expected, "Test 2: Already sorted array") + end subroutine test_already_sorted + + ! Test case 3: Reverse sorted array + subroutine test_reverse_sorted() + array = (/9, 8, 7, 6, 5, 4, 3, 2, 1/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9/) + call run_test(array, expected, "Test 3: Reverse sorted array") + end subroutine test_reverse_sorted + + ! Test case 4: Array with all negative numbers + subroutine test_negative_numbers() + array = (/-110, -550, -430, -700, -20, -10, -150, -90, -250/) + expected = (/-700, -550, -430, -250, -150, -110, -90, -20, -10/) + call run_test(array, expected, "Test 4: Array with all negative numbers") + end subroutine test_negative_numbers + + ! Test case 5: Single element array + subroutine test_single_element() + array = (/43/) + expected = (/43/) + call run_test(array, expected, "Test 5: Single element array") + end subroutine test_single_element + + ! Test case 6: Array with identical elements + subroutine test_identical_elements() + array = (/7, 7, 7, 7, 7/) + expected = (/7, 7, 7, 7, 7/) + call run_test(array, expected, "Test 6: Array with identical elements") + end subroutine test_identical_elements + + ! Test case 7: Array with alternating high and low values + subroutine test_alternating_values() + array = (/1, 1000, 2, 999, 3, 998/) + expected = (/1, 2, 3, 998, 999, 1000/) + call run_test(array, expected, "Test 7: Array with alternating high and low values") + end subroutine test_alternating_values + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 8: Empty array") + end subroutine test_empty_array + + + !> Subroutine to run the heap sort test + subroutine run_test(array, expected, test_name) integer, dimension(:), intent(inout) :: array - integer :: n, i + integer, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name + integer :: n n = size(array) - ! Print original array - print *, "Original array:" - do i = 1, n - print *, array(i) - end do - - ! Call heap_sort + ! Call heap_sort in module call heap_sort(array, n) - ! Print sorted array - print *, "Sorted array:" - do i = 1, n - print *, array(i) - end do + ! Assert that the sorted array matches the expected array + if (all(array == expected)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if - print *, "" end subroutine run_test end program tests_heap_sort diff --git a/tests/sorts/tests_merge_sort.f90 b/tests/sorts/tests_merge_sort.f90 index 5da8ad0..a4ac694 100644 --- a/tests/sorts/tests_merge_sort.f90 +++ b/tests/sorts/tests_merge_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Merge Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #7 -!! https://github.com/TheAlgorithms/Fortran/pull/7 +!! in Pull Request: #29 +!! https://github.com/TheAlgorithms/Fortran/pull/29 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! @@ -13,86 +13,101 @@ program tests_merge_sort use merge_sort_module implicit none - integer, dimension(:), allocatable :: array - - ! Test 1: Repeated elements - print *, "Test 1: Array with repeated elements" - array = (/4, 2, 7, 3, 1, 4, 9, 5, 10, 9, 2, 1/) - call run_test(array) - - ! Test 2: Already sorted array - print *, "Test 2: Already sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/1, 2, 3, 4, 5, 6, 7, 8/) - call run_test(array) - - ! Test 3: Reverse sorted array - print *, "Test 3: Reverse sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/8, 7, 6, 5, 4, 3, 2, 1/) - call run_test(array) - - ! Test 4: Array with all negative numbers - print *, "Test 4: Array with all negative numbers" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/-11, -55, -43, -70, -2, -1, -15, -9/) - call run_test(array) - - ! Test 5: Single element array - print *, "Test 5: Single element array" - if (allocated(array)) deallocate (array) - allocate (array(1)) - array = (/62/) - call run_test(array) - - ! Test 6: Array with identical elements - print *, "Test 6: Array with identical elements" - if (allocated(array)) deallocate (array) - allocate (array(5)) - array = (/4, 4, 4, 4, 4/) - call run_test(array) - - ! Test 7: Array with alternating high and low values - print *, "Test 7: Array with alternating high and low values" - if (allocated(array)) deallocate (array) - allocate (array(6)) - array = (/10, 2000, 20, 888, 30, 798/) - call run_test(array) - - ! Test 8: Empty array - print *, "Test 8: Empty array" - if (allocated(array)) deallocate (array) - allocate (array(0)) - call run_test(array) + integer, dimension(:), allocatable :: array, expected + + ! Run test cases + call test_repeated_elements() + call test_already_sorted() + call test_reverse_sorted() + call test_negative_numbers() + call test_single_element() + call test_identical_elements() + call test_alternating_values() + call test_empty_array() + + print *, "All tests completed." contains - !> Subroutine to run and print the merge sort test - subroutine run_test(array) + ! Test case 1: Array with repeated elements + subroutine test_repeated_elements() + array = (/4, 2, 7, 3, 1, 4, 9, 5, 10, 9, 2, 1/) + expected = (/1, 1, 2, 2, 3, 4, 4, 5, 7, 9, 9, 10/) + call run_test(array, expected, "Test 1: Array with repeated elements") + end subroutine test_repeated_elements + + ! Test case 2: Already sorted array + subroutine test_already_sorted() + array = (/1, 2, 3, 4, 5, 6, 7, 8/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8/) + call run_test(array, expected, "Test 2: Already sorted array") + end subroutine test_already_sorted + + ! Test case 3: Reverse sorted array + subroutine test_reverse_sorted() + array = (/8, 7, 6, 5, 4, 3, 2, 1/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8/) + call run_test(array, expected, "Test 3: Reverse sorted array") + end subroutine test_reverse_sorted + + ! Test case 4: Array with all negative numbers + subroutine test_negative_numbers() + array = (/-11, -55, -43, -70, -2, -1, -15, -9/) + expected = (/-70, -55, -43, -15, -11, -9, -2, -1/) + call run_test(array, expected, "Test 4: Array with all negative numbers") + end subroutine test_negative_numbers + + ! Test case 5: Single element array + subroutine test_single_element() + array = (/62/) + expected = (/62/) + call run_test(array, expected, "Test 5: Single element array") + end subroutine test_single_element + + ! Test case 6: Array with identical elements + subroutine test_identical_elements() + array = (/4, 4, 4, 4, 4/) + expected = (/4, 4, 4, 4, 4/) + call run_test(array, expected, "Test 6: Array with identical elements") + end subroutine test_identical_elements + + ! Test case 7: Array with alternating high and low values + subroutine test_alternating_values() + array = (/10, 2000, 20, 888, 30, 798/) + expected = (/10, 20, 30, 798, 888, 2000/) + call run_test(array, expected, "Test 7: Array with alternating high and low values") + end subroutine test_alternating_values + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 8: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the merge sort test + subroutine run_test(array, expected, test_name) integer, dimension(:), intent(inout) :: array - integer :: n, i + integer, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name + integer :: n n = size(array) - ! Print original array - print *, "Original array:" - do i = 1, n - print *, array(i) - end do - - ! Call merge_sort + ! Call merge_sort in module call merge_sort(array, n) - ! Print sorted array - print *, "Sorted array:" - do i = 1, n - print *, array(i) - end do + ! Assert that the sorted array matches the expected array + if (all(array == expected)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + end if - print *, "" end subroutine run_test end program tests_merge_sort From 3ee89ba8429a6e75911e2b90c5f4ccddd4fe1d6c Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 14:28:52 +0200 Subject: [PATCH 2/6] Implementing ctest-friendly tests for /sorts --- .github/workflows/ci.yml | 2 +- tests/sorts/tests_bubble_sort.f90 | 107 ++++++++++++ tests/sorts/tests_gnome_sort.f90 | 159 ++++++++++-------- tests/sorts/tests_heap_sort.f90 | 9 +- tests/sorts/tests_merge_sort.f90 | 7 +- tests/sorts/tests_quick_sort.f90 | 156 ++++++++++-------- tests/sorts/tests_radix_sort.f90 | 183 +++++++++++---------- tests/sorts/tests_recursive_bubbe_sort.f90 | 110 +++++++++++++ 8 files changed, 498 insertions(+), 235 deletions(-) create mode 100644 tests/sorts/tests_bubble_sort.f90 create mode 100644 tests/sorts/tests_recursive_bubbe_sort.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/tests/sorts/tests_bubble_sort.f90 b/tests/sorts/tests_bubble_sort.f90 new file mode 100644 index 0000000..ca7e62e --- /dev/null +++ b/tests/sorts/tests_bubble_sort.f90 @@ -0,0 +1,107 @@ +!> Test program for the Bubble Sort algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #27 +!! https://github.com/TheAlgorithms/Fortran/pull/27 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program tests the bubble_sort_module for correct sorting behavior. + +program tests_bubble_sort + use bubble_sort_module + implicit none + real, dimension(:), allocatable :: array, expected + + ! Run test cases + call test_sorted_array() + call test_reverse_sorted_array() + call test_unsorted_array() + call test_array_with_repeated_elements() + call test_array_with_identical_elements() + call test_single_element_array() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test case 1: Already sorted array + subroutine test_sorted_array() + array = (/1.0, 2.0, 3.0, 4.0, 5.0/) + expected = array + call run_test(array, expected, "Test 1: Already sorted array") + end subroutine test_sorted_array + + ! Test case 2: Reverse sorted array + subroutine test_reverse_sorted_array() + array = (/5.0, 4.0, 3.0, 2.0, 1.0/) + expected = (/1.0, 2.0, 3.0, 4.0, 5.0/) + call run_test(array, expected, "Test 2: Reverse sorted array") + end subroutine test_reverse_sorted_array + + ! Test case 3: Unsorted array + subroutine test_unsorted_array() + array = (/3.5, 1.2, 4.8, 2.7, 5.0/) + expected = (/1.2, 2.7, 3.5, 4.8, 5.0/) + call run_test(array, expected, "Test 3: Unsorted array") + end subroutine test_unsorted_array + + ! Test case 4: Array with repeated elements + subroutine test_array_with_repeated_elements() + array = (/3.0, 1.0, 2.0, 3.0, 4.0, 3.0/) + expected = (/1.0, 2.0, 3.0, 3.0, 3.0, 4.0/) + call run_test(array, expected, "Test 4: Array with repeated elements") + end subroutine test_array_with_repeated_elements + + ! Test case 5: Array with identical elements + subroutine test_array_with_identical_elements() + array = (/7.0, 7.0, 7.0, 7.0, 7.0/) + expected = array + call run_test(array, expected, "Test 5: Array with identical elements") + end subroutine test_array_with_identical_elements + + ! Test case 6: Single element array + subroutine test_single_element_array() + array = (/42.0/) + expected = array + call run_test(array, expected, "Test 6: Single element array") + end subroutine test_single_element_array + + ! Test case 7: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 7: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the bubble sort test + subroutine run_test(array, expected, test_name) + real, dimension(:), intent(inout) :: array + real, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name + real :: tolerance + + ! Call bubble_sort in module + call bubble_sort(array) + + ! Set an appropriate tolerance value + tolerance = 1.0e-6 + + ! Assert if the sorted values are sufficiently close to the expected array otherwise report failure + if (all(abs(array - expected) < tolerance)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if + + end subroutine run_test + +end program tests_bubble_sort + diff --git a/tests/sorts/tests_gnome_sort.f90 b/tests/sorts/tests_gnome_sort.f90 index d921c67..4fab834 100644 --- a/tests/sorts/tests_gnome_sort.f90 +++ b/tests/sorts/tests_gnome_sort.f90 @@ -1,7 +1,7 @@ !> Test program for the Gnome Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #09 +!! in Pull Request: #9 !! https://github.com/TheAlgorithms/Fortran/pull/9 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request @@ -13,86 +13,99 @@ program tests_gnome_sort use gnome_sort_module implicit none - integer, dimension(:), allocatable :: array - - ! Test 1: Repeated elements - print *, "Test 1: Array with repeated elements" - array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) - call run_test(array) - - ! Test 2: Already sorted array - print *, "Test 2: Already sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/1, 2, 3, 4, 5, 6, 7, 8/) - call run_test(array) - - ! Test 3: Reverse sorted array - print *, "Test 3: Reverse sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/8, 7, 6, 5, 4, 3, 2, 1/) - call run_test(array) - - ! Test 4: Array with all negative numbers - print *, "Test 4: Array with all negative numbers" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/-1, -5, -3, -7, -2, -12, -15, -4/) - call run_test(array) - - ! Test 5: Single element array - print *, "Test 5: Single element array" - if (allocated(array)) deallocate (array) - allocate (array(1)) - array = (/42/) - call run_test(array) - - ! Test 6: Array with identical elements - print *, "Test 6: Array with identical elements" - if (allocated(array)) deallocate (array) - allocate (array(5)) - array = (/7, 7, 7, 7, 7/) - call run_test(array) - - ! Test 7: Array with alternating high and low values - print *, "Test 7: Array with alternating high and low values" - if (allocated(array)) deallocate (array) - allocate (array(6)) - array = (/1, 1000, 2, 999, 3, 998/) - call run_test(array) - - ! Test 8: Empty array - print *, "Test 8: Empty array" - if (allocated(array)) deallocate (array) - allocate (array(0)) - call run_test(array) + integer, dimension(:), allocatable :: array, expected -contains + ! Run test cases + call test_repeated_elements() + call test_already_sorted() + call test_reverse_sorted() + call test_negative_numbers() + call test_single_element() + call test_identical_elements() + call test_alternating_values() + call test_empty_array() - !> Subroutine to run and print the gnome sort test - subroutine run_test(array) - integer, dimension(:), intent(inout) :: array - integer :: n, i + print *, "All tests completed." - n = size(array) +contains - ! Print original array - print *, "Original array:" - do i = 1, n - print *, array(i) - end do + ! Test case 1: Array with repeated elements + subroutine test_repeated_elements() + array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) + expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 10/) + call run_test(array, expected, "Test 1: Array with repeated elements") + end subroutine test_repeated_elements + + ! Test case 2: Already sorted array + subroutine test_already_sorted() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13/) + call run_test(array, expected, "Test 2: Already sorted array") + end subroutine test_already_sorted + + ! Test case 3: Reverse sorted array + subroutine test_reverse_sorted() + array = (/11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11/) + call run_test(array, expected, "Test 3: Reverse sorted array") + end subroutine test_reverse_sorted + + ! Test case 4: Array with all negative numbers + subroutine test_negative_numbers() + array = (/-1, -5, -4, -7, -2, -1, -1, -9, -2/) + expected = (/-9, -7, -5, -4, -2, -2, -1, -1, -1/) + call run_test(array, expected, "Test 4: Array with all negative numbers") + end subroutine test_negative_numbers + + ! Test case 5: Single element array + subroutine test_single_element() + array = (/73/) + expected = (/73/) + call run_test(array, expected, "Test 5: Single element array") + end subroutine test_single_element + + ! Test case 6: Array with identical elements + subroutine test_identical_elements() + array = (/8, 8, 8, 8, 8/) + expected = (/8, 8, 8, 8, 8/) + call run_test(array, expected, "Test 6: Array with identical elements") + end subroutine test_identical_elements + + ! Test case 7: Array with alternating high and low values + subroutine test_alternating_values() + array = (/1, 999, 2, 600, 3, 950/) + expected = (/1, 2, 3, 600, 950, 999/) + call run_test(array, expected, "Test 7: Array with alternating high and low values") + end subroutine test_alternating_values + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 8: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the heap sort test + subroutine run_test(array, expected, test_name) + integer, dimension(:), intent(inout) :: array + integer, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name - ! Call gnome_sort + ! Call gnome_sort in module call gnome_sort(array) - ! Print sorted array - print *, "Sorted array:" - do i = 1, n - print *, array(i) - end do + ! Assert that the sorted array matches the expected array otherwise report failure for ctest + if (all(array == expected)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if - print *, "" end subroutine run_test end program tests_gnome_sort diff --git a/tests/sorts/tests_heap_sort.f90 b/tests/sorts/tests_heap_sort.f90 index 97e7fcb..2cf19dd 100644 --- a/tests/sorts/tests_heap_sort.f90 +++ b/tests/sorts/tests_heap_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Heap Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #29 -!! https://github.com/TheAlgorithms/Fortran/pull/29 +!! in Pull Request: #8 +!! https://github.com/TheAlgorithms/Fortran/pull/8 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! @@ -32,7 +32,7 @@ program tests_heap_sort ! Test case 1: Array with repeated elements subroutine test_repeated_elements() array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) - expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 100/) + expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 10/) call run_test(array, expected, "Test 1: Array with repeated elements") end subroutine test_repeated_elements @@ -87,7 +87,6 @@ subroutine test_empty_array() call run_test(array, expected, "Test 8: Empty array") end subroutine test_empty_array - !> Subroutine to run the heap sort test subroutine run_test(array, expected, test_name) integer, dimension(:), intent(inout) :: array @@ -100,7 +99,7 @@ subroutine run_test(array, expected, test_name) ! Call heap_sort in module call heap_sort(array, n) - ! Assert that the sorted array matches the expected array + ! Assert that the sorted array matches the expected array otherwise report failure for ctest if (all(array == expected)) then print *, test_name, " PASSED" else diff --git a/tests/sorts/tests_merge_sort.f90 b/tests/sorts/tests_merge_sort.f90 index a4ac694..b27f70b 100644 --- a/tests/sorts/tests_merge_sort.f90 +++ b/tests/sorts/tests_merge_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Merge Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #29 -!! https://github.com/TheAlgorithms/Fortran/pull/29 +!! in Pull Request: #7 +!! https://github.com/TheAlgorithms/Fortran/pull/7 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! @@ -99,13 +99,14 @@ subroutine run_test(array, expected, test_name) ! Call merge_sort in module call merge_sort(array, n) - ! Assert that the sorted array matches the expected array + ! Assert that the sorted array matches the expected array otherwise report failure for ctest if (all(array == expected)) then print *, test_name, " PASSED" else print *, test_name, " FAILED" print *, "Expected: ", expected print *, "Got: ", array + stop 1 end if end subroutine run_test diff --git a/tests/sorts/tests_quick_sort.f90 b/tests/sorts/tests_quick_sort.f90 index a46835f..c574a4b 100644 --- a/tests/sorts/tests_quick_sort.f90 +++ b/tests/sorts/tests_quick_sort.f90 @@ -13,86 +13,102 @@ program tests_quick_sort use quick_sort_module implicit none - integer, dimension(:), allocatable :: array - - ! Test 1: Repeated elements - print *, "Test 1: Array with repeated elements" - array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) - call run_test(array) - - ! Test 2: Already sorted array - print *, "Test 2: Already sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/1, 2, 3, 4, 5, 6, 7, 8/) - call run_test(array) - - ! Test 3: Reverse sorted array - print *, "Test 3: Reverse sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/8, 7, 6, 5, 4, 3, 2, 1/) - call run_test(array) - - ! Test 4: Array with all negative numbers - print *, "Test 4: Array with all negative numbers" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/-1, -5, -3, -7, -2, -12, -15, -4/) - call run_test(array) - - ! Test 5: Single element array - print *, "Test 5: Single element array" - if (allocated(array)) deallocate (array) - allocate (array(1)) - array = (/42/) - call run_test(array) - - ! Test 6: Array with identical elements - print *, "Test 6: Array with identical elements" - if (allocated(array)) deallocate (array) - allocate (array(5)) - array = (/7, 7, 7, 7, 7/) - call run_test(array) - - ! Test 7: Array with alternating high and low values - print *, "Test 7: Array with alternating high and low values" - if (allocated(array)) deallocate (array) - allocate (array(6)) - array = (/1, 1000, 2, 999, 3, 998/) - call run_test(array) - - ! Test 8: Empty array - print *, "Test 8: Empty array" - if (allocated(array)) deallocate (array) - allocate (array(0)) - call run_test(array) + integer, dimension(:), allocatable :: array, expected + + ! Run test cases + call test_repeated_elements() + call test_already_sorted() + call test_reverse_sorted() + call test_negative_numbers() + call test_single_element() + call test_identical_elements() + call test_alternating_values() + call test_empty_array() + + print *, "All tests completed." contains - !> Subroutine to run and print the quick sort test - subroutine run_test(array) + ! Test case 1: Array with repeated elements + subroutine test_repeated_elements() + array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) + expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 10/) + call run_test(array, expected, "Test 1: Array with repeated elements") + end subroutine test_repeated_elements + + ! Test case 2: Already sorted array + subroutine test_already_sorted() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12/) + call run_test(array, expected, "Test 2: Already sorted array") + end subroutine test_already_sorted + + ! Test case 3: Reverse sorted array + subroutine test_reverse_sorted() + array = (/10, 9, 8, 7, 6, 5, 4, 3, 2, 1/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + call run_test(array, expected, "Test 3: Reverse sorted array") + end subroutine test_reverse_sorted + + ! Test case 4: Array with all negative numbers + subroutine test_negative_numbers() + array = (/-1, -5, -4, -7, -2, -1, -1, -9, -2/) + expected = (/-9, -7, -5, -4, -2, -2, -1, -1, -1/) + call run_test(array, expected, "Test 4: Array with all negative numbers") + end subroutine test_negative_numbers + + ! Test case 5: Single element array + subroutine test_single_element() + array = (/23/) + expected = (/23/) + call run_test(array, expected, "Test 5: Single element array") + end subroutine test_single_element + + ! Test case 6: Array with identical elements + subroutine test_identical_elements() + array = (/-9, -9, -9, -9, -9/) + expected = (/-9, -9, -9, -9, -9/) + call run_test(array, expected, "Test 6: Array with identical elements") + end subroutine test_identical_elements + + ! Test case 7: Array with alternating high and low values + subroutine test_alternating_values() + array = (/1, 999, 2, 600, 3, 950/) + expected = (/1, 2, 3, 600, 950, 999/) + call run_test(array, expected, "Test 7: Array with alternating high and low values") + end subroutine test_alternating_values + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 8: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the quick sort test + subroutine run_test(array, expected, test_name) integer, dimension(:), intent(inout) :: array - integer :: n, i + integer, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name + integer :: n n = size(array) - ! Print original array - print *, "Original array:" - do i = 1, n - print *, array(i) - end do - - ! Call quick_sort + ! Call quick_sort in module call quick_sort(array, 1, n) ! (1: low bound , n: high bound) of the array - ! Print sorted array - print *, "Sorted array:" - do i = 1, n - print *, array(i) - end do + ! Assert that the sorted array matches the expected array otherwise report failure for ctest + if (all(array == expected)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if - print *, "" end subroutine run_test end program tests_quick_sort diff --git a/tests/sorts/tests_radix_sort.f90 b/tests/sorts/tests_radix_sort.f90 index 056fd5c..fb9e65e 100644 --- a/tests/sorts/tests_radix_sort.f90 +++ b/tests/sorts/tests_radix_sort.f90 @@ -13,112 +13,129 @@ program tests_radix_sort use radix_sort_module implicit none - integer, dimension(:), allocatable :: array + integer, dimension(:), allocatable :: array, expected integer, parameter :: base10 = 10, base2 = 2, base16 = 16 - ! Test 1: Base 10 - print *, "Test 1: Radix Sort with base 10" - if (allocated(array)) deallocate (array) - allocate (array(10)) - array = (/170, 45, 75, 90, 802, 24, 2, 66, 15, 40/) - call run_test(array, base10) - - ! Test 2: Base 2 - print *, "Test 2: Radix Sort with base 2" - if (allocated(array)) deallocate (array) - allocate (array(10)) - array = (/10, 13, 9, 14, 2, 5, 15, 6, 8, 1/) ! Binary values as decimal - call run_test(array, base2) - - ! Test 3: Base 16 - print *, "Test 3: Radix Sort with base 16" - if (allocated(array)) deallocate (array) - allocate (array(10)) - array = (/171, 31, 61, 255, 16, 5, 211, 42, 180, 0/) ! Hexadecimal values as decimal - call run_test(array, base16) - - ! Test 4: Repeated elements - print *, "Test 4: Array with repeated elements" - if (allocated(array)) deallocate (array) - allocate (array(12)) - array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) - call run_test(array, base10) - - ! Test 5: Already sorted array - print *, "Test 5: Already sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/1, 2, 3, 4, 5, 6, 7, 8/) - call run_test(array, base10) + ! Run test cases + call test_base10() + call test_base2() + call test_base16() + call test_repeated_elements() + call test_already_sorted() + call test_reverse_sorted() + call test_negative_numbers() + call test_single_element() + call test_identical_elements() + call test_alternating_values() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test 1: sort with Base 10 + subroutine test_base10() + array = (/170, 45, 75, 90, 802, 24, 2, 66, 15, 40/) + expected = (/2, 15, 24, 40, 45, 66, 75, 90, 170, 802/) + call run_test(array, expected, base10, "Test 1: Base 10") + end subroutine test_base10 + + ! Test 2: Sort with Base 2 + subroutine test_base2() + array = (/10, 13, 9, 14, 2, 5, 15, 6, 8, 1/) ! Binary values as decimal + expected = (/1, 2, 5, 6, 8, 9, 10, 13, 14, 15/) + call run_test(array, expected, base2, "Test 2 Base 2") + end subroutine test_base2 + + ! Test 3: Sorth with Base 16 + subroutine test_base16() + array = (/171, 31, 61, 255, 16, 5, 211, 42, 180, 0/) ! Hexadecimal values as decimal + expected = (/0, 5, 16, 31, 42, 61, 171, 180, 211, 255/) + call run_test(array, expected, base16, "Test 3: Base 16") + end subroutine test_base16 + + ! Test case 4: Array with repeated elements + subroutine test_repeated_elements() + array = (/5, 3, 8, 3, 1, 5, 7, 5, 10, 7, 3, 1/) + expected = (/1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 8, 10/) + call run_test(array, expected, base10, "Test 4: Array with repeated elements") + end subroutine test_repeated_elements + + ! Test case 5: Already sorted array + subroutine test_already_sorted() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13/) + call run_test(array, expected, base10, "Test 5: Already sorted array") + end subroutine test_already_sorted ! Test 6: Reverse sorted array - print *, "Test 6: Reverse sorted array" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/8, 7, 6, 5, 4, 3, 2, 1/) - call run_test(array, base10) + subroutine test_reverse_sorted() + array = (/11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1/) + expected = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11/) + call run_test(array, expected, base10, "Test 6: Reverse sorted array") + end subroutine test_reverse_sorted ! Test 7: Array with all negative numbers (Note: Radix Sort only handles non-negative integers) - print *, "Test 7: Array with all negative numbers (handled as base 10)" - if (allocated(array)) deallocate (array) - allocate (array(8)) - array = (/-1, -5, -3, -7, -2, -12, -15, -4/) - call run_test(array, base10) + subroutine test_negative_numbers() + array = (/-1, -5, -3, -7, -2, -12, -15, -4/) + expected = (/-1, -5, -3, -7, -2, -12, -15, -4/) + call run_test(array, expected, base10, "Test 7: Array with all negative numbers (handled as base 10)") + end subroutine test_negative_numbers ! Test 8: Single element array - print *, "Test 8: Single element array" - if (allocated(array)) deallocate (array) - allocate (array(1)) - array = (/42/) - call run_test(array, base10) + subroutine test_single_element() + array = (/93/) + expected = (/93/) + call run_test(array, expected, base10, "Test 8: Single element array") + end subroutine test_single_element ! Test 9: Array with identical elements - print *, "Test 9: Array with identical elements" - if (allocated(array)) deallocate (array) - allocate (array(5)) - array = (/7, 7, 7, 7, 7/) - call run_test(array, base10) + subroutine test_identical_elements() + array = (/8, 8, 8, 8, 8/) + expected = (/8, 8, 8, 8, 8/) + call run_test(array, expected, base10, "Test 9: Array with identical elements") + end subroutine test_identical_elements ! Test 10: Array with alternating high and low values - print *, "Test 10: Array with alternating high and low values" - if (allocated(array)) deallocate (array) - allocate (array(6)) - array = (/1, 1000, 2, 999, 3, 998/) - call run_test(array, base10) + subroutine test_alternating_values() + array = (/1, 999, 2, 600, 3, 950/) + expected = (/1, 2, 3, 600, 950, 999/) + call run_test(array, expected, base10, "Test 10: Array with alternating high and low values") + end subroutine test_alternating_values ! Test 11: Empty array - print *, "Test 11: Empty array" - if (allocated(array)) deallocate (array) - allocate (array(0)) - call run_test(array, base10) - -contains - - !> Subroutine to run and print the radix sort test - subroutine run_test(array, base) + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, base10, "Test 11: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the radix sort test + subroutine run_test(array, expected, base, test_name) integer, dimension(:), intent(inout) :: array + integer, dimension(:), intent(in) :: expected integer, intent(in) :: base - integer :: n, i + character(len=*), intent(in) :: test_name + integer :: n n = size(array) - ! Print original array - print *, "Original array:" - do i = 1, n - print *, array(i) - end do - - ! Call radix_sort + ! Call radix_sort in module ! The parameters specify the array to sort, its size, and the base for sorting. call radix_sort(array, n, base) - ! Print sorted array - print *, "Sorted array:" - do i = 1, n - print *, array(i) - end do + ! Assert that the sorted array matches the expected array otherwise report failure for ctest + if (all(array == expected)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if - print *, "" end subroutine run_test end program tests_radix_sort diff --git a/tests/sorts/tests_recursive_bubbe_sort.f90 b/tests/sorts/tests_recursive_bubbe_sort.f90 new file mode 100644 index 0000000..f036f30 --- /dev/null +++ b/tests/sorts/tests_recursive_bubbe_sort.f90 @@ -0,0 +1,110 @@ +!> Test program for the Bubble Sort algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #27 +!! https://github.com/TheAlgorithms/Fortran/pull/27 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program tests the recursive_bubble_sort_module for correct sorting behavior. + +program tests_recursive_bubble_sort + use recursive_bubble_sort_module + implicit none + real, dimension(:), allocatable :: array, expected + + ! Run test cases + call test_sorted_array() + call test_reverse_sorted_array() + call test_unsorted_array() + call test_array_with_repeated_elements() + call test_array_with_identical_elements() + call test_single_element_array() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test case 1: Already sorted array + subroutine test_sorted_array() + array = (/1.0, 2.0, 3.0, 4.0, 5.0/) + expected = array + call run_test(array, expected, "Test 1: Already sorted array") + end subroutine test_sorted_array + + ! Test case 2: Reverse sorted array + subroutine test_reverse_sorted_array() + array = (/5.0, 4.0, 3.0, 2.0, 1.0/) + expected = (/1.0, 2.0, 3.0, 4.0, 5.0/) + call run_test(array, expected, "Test 2: Reverse sorted array") + end subroutine test_reverse_sorted_array + + ! Test case 3: Unsorted array + subroutine test_unsorted_array() + array = (/3.5, 1.2, 4.8, 2.7, 5.0/) + expected = (/1.2, 2.7, 3.5, 4.8, 5.0/) + call run_test(array, expected, "Test 3: Unsorted array") + end subroutine test_unsorted_array + + ! Test case 4: Array with repeated elements + subroutine test_array_with_repeated_elements() + array = (/3.0, 1.0, 2.0, 3.0, 4.0, 3.0/) + expected = (/1.0, 2.0, 3.0, 3.0, 3.0, 4.0/) + call run_test(array, expected, "Test 4: Array with repeated elements") + end subroutine test_array_with_repeated_elements + + ! Test case 5: Array with identical elements + subroutine test_array_with_identical_elements() + array = (/7.0, 7.0, 7.0, 7.0, 7.0/) + expected = array + call run_test(array, expected, "Test 5: Array with identical elements") + end subroutine test_array_with_identical_elements + + ! Test case 6: Single element array + subroutine test_single_element_array() + array = (/42.0/) + expected = array + call run_test(array, expected, "Test 6: Single element array") + end subroutine test_single_element_array + + ! Test case 7: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + if (allocated(expected)) deallocate (expected) + allocate (array(0)) + allocate (expected(0)) + call run_test(array, expected, "Test 7: Empty array") + end subroutine test_empty_array + + !> Subroutine to run the bubble sort test + subroutine run_test(array, expected, test_name) + real, dimension(:), intent(inout) :: array + real, dimension(:), intent(in) :: expected + character(len=*), intent(in) :: test_name + real :: tolerance + integer :: n + + n = size(array) + + ! Call bubble_sort in module + call recursive_bubble_sort(array, n) + + ! Set an appropriate tolerance value + tolerance = 1.0e-6 + + ! Assert if the sorted values are sufficiently close to the expected array otherwise report failure + if (all(abs(array - expected) < tolerance)) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", array + stop 1 + end if + + end subroutine run_test + +end program tests_recursive_bubble_sort + From 0bcd2a491cdbd22b15fa2015a98d8a87ee7b197f Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 15:25:35 +0200 Subject: [PATCH 3/6] minor comment edit --- tests/sorts/tests_bubble_sort.f90 | 4 ++-- tests/sorts/tests_recursive_bubbe_sort.f90 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/sorts/tests_bubble_sort.f90 b/tests/sorts/tests_bubble_sort.f90 index ca7e62e..2ce0f00 100644 --- a/tests/sorts/tests_bubble_sort.f90 +++ b/tests/sorts/tests_bubble_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Bubble Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #27 -!! https://github.com/TheAlgorithms/Fortran/pull/27 +!! in Pull Request: #29 +!! https://github.com/TheAlgorithms/Fortran/pull/29 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! diff --git a/tests/sorts/tests_recursive_bubbe_sort.f90 b/tests/sorts/tests_recursive_bubbe_sort.f90 index f036f30..b07b192 100644 --- a/tests/sorts/tests_recursive_bubbe_sort.f90 +++ b/tests/sorts/tests_recursive_bubbe_sort.f90 @@ -1,8 +1,8 @@ !> Test program for the Bubble Sort algorithm !! !! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) -!! in Pull Request: #27 -!! https://github.com/TheAlgorithms/Fortran/pull/27 +!! in Pull Request: #29 +!! https://github.com/TheAlgorithms/Fortran/pull/29 !! !! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request !! addressing bugs/corrections to this file. Thank you! From cf268b232166c3b9a0828584c485487615206d04 Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 17:26:09 +0200 Subject: [PATCH 4/6] Implementing ctest-friendly tests for /searches modules --- .github/workflows/ci.yml | 2 +- tests/searches/linear_search.f90 | 122 +++++++++++++++++++++ tests/searches/recursive_linear_search.f90 | 122 +++++++++++++++++++++ tests/searches/ternary_search_array.f90 | 121 ++++++++++++++++++++ tests/searches/ternary_search_function.f90 | 85 ++++++++++++++ 5 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 tests/searches/linear_search.f90 create mode 100644 tests/searches/recursive_linear_search.f90 create mode 100644 tests/searches/ternary_search_array.f90 create mode 100644 tests/searches/ternary_search_function.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/tests/searches/linear_search.f90 b/tests/searches/linear_search.f90 new file mode 100644 index 0000000..8d23203 --- /dev/null +++ b/tests/searches/linear_search.f90 @@ -0,0 +1,122 @@ +!> Test program for the Linear Search algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #30 +!! https://github.com/TheAlgorithms/Fortran/pull/30 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides additional test cases to validate the linear_search_module. + + +program tests_linear_search + use linear_search_module + implicit none + integer, dimension(:), allocatable :: array + integer :: target, index, expected + + ! Run test cases + call test_found() + call test_not_found() + call test_first_element() + call test_last_element() + call test_multiple_occurrences() + call test_single_element_found() + call test_single_element_not_found() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test case 1: Target is found in the array + subroutine test_found() + array = (/30, 10, 20, 40, 55, 61, 72, 86, 97, 101/) + target = 97 + expected = 9 + index = linear_search(array, target) + call assert_test(index, expected, "Test 1: Target found in the array") + end subroutine test_found + + ! Test case 2: Target is not found in the array + subroutine test_not_found() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11/) + target = 66 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 2: Target not found in the array") + end subroutine test_not_found + + ! Test case 3: Target is the first element + subroutine test_first_element() + array = (/10, 20, 30, 40, 50/) + target = array(1) + expected = 1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 3: Target is the first element") + end subroutine test_first_element + + ! Test case 4: Target is the last element + subroutine test_last_element() + array = (/10, 20, 30, 40, 50, 60, 70, 80/) + target = array(size(array)) + expected = size(array) + index = linear_search(array, target) + call assert_test(index, expected, "Test 4: Target is the last element") + end subroutine test_last_element + + ! Test case 5: Multiple occurrences of the target + subroutine test_multiple_occurrences() + array = (/1, 2, 3, 2, 4, 2, 5, 2, 4/) + target = 4 + expected = 5 + index = linear_search(array, target) + call assert_test(index, expected, "Test 5: Target has multiple occurrences (first found)") + end subroutine test_multiple_occurrences + + ! Test case 6: Single element found + subroutine test_single_element_found() + array = (/42/) + target = 42 + expected = 1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 6: Single element found") + end subroutine test_single_element_found + + ! Test case 7: Single element not found + subroutine test_single_element_not_found() + array = (/42/) + target = 99 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 7: Single element not found") + end subroutine test_single_element_not_found + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + allocate (array(0)) ! Empty array + target = 1 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 8: Search in an empty array") + end subroutine test_empty_array + + !> 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_linear_search diff --git a/tests/searches/recursive_linear_search.f90 b/tests/searches/recursive_linear_search.f90 new file mode 100644 index 0000000..d264e03 --- /dev/null +++ b/tests/searches/recursive_linear_search.f90 @@ -0,0 +1,122 @@ +!> Test program for the Recursive Linear Search algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #30 +!! https://github.com/TheAlgorithms/Fortran/pull/30 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides additional test cases to validate the recursive_linear_search_module. + + +program tests_recursive_linear_search + use linear_search_module + implicit none + integer, dimension(:), allocatable :: array + integer :: target, index, expected + + ! Run test cases + call test_found() + call test_not_found() + call test_first_element() + call test_last_element() + call test_multiple_occurrences() + call test_single_element_found() + call test_single_element_not_found() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test case 1: Target is found in the array + subroutine test_found() + array = (/30, 10, 20, 40, 55, 61, 72, 86, 97, 101/) + target = 97 + expected = 9 + index = linear_search(array, target) + call assert_test(index, expected, "Test 1: Target found in the array") + end subroutine test_found + + ! Test case 2: Target is not found in the array + subroutine test_not_found() + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11/) + target = 66 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 2: Target not found in the array") + end subroutine test_not_found + + ! Test case 3: Target is the first element + subroutine test_first_element() + array = (/10, 20, 30, 40, 50/) + target = array(1) + expected = 1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 3: Target is the first element") + end subroutine test_first_element + + ! Test case 4: Target is the last element + subroutine test_last_element() + array = (/10, 20, 30, 40, 50, 60, 70, 80/) + target = array(size(array)) + expected = size(array) + index = linear_search(array, target) + call assert_test(index, expected, "Test 4: Target is the last element") + end subroutine test_last_element + + ! Test case 5: Multiple occurrences of the target + subroutine test_multiple_occurrences() + array = (/1, 2, 3, 2, 4, 2, 5, 2, 4/) + target = 4 + expected = 5 + index = linear_search(array, target) + call assert_test(index, expected, "Test 5: Target has multiple occurrences (first found)") + end subroutine test_multiple_occurrences + + ! Test case 6: Single element found + subroutine test_single_element_found() + array = (/42/) + target = 42 + expected = 1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 6: Single element found") + end subroutine test_single_element_found + + ! Test case 7: Single element not found + subroutine test_single_element_not_found() + array = (/42/) + target = 99 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 7: Single element not found") + end subroutine test_single_element_not_found + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(array)) deallocate (array) + allocate (array(0)) ! Empty array + target = 1 + expected = -1 + index = linear_search(array, target) + call assert_test(index, expected, "Test 8: Search in an empty array") + end subroutine test_empty_array + + !> 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_recursive_linear_search diff --git a/tests/searches/ternary_search_array.f90 b/tests/searches/ternary_search_array.f90 new file mode 100644 index 0000000..b66ac1e --- /dev/null +++ b/tests/searches/ternary_search_array.f90 @@ -0,0 +1,121 @@ +!> Test program for the Array-Based Ternary Search algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #30 +!! https://github.com/TheAlgorithms/Fortran/pull/30 +!! +!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request +!! addressing bugs/corrections to this file. Thank you! +!! +!! This program provides additional test cases to validate the array-based ternary_search module. + +program tests_ternary_search_array + use ternary_search + implicit none + integer, dimension(:), allocatable :: sorted_array + integer :: target, index, expected + + ! Run test cases + call test_found() + call test_not_found() + call test_first_element() + call test_last_element() + call test_multiple_occurrences() + call test_single_element_found() + call test_single_element_not_found() + call test_empty_array() + + print *, "All tests completed." + +contains + + ! Test case 1: Target found + subroutine test_found() + sorted_array = (/1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25/) + target = 21 + expected = 11 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 1: Target found in the array") + end subroutine test_found + + ! Test case 2: Target not found + subroutine test_not_found() + sorted_array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12/) + target = 110 + expected = -1 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, -1, "Test 2: Target not found in the array") + end subroutine test_not_found + + ! Test case 3: Target is the first element + subroutine test_first_element() + sorted_array = (/10, 20, 30, 40, 50, 60, 70, 80/) + target = sorted_array(1) + expected = 1 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 3: Target is the first element") + end subroutine test_first_element + + ! Test case 4: Target is the last element + subroutine test_last_element() + sorted_array = (/100, 200, 300, 400, 500, 600, 700, 800, 900/) + target = sorted_array(size(sorted_array)) + expected = size(sorted_array) + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 4: Target is the last element") + end subroutine test_last_element + + ! Test case 5: Multiple occurrences of the target + subroutine test_multiple_occurrences() + sorted_array = (/1, 1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12/) + target = 12 + expected = 16 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 5: Target has multiple occurrences (first found)") + end subroutine test_multiple_occurrences + + ! Test case 6: Single element found + subroutine test_single_element_found() + sorted_array = (/59/) + target = 59 + expected = 1 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 6: Single element found") + end subroutine test_single_element_found + + ! Test case 7: Single element not found + subroutine test_single_element_not_found() + sorted_array = (/42/) + target = 99 + expected = -1 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 7: Single element not found") + end subroutine test_single_element_not_found + + ! Test case 8: Empty array + subroutine test_empty_array() + if (allocated(sorted_array)) deallocate (sorted_array) + allocate (sorted_array(0)) ! Empty array + target = 1 + expected = -1 + index = ternary_search_array(sorted_array, target, 1, size(sorted_array)) + call assert_test(index, expected, "Test 8: Search in an empty array") + end subroutine test_empty_array + + !> 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_ternary_search_array diff --git a/tests/searches/ternary_search_function.f90 b/tests/searches/ternary_search_function.f90 new file mode 100644 index 0000000..e137b46 --- /dev/null +++ b/tests/searches/ternary_search_function.f90 @@ -0,0 +1,85 @@ +!> Test program for the Function-Based Ternary Search algorithm +!! +!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) +!! in Pull Request: #30 +!! https://github.com/TheAlgorithms/Fortran/pull/30 +!! +!! 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 function-based ternary search algorithms for known functions. + +program tests_ternary_search_function + use ternary_search + implicit none + real(8) :: tol, left, right, result, expected + + tol = 1.0d-6 + left = -100.0d0 + right = 100.0d0 + + ! Run test cases + call test_find_min_parabola() + call test_find_max_negative_parabola() + call test_find_min_custom_function() + + print *, "All tests completed." + +contains + + ! Test case 1: Find minimum of a parabola (f(x) = x^2) + subroutine test_find_min_parabola() + result = ternary_search_minimum(parabola, left, right, tol) + expected = 0.0d0 + call assert_test(abs(result), expected, "Test 1: Find minimum of f(x) = x^2") + end subroutine test_find_min_parabola + + ! Test case 2: Find maximum of a negative parabola (f(x) = -x^2) + subroutine test_find_max_negative_parabola() + result = ternary_search_maximum(negative_parabola, left, right, tol) + expected = 0.0d0 + call assert_test(abs(result), expected, "Test 2: Find maximum of f(x) = -x^2") + end subroutine test_find_max_negative_parabola + + ! Test case 3: Find minimum of a custom unimodal function + subroutine test_find_min_custom_function() + result = ternary_search_minimum(custom_unimodal_function, left, right, tol) + expected = 50.0d0 + call assert_test(result, 50.0d0, "Test 3: Find minimum of custom unimodal function") + end subroutine test_find_min_custom_function + + !> Subroutine to assert the test results + subroutine assert_test(actual, expected, test_name) + real(8), intent(in) :: actual, expected + character(len=*), intent(in) :: test_name + + if (abs(actual - expected) < tol) then + print *, test_name, " PASSED" + else + print *, test_name, " FAILED" + print *, "Expected: ", expected + print *, "Got: ", actual + stop 1 + end if + + end subroutine assert_test + + ! Parabola function: f(x) = x^2 + real(8) function parabola(x) + real(8), intent(in) :: x + parabola = x**2 + end function parabola + + ! Negative parabola function: f(x) = -x^2 + real(8) function negative_parabola(x) + real(8), intent(in) :: x + negative_parabola = -x**2 + end function negative_parabola + + ! Custom unimodal function: A function with a known minimum at x = 50 + real(8) function custom_unimodal_function(x) + real(8), intent(in) :: x + custom_unimodal_function = (x - 50.0d0)**2 + 100.0d0 + end function custom_unimodal_function + +end program tests_ternary_search_function From 5f45884093d676bfdc8d1ad8602b0ecd2c704822 Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 17:27:43 +0200 Subject: [PATCH 5/6] File renaming --- tests/sorts/{tests_bubble_sort.f90 => bubble_sort.f90} | 0 tests/sorts/{tests_gnome_sort.f90 => gnome_sort.f90} | 0 tests/sorts/{tests_heap_sort.f90 => heap_sort.f90} | 0 tests/sorts/{tests_merge_sort.f90 => merge_sort.f90} | 0 tests/sorts/{tests_quick_sort.f90 => quick_sort.f90} | 0 tests/sorts/{tests_radix_sort.f90 => radix_sort.f90} | 0 .../{tests_recursive_bubbe_sort.f90 => recursive_bubbe_sort.f90} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tests/sorts/{tests_bubble_sort.f90 => bubble_sort.f90} (100%) rename tests/sorts/{tests_gnome_sort.f90 => gnome_sort.f90} (100%) rename tests/sorts/{tests_heap_sort.f90 => heap_sort.f90} (100%) rename tests/sorts/{tests_merge_sort.f90 => merge_sort.f90} (100%) rename tests/sorts/{tests_quick_sort.f90 => quick_sort.f90} (100%) rename tests/sorts/{tests_radix_sort.f90 => radix_sort.f90} (100%) rename tests/sorts/{tests_recursive_bubbe_sort.f90 => recursive_bubbe_sort.f90} (100%) diff --git a/tests/sorts/tests_bubble_sort.f90 b/tests/sorts/bubble_sort.f90 similarity index 100% rename from tests/sorts/tests_bubble_sort.f90 rename to tests/sorts/bubble_sort.f90 diff --git a/tests/sorts/tests_gnome_sort.f90 b/tests/sorts/gnome_sort.f90 similarity index 100% rename from tests/sorts/tests_gnome_sort.f90 rename to tests/sorts/gnome_sort.f90 diff --git a/tests/sorts/tests_heap_sort.f90 b/tests/sorts/heap_sort.f90 similarity index 100% rename from tests/sorts/tests_heap_sort.f90 rename to tests/sorts/heap_sort.f90 diff --git a/tests/sorts/tests_merge_sort.f90 b/tests/sorts/merge_sort.f90 similarity index 100% rename from tests/sorts/tests_merge_sort.f90 rename to tests/sorts/merge_sort.f90 diff --git a/tests/sorts/tests_quick_sort.f90 b/tests/sorts/quick_sort.f90 similarity index 100% rename from tests/sorts/tests_quick_sort.f90 rename to tests/sorts/quick_sort.f90 diff --git a/tests/sorts/tests_radix_sort.f90 b/tests/sorts/radix_sort.f90 similarity index 100% rename from tests/sorts/tests_radix_sort.f90 rename to tests/sorts/radix_sort.f90 diff --git a/tests/sorts/tests_recursive_bubbe_sort.f90 b/tests/sorts/recursive_bubbe_sort.f90 similarity index 100% rename from tests/sorts/tests_recursive_bubbe_sort.f90 rename to tests/sorts/recursive_bubbe_sort.f90 From 76e7c83b237bf6cf320e77b2b1b5a3bf6232db8a Mon Sep 17 00:00:00 2001 From: Ramy-Badr-Ahmed Date: Wed, 9 Oct 2024 17:39:55 +0200 Subject: [PATCH 6/6] code_style fix --- tests/searches/linear_search.f90 | 1 - tests/searches/recursive_linear_search.f90 | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/searches/linear_search.f90 b/tests/searches/linear_search.f90 index 8d23203..cb40616 100644 --- a/tests/searches/linear_search.f90 +++ b/tests/searches/linear_search.f90 @@ -9,7 +9,6 @@ !! !! This program provides additional test cases to validate the linear_search_module. - program tests_linear_search use linear_search_module implicit none diff --git a/tests/searches/recursive_linear_search.f90 b/tests/searches/recursive_linear_search.f90 index d264e03..38f4847 100644 --- a/tests/searches/recursive_linear_search.f90 +++ b/tests/searches/recursive_linear_search.f90 @@ -9,7 +9,6 @@ !! !! This program provides additional test cases to validate the recursive_linear_search_module. - program tests_recursive_linear_search use linear_search_module implicit none