module testBaseMpi
  use testHelperMpi
  use mpidefs

  implicit none

contains

  @before
  subroutine setup(this)
      class (MpiTestMethod), intent(inout) :: this

      call setMpiReal()

  end subroutine setup

  @after
  subroutine teardown(this)
      class (MpiTestMethod), intent(inout) :: this

  end subroutine teardown

  @test(npes=[2])
  subroutine test2ProcNeighborAllgather(this)
      class (MpiTestMethod), intent(inout) :: this

      integer :: neighborRank(1), ierr
      type(MPI_Comm) :: newComm

      real(rp) :: outValue, inValue

      if(this%getProcessRank() == 0) then
          neighborRank = 1
      else
          neighborRank = 0
      endif

      call mpi_dist_graph_create_adjacent(getMpiF08Communicator(this), &
                    1,neighborRank,(/1/), &
                    1,neighborRank,(/1/), &
                    MPI_INFO_NULL, .false., newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'create graph failed')

      outValue = 1
      inValue = 2

      call mpi_neighbor_allgather(outValue,1,MPI_MYFLOAT,inValue,1,MPI_MYFLOAT,newComm,ierr)
      @assertEqual(MPI_SUCCESS,ierr,'allgather failed')

      @assertEqual(1, inValue, 'comms failed')

  end subroutine test2ProcNeighborAllgather

  @test(npes=[2])
  subroutine test2ProcNeighborAllgatherv(this)
      class (MpiTestMethod), intent(inout) :: this

      integer :: neighborRank(1), ierr
      type(MPI_Comm) :: newComm

      real(rp) :: outValue, inValue

      if(this%getProcessRank() == 0) then
          neighborRank = 1
      else
          neighborRank = 0
      endif

      call mpi_dist_graph_create_adjacent(getMpiF08Communicator(this), &
                    1,neighborRank,(/1/), &
                    1,neighborRank,(/1/), &
                    MPI_INFO_NULL, .false., newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'create graph failed')

      outValue = 1
      inValue = 2

      call mpi_neighbor_allgatherv(outValue,1,MPI_MYFLOAT,inValue,(/1/),(/0/),MPI_MYFLOAT,newComm,ierr)
      @assertEqual(MPI_SUCCESS,ierr,'allgatherv failed')

      @assertEqual(1, inValue, 'comms failed')

  end subroutine test2ProcNeighborAllgatherv

  @test(npes=[2])
  subroutine test2ProcNeighborAlltoall(this)
      class (MpiTestMethod), intent(inout) :: this

      integer :: neighborRank(1), ierr
      type(MPI_Comm) :: newComm

      real(rp) :: outValue, inValue

      if(this%getProcessRank() == 0) then
          neighborRank = 1
      else
          neighborRank = 0
      endif

      call mpi_dist_graph_create_adjacent(getMpiF08Communicator(this), &
                    1,neighborRank,(/1/), &
                    1,neighborRank,(/1/), &
                    MPI_INFO_NULL, .false., newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'create graph failed')

      outValue = 1
      inValue = 2

      call mpi_neighbor_alltoall(outValue, 1, MPI_MYFLOAT, &
                                  inValue,  1, MPI_MYFLOAT, &
                                  newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'alltoall failed')

      @assertEqual(1, inValue, 'comms failed')

  end subroutine test2ProcNeighborAlltoall

  @test(npes=[2])
  subroutine test2ProcNeighborAlltoallv(this)
      class (MpiTestMethod), intent(inout) :: this

      integer :: neighborRank(1), ierr
      type(MPI_Comm) :: newComm

      real(rp) :: outValue, inValue

      if(this%getProcessRank() == 0) then
          neighborRank = 1
      else
          neighborRank = 0
      endif

      call mpi_dist_graph_create_adjacent(getMpiF08Communicator(this), &
                    1,neighborRank,(/1/), &
                    1,neighborRank,(/1/), &
                    MPI_INFO_NULL, .false., newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'create graph failed')

      outValue = 1
      inValue = 2

      call mpi_neighbor_alltoallv(outValue, (/1/), (/0/), MPI_MYFLOAT, &
                                  inValue,  (/1/), (/0/), MPI_MYFLOAT, &
                                  newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'alltoallv failed')

      @assertEqual(1, inValue, 'comms failed')

  end subroutine test2ProcNeighborAlltoallv

  @test(npes=[2])
  subroutine test2ProcNeighborAlltoallw(this)
      class (MpiTestMethod), intent(inout) :: this

      integer :: neighborRank(1), ierr
      type(MPI_Comm) :: newComm
      integer(kind=MPI_AN_MYADDR) :: sDisp(1),rDisp(1)

      real(rp) :: outValue, inValue

      if(this%getProcessRank() == 0) then
          neighborRank = 1
      else
          neighborRank = 0
      endif

      call mpi_dist_graph_create_adjacent(getMpiF08Communicator(this), &
                    1,neighborRank,(/1/), &
                    1,neighborRank,(/1/), &
                    MPI_INFO_NULL, .false., newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'create graph failed')

      outValue = 1
      inValue = 2

      sDisp = 0
      rDisp = 0

      call mpi_neighbor_alltoallw(outValue, (/1/), sDisp, (/MPI_MYFLOAT/), &
                                  inValue,  (/1/), rDisp, (/MPI_MYFLOAT/), &
                                  newComm, ierr)
      @assertEqual(MPI_SUCCESS,ierr,'alltoallw failed')

      @assertEqual(1, inValue, 'comms failed')

  end subroutine test2ProcNeighborAlltoallw

end module testBaseMpi

