diff --git a/CMakeLists.txt b/CMakeLists.txt index 13c4c3b..a7cffc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ include(GNUInstallDirs) add_subdirectory(lib) if(NOT BUILD_EXPORTED_TARGETS_ONLY) + enable_testing() add_subdirectory(test) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0b6785c..394cd1e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,9 @@ -set(targets +set(tested test_allgather - test_allgatherv + test_allgatherv) + +set(targets + ${tested} test_allreduce test_bcast test_comm_split @@ -12,7 +15,29 @@ set(targets test_scatterv test_win_shared_mem) +set(sources-helper + testhelper.f90) + +add_library(mpifxtesthelp ${sources-helper}) +target_link_libraries(mpifxtesthelp PRIVATE MPI::MPI_Fortran MpiFx) + foreach(target IN LISTS targets) add_executable(${target} ${target}.f90) - target_link_libraries(${target} MpiFx) + target_link_libraries(${target} MpiFx mpifxtesthelp) +endforeach() + +foreach(target IN LISTS tested) + add_test(NAME ${target} + COMMAND ${MPIEXEC_EXECUTABLE} + ${MPIEXEC_NUMPROC_FLAG} + ${MPIEXEC_MAX_NUMPROCS} + ${MPIEXEC_PREFLAGS} + ${CMAKE_CURRENT_BINARY_DIR}/${target} + ${MPIEXEC_POSTFLAGS}) + set_tests_properties(${target} PROPERTIES + # test cases generate this on stdOut + PASS_REGULAR_EXPRESSION "TestPASSED") + set_tests_properties(${target} PROPERTIES + # test cases generate this on stdOut + FAIL_REGULAR_EXPRESSION "TestFAILED") endforeach() diff --git a/test/test_allgather.f90 b/test/test_allgather.f90 index 7b58d3e..437734c 100644 --- a/test/test_allgather.f90 +++ b/test/test_allgather.f90 @@ -1,5 +1,7 @@ +!> Test various patterns of allgather program test_allgather use libmpifx_module + use testhelper implicit none type(mpifx_comm) :: mycomm @@ -8,6 +10,7 @@ program test_allgather integer, allocatable :: recv1(:), recv2(:,:) character(100) :: formstr character(*), parameter :: label = "(I2.2,'-',I3.3,'|',1X" + logical :: tPassed call mpifx_init() call mycomm%init() @@ -16,12 +19,16 @@ program test_allgather send0 = mycomm%rank * 2 allocate(recv1(1 * mycomm%size)) recv1(:) = 0 - write(*, label // ",A,1X,I0)") 1, mycomm%rank, & - & "Send0 buffer:", send0 + write(*, label // ",A,1X,I0)") 1, mycomm%rank, "Send0 buffer:", send0 call mpifx_allgather(mycomm, send0, recv1) write(formstr, "(A,I0,A)") "A,", size(recv1), "(1X,I0))" - write(*, label // formstr) 2, mycomm%rank, & - & "Recv1 buffer:", recv1(:) + write(*, label // formstr) 2, mycomm%rank, "Recv1 buffer:", recv1(:) + if (sum(recv1) /= mycomm%size * (mycomm%size-1)) then + tPassed = .false. + else + tPassed = .true. + end if + call testReturn(mycomm, tPassed) deallocate(recv1) ! I1 -> I1 @@ -30,25 +37,33 @@ program test_allgather recv1(:) = 0 send1(:) = [ mycomm%rank, mycomm%rank + 1 ] write(formstr, "(A,I0,A)") "A,", size(send1), "(1X,I0))" - write(*, label // formstr) 3, mycomm%rank, & - & "Send1 buffer:", send1(:) + write(*, label // formstr) 3, mycomm%rank, "Send1 buffer:", send1(:) call mpifx_allgather(mycomm, send1, recv1) write(formstr, "(A,I0,A)") "A,", size(recv1), "(1X,I0))" - write(*, label // formstr) 4, mycomm%rank, & - & "Recv1 buffer:", recv1 + write(*, label // formstr) 4, mycomm%rank, "Recv1 buffer:", recv1 + if (sum(recv1) /= mycomm%size**2) then + tPassed = .false. + else + tPassed = .true. + end if + call testReturn(mycomm, tPassed) ! I1 -> I2 allocate(recv2(size(send1), mycomm%size)) recv2(:,:) = 0 send1(:) = [ mycomm%rank, mycomm%rank + 1 ] write(formstr, "(A,I0,A)") "A,", size(send1), "(1X,I0))" - write(*, label // formstr) 5, mycomm%rank, & - & "Send1 buffer:", send1(:) + write(*, label // formstr) 5, mycomm%rank, "Send1 buffer:", send1(:) call mpifx_allgather(mycomm, send1, recv2) write(formstr, "(A,I0,A)") "A,", size(recv2), "(1X,I0))" - write(*, label // formstr) 6, mycomm%rank, & - & "Recv2 buffer:", recv2 - + write(*, label // formstr) 6, mycomm%rank, "Recv2 buffer:", recv2 + if (sum(recv1) /= mycomm%size**2) then + tPassed = .false. + else + tPassed = .true. + end if + call testReturn(mycomm, tPassed) + call mpifx_finalize() - + end program test_allgather diff --git a/test/test_allgatherv.f90 b/test/test_allgatherv.f90 index e3c831d..ae46762 100644 --- a/test/test_allgatherv.f90 +++ b/test/test_allgatherv.f90 @@ -1,5 +1,7 @@ +!> Test various patterns of allgatherv program test_allgatherv use libmpifx_module + use testhelper implicit none type(mpifx_comm) :: mycomm @@ -12,6 +14,8 @@ program test_allgatherv integer :: ii, nrecv, nCol character(100) :: formstr character(*), parameter :: label = "(I2.2,'-',I3.3,'|',1X" + logical :: tPassed + integer :: iCount call mpifx_init() call mycomm%init() @@ -33,6 +37,15 @@ program test_allgatherv if (mycomm%rank == mycomm%size - 1) then write(*, *) "Recv1 buffer:", recv1 end if + ! test what has been gathered + iCount = (2*mycomm%size**3+3*mycomm%size**2+mycomm%size)/6 + if (nint(sum(recv1)) /= iCount) then + tPassed = .false. + else + tPassed = .true. + end if + tPassed = tPassed .and. (abs(sum(recv1)-nint(sum(recv1))) < epsilon(1.0_sp)) + call testReturn(mycomm, tPassed) deallocate(recvcounts) deallocate(recv1) @@ -59,6 +72,14 @@ program test_allgatherv write(*,*)recv2(:,ii) end do end if + iCount = 5*mycomm%size*(mycomm%size+1)*(2*mycomm%size+1)/6 + if (nint(sum(recv2)) /= iCount) then + tPassed = .false. + else + tPassed = .true. + end if + tPassed = tPassed .and. (abs(sum(recv2)-nint(sum(recv2))) < epsilon(1.0_sp)) + call testReturn(mycomm, tPassed) deallocate(recvcounts) @@ -81,6 +102,14 @@ program test_allgatherv if (mycomm%rank == mycomm%size - 1) then write(*, *) "Recv1 buffer:", recv1 end if + ! test what has been gathered + if (nint(sum(recv1)) /= (mycomm%size*(mycomm%size+1))/2) then + tPassed = .false. + else + tPassed = .true. + end if + tPassed = tPassed .and. (abs(sum(recv1)-nint(sum(recv1))) < epsilon(1.0_sp)) + call testReturn(mycomm, tPassed) call mpifx_finalize() diff --git a/test/testhelper.f90 b/test/testhelper.f90 new file mode 100644 index 0000000..4e8878d --- /dev/null +++ b/test/testhelper.f90 @@ -0,0 +1,36 @@ +!> Helper routines for testers +module testhelper + use libmpifx_module, only : mpifx_comm, mpifx_barrier, mpifx_finalize + implicit none + + private + public :: testReturn + +contains + + !> Return expected labels for ctest + subroutine testReturn(mycomm, tPassed) + + type(mpifx_comm), intent(in) :: mycomm + + logical, intent(in) :: tPassed + + call mpifx_barrier(mycomm) + + if (tPassed) then + if (mycomm%rank == 0) then + ! label for ctest regex + write(*,*)'TestPASSED' + end if + else + if (mycomm%rank == 0) then + ! label for ctest regex + write(*,*)'TestFAILED' + end if + call mpifx_finalize() + stop + end if + + end subroutine testReturn + +end module testhelper