Blame test/mpi/cxx/spawn/spawnargvx.cxx

Packit 0848f5
/* -*- Mode: C++; c-basic-offset:4 ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *
Packit 0848f5
 *  (C) 2003 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include "mpitestconf.h"
Packit 0848f5
#ifdef HAVE_IOSTREAM
Packit 0848f5
// Not all C++ compilers have iostream instead of iostream.h
Packit 0848f5
#include <iostream>
Packit 0848f5
#ifdef HAVE_NAMESPACE_STD
Packit 0848f5
// Those that do need the std namespace; otherwise, a bare "cout"
Packit 0848f5
// is likely to fail to compile
Packit 0848f5
using namespace std;
Packit 0848f5
#endif
Packit 0848f5
#else
Packit 0848f5
#include <iostream.h>
Packit 0848f5
#endif
Packit 0848f5
#include "mpitestcxx.h"
Packit 0848f5
#ifdef HAVE_STRING_H
Packit 0848f5
#include <string.h>
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
static char MTEST_Descrip[] = "A simple test of Comm_spawn, with complex arguments";
Packit 0848f5
Packit 0848f5
int main( int argc, char *argv[] )
Packit 0848f5
{
Packit 0848f5
    int errs = 0, err;
Packit 0848f5
    int rank, size, rsize, i;
Packit 0848f5
    int np = 2;
Packit 0848f5
    int errcodes[2];
Packit 0848f5
    MPI::Intercomm      parentcomm, intercomm;
Packit 0848f5
    MPI::Status         status;
Packit 0848f5
    const char * inargv[]  = { "a", "b=c", "d e", "-pf", " Ss", 0 };
Packit 0848f5
    const char * outargv[] = { "a", "b=c", "d e", "-pf", " Ss", 0 };
Packit 0848f5
Packit 0848f5
    MTest_Init( );
Packit 0848f5
Packit 0848f5
    parentcomm = MPI::Comm::Get_parent();
Packit 0848f5
Packit 0848f5
    if (parentcomm == MPI::COMM_NULL) {
Packit 0848f5
	/* Create 2 more processes */
Packit 0848f5
	/* ./ is unix specific .
Packit 0848f5
	   The more generic approach would be to specify "spawnargv" as the 
Packit 0848f5
	   executable and pass an info with ("path", ".") */
Packit 0848f5
	intercomm = MPI::COMM_WORLD.Spawn( "./spawnargvx", inargv, np,
Packit 0848f5
			MPI::INFO_NULL, 0, errcodes );
Packit 0848f5
    }
Packit 0848f5
    else 
Packit 0848f5
	intercomm = parentcomm;
Packit 0848f5
Packit 0848f5
    /* We now have a valid intercomm */
Packit 0848f5
Packit 0848f5
    rsize = intercomm.Get_remote_size();
Packit 0848f5
    size  = intercomm.Get_size();
Packit 0848f5
    rank  = intercomm.Get_rank();
Packit 0848f5
Packit 0848f5
    if (parentcomm == MPI::COMM_NULL) {
Packit 0848f5
	/* Master */
Packit 0848f5
	if (rsize != np) {
Packit 0848f5
	    errs++;
Packit 0848f5
	    cout << "Did not create " << np << " processes (got " <<
Packit 0848f5
		rsize << ")\n";
Packit 0848f5
	}
Packit 0848f5
	for (i=0; i
Packit 0848f5
	    intercomm.Send( &i, 1, MPI::INT, i, 0 );
Packit 0848f5
	}
Packit 0848f5
	/* We could use intercomm reduce to get the errors from the 
Packit 0848f5
	   children, but we'll use a simpler loop to make sure that
Packit 0848f5
	   we get valid data */
Packit 0848f5
	for (i=0; i
Packit 0848f5
	    intercomm.Recv( &err, 1, MPI::INT, i, 1 );
Packit 0848f5
	    errs += err;
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    else {
Packit 0848f5
	/* Child */
Packit 0848f5
	/* FIXME: This assumes that stdout is handled for the children
Packit 0848f5
	   (the error count will still be reported to the parent) */
Packit 0848f5
	if (size != np) {
Packit 0848f5
	    errs++;
Packit 0848f5
	    cout << "(Child) Did not create " << np << " (got " <<
Packit 0848f5
		size << ")\n";
Packit 0848f5
	}
Packit 0848f5
	intercomm.Recv( &i, 1, MPI::INT, 0, 0, status );
Packit 0848f5
	if (i != rank) {
Packit 0848f5
	    errs++;
Packit 0848f5
	    cout << "Unexpected rank on child " << rank << " (" << 
Packit 0848f5
		i << "\n";
Packit 0848f5
	}
Packit 0848f5
	/* Check the command line */
Packit 0848f5
	for (i=1; i
Packit 0848f5
	    if (!outargv[i-1]) {
Packit 0848f5
		errs++;
Packit 0848f5
		cout << "Wrong number of arguments (" << argc << ")\n";
Packit 0848f5
		break;
Packit 0848f5
	    }
Packit 0848f5
	    if (strcmp( argv[i], outargv[i-1] ) != 0) {
Packit 0848f5
		errs++;
Packit 0848f5
		cout << "Found arg " << argv[i] << " but expected " <<
Packit 0848f5
		    outargv[i-1] << "\n";
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
	if (outargv[i-1]) {
Packit 0848f5
	    /* We had too few args in the spawned command */
Packit 0848f5
	    errs++;
Packit 0848f5
	    cout << "Too few arguments to spawned command\n";
Packit 0848f5
	}
Packit 0848f5
	/* Send the errs back to the master process */
Packit 0848f5
	intercomm.Ssend( &errs, 1, MPI::INT, 0, 1 );
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* It isn't necessary to free the intercomm, but it should not hurt */
Packit 0848f5
    intercomm.Free();
Packit 0848f5
Packit 0848f5
    /* Note that the MTest_Finalize get errs only over COMM_WORLD */
Packit 0848f5
    if (parentcomm == MPI::COMM_NULL) {
Packit 0848f5
	MTest_Finalize( errs );
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI::Finalize();
Packit 0848f5
    return 0;
Packit 0848f5
}