/*
** Simple test program 04 for the MIAMI protocol
** Rolf Riesen, December 2009
**
** Usage: test_04 local_host local_port remote_host remote_port rank
** rank should be 0 in one process, and 1 in the other.
**
** Test messages shorter and longer than requested.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#if defined (_MPI_)
#include <mpi.h>
#endif
#include "miami.h"

#define BUF_SIZE	(64)



int
main(int argc, char *argv[])
{

char *host1;
char *host2;
int sbuf[BUF_SIZE];
int rbuf[BUF_SIZE];
int port1, port2;
int rank;
int tag;
int shandle, rhandle;
int bytes;
int i, rc;
int length;


    if (argc != 6)   {
	fprintf(stderr, "Usage: %s local_host local_port remote_host remote_port rank\n", argv[0]);
	return -1;
    }

    host1= argv[1];
    host2= argv[3];
    port1= strtol(argv[2], NULL, 10);
    port2= strtol(argv[4], NULL, 10);
    rank= strtol(argv[5], NULL, 10);

    miami_init(host1, port1, host2, port2);
#if defined (_MPI_)
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#endif

    tag= 12;
    rc= 0;

    /* Fill the send buffer */
    for (i= 0; i < BUF_SIZE; i++)   {
	sbuf[i]= i;
    }

    if (rank == 0)   {
	/* I'm the sender */

	/* Send a little less */
	length= sizeof(int) * (BUF_SIZE - 2);
	printf("Test Test 1: sending %d bytes\n", length);
	shandle= miami_tx_start(sbuf, length, tag);
	while (!miami_tx_done(shandle))   {
	}

	/* Send a little more */
	length= sizeof(int) * BUF_SIZE;
	printf("Test Test 2: sending %d bytes\n", length);
	shandle= miami_tx_start(sbuf, length, tag);
	while (!miami_tx_done(shandle))   {
	}

    } else   {

	/* I'm the receiver */

	/* Clear the receive buffer */
	memset(rbuf, 0, sizeof(int) * BUF_SIZE);

	/* Post a receive */
	length= sizeof(int) * BUF_SIZE;
	printf("Test Test 1: posting %d bytes, but expecting %ld bytes\n", length,
	    sizeof(int) * (BUF_SIZE - 2));
	rhandle= miami_rx_start(rbuf, length, tag);
	while (!miami_rx_done(rhandle, &bytes))   {
	    /* Wait for that message */
	}

	if (bytes != sizeof(int) * (BUF_SIZE - 2))   {
	    printf("Test Test 1: Error: received %d bytes, but wanted %ld bytes\n",
		bytes, sizeof(int) * (BUF_SIZE - 2));
	    rc= 1;
	} else   {
	    printf("Test Test 1: Received %d bytes\n", bytes);
	}

	/* Check the receive buffer against the send buffer */
	for (i= 0; i < (bytes / (int)sizeof(int)); i++)   {
	    if (rbuf[i] != sbuf[i])   {
		fprintf(stderr, "Test Test 1: Send and recv buffer differ at position "
		    "%d: %d != %d\n", i, rbuf[i], sbuf[i]);
		rc= 1;
		break;
	    }
	}

	/* The remainder of the recv buffer should be untouched */
	for (i= (bytes / sizeof(int)) + 1; i < BUF_SIZE; i++)   {
	    if (rbuf[i] != 0)   {
		fprintf(stderr, "Test Test 1: Send and recv buffer differ at position "
		    "%d: %d != %d\n", i, rbuf[i], sbuf[i]);
		rc= 1;
		break;
	    }
	}

	/* Clear the receive buffer */
	memset(rbuf, 0, sizeof(int) * BUF_SIZE);

	/* Post a receive */
	length= sizeof(int) * (BUF_SIZE - 2);
	printf("Test Test 2: posting %d bytes, will get %ld bytes, but receive only %d\n",
	    length, sizeof(int) * BUF_SIZE, length);

	rhandle= miami_rx_start(rbuf, length, tag);
	while (!miami_rx_done(rhandle, &bytes))   {
	    /* Wait for that message */
	}

	if (bytes != length)   {
	    printf("Test Test 2: Error: received %d bytes, but wanted %d bytes\n", bytes, length);
	    rc= 1;
	} else   {
	    printf("Test Test 2: Received %d bytes\n", bytes);
	}

	/* Check the receive buffer against the send buffer */
	for (i= 0; i < (bytes / (int)sizeof(int)); i++)   {
	    if (rbuf[i] != sbuf[i])   {
		fprintf(stderr, "Test Test 2: Send and recv buffer differ at position %d: %d != %d\n", i, rbuf[i], sbuf[i]);
		rc= 1;
		break;
	    }
	}

	/* The remainder of the recv buffer should be untouched */
	for (i= (bytes / sizeof(int)) + 1; i < BUF_SIZE; i++)   {
	    if (rbuf[i] != 0)   {
		fprintf(stderr, "Test Test 2: Send and recv buffer differ at position %d: %d != %d\n", i, rbuf[i], sbuf[i]);
		rc= 1;
		break;
	    }
	}


    }

    miami_finalize();

    return rc;

}  /* end of main() */
