#include #include #include #include #include "common/UnitTest.h" #include "common/Utilities.h" #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) // Windows // Sleep is defined in milliseconds #else // Linux // usleep is defined in microseconds, create a Sleep command #define Sleep(x) usleep(x*1000) #endif /******************************************************************** * Empty Constructor * ********************************************************************/ UnitTest::UnitTest() { #ifdef USE_MPI comm = MPI_COMM_WORLD; #endif } /******************************************************************** * Print a global report * * Note: only rank 0 will print, all messages will be aggregated * ********************************************************************/ void UnitTest::report(const int level0) { int size = getSize(); int rank = getRank(); // Broadcast the print level from rank 0 int level = level0; #ifdef USE_MPI if ( getSize() > 1 ) MPI_Bcast( &level, 1, MPI_INT, 0, comm ); #endif if ( level<0 || level > 2 ) ERROR("Invalid print level"); // Perform a global all gather to get the number of failures per processor std::vector N_pass(size,0); std::vector N_fail(size,0); std::vector N_expected_fail(size,0); int local_pass_size = (int) pass_messages.size(); int local_fail_size = (int) fail_messages.size(); int local_expected_fail_size = (int) expected_fail_messages.size(); if ( getSize() > 1 ) { #ifdef USE_MPI MPI_Allgather( &local_pass_size, 1, MPI_INT, &N_pass[0], 1, MPI_INT, comm); MPI_Allgather( &local_fail_size, 1, MPI_INT, &N_fail[0], 1, MPI_INT, comm); MPI_Allgather( &local_expected_fail_size, 1, MPI_INT, &N_expected_fail[0], 1, MPI_INT, comm); #endif } else { N_pass[0] = local_pass_size; N_fail[0] = local_fail_size; N_expected_fail[0] = local_expected_fail_size; } int N_pass_tot = 0; int N_expected_fail_tot = 0; for (int i=0; i > pass_messages_rank(size); std::vector< std::vector > fail_messages_rank(size); std::vector< std::vector > expected_fail_rank(size); // Get the pass messages if ( ( level==1 && N_pass_tot<=20 ) || level==2 ) { if ( rank==0 ) { // Rank 0 should receive all messages for (int i=0; i0 ) pass_messages_rank[i] = unpack_message_stream(i,1); } } else if ( pass_messages.size() ) { // All other ranks send their message (use non-blocking communication) pack_message_stream(pass_messages,0,1); } } // Get the fail messages if ( level==1 || level==2 ) { if ( rank==0 ) { // Rank 0 should receive all messages for (int i=0; i0 ) fail_messages_rank[i] = unpack_message_stream(i,2); } } else if ( !fail_messages.empty() ){ // All other ranks send their message (use non-blocking communication) pack_message_stream(fail_messages,0,2); } } // Get the expected_fail messages if ( ( level==1 && N_expected_fail_tot<=50 ) || level==2 ) { if ( rank==0 ) { // Rank 0 should receive all messages for (int i=0; i0 ) expected_fail_rank[i] = unpack_message_stream(i,3); } } else if ( !expected_fail_messages.empty() ){ // All other ranks send their message (use non-blocking communication) pack_message_stream(expected_fail_messages,0,3); } } // Print the results of all messages (only rank 0 will print) if ( rank==0 ) { std::cout << std::endl; // Print the passed tests std::cout << "Tests passed" << std::endl; if ( level==0 || ( level==1 && N_pass_tot>20 ) ) { // We want to print a summary if ( size>8 ) { // Print 1 summary for all processors std::cout << " " << N_pass_tot << " tests passed (use report level 2 for more detail)" << std::endl; } else { // Print a summary for each processor for (int i=0; i 0 ) { std::cout << " Proccessor " << i << ":" << std::endl; for (unsigned int j=0; j8 ) { // Print 1 summary for all processors std::cout << " " << N_pass_tot << " tests failed (use report level 2 for more detail)" << std::endl; } else { // Print a summary for each processor for (int i=0; i 0 ) { std::cout << " Processor " << i << ":" << std::endl; for (unsigned int j=0; j50 ) ) { // We want to print a summary if ( size>8 ) { // Print 1 summary for all processors std::cout << " " << N_expected_fail_tot << " tests expected failed (use report level 2 for more detail)" << std::endl; } else { // Print a summary for each processor for (int i=0; i 0 ) { std::cout << " Processor " << i << ":" << std::endl; for (unsigned int j=0; j 1 ) MPI_Barrier(comm); #endif } /******************************************************************** * Pack and send the given messages * ********************************************************************/ void UnitTest::pack_message_stream(const std::vector& messages, const int rank, const int tag) { #ifdef USE_MPI // Get the size of the messages int N_messages = (int) messages.size(); int *msg_size = new int[N_messages]; int msg_size_tot = 0; for (int i=0; i UnitTest::unpack_message_stream(const int rank, const int tag) { #ifdef USE_MPI // Probe the message to get the message size MPI_Status status; MPI_Probe(rank,tag,comm,&status); int size_data=-1; MPI_Get_count(&status,MPI_BYTE,&size_data); ASSERT(size_data>=0); // Allocate memory to receive the data char *data = new char[size_data]; // receive the data (using a non-blocking receive) MPI_Request request; MPI_Irecv( data, size_data, MPI_CHAR, rank, tag, comm, &request ); // Wait for the communication to be received MPI_Wait( &request, &status ); // Unpack the message stream int *tmp = (int*) data; int N_messages = tmp[0]; int *msg_size = &tmp[1]; std::vector messages(N_messages); int k = (N_messages+1)*sizeof(int); for (int i=0; i(); #endif } /******************************************************************** * Other functions * ********************************************************************/ int UnitTest::getRank() { int rank = 0; #ifdef USE_MPI int flag=0; MPI_Initialized(&flag); if ( flag ) MPI_Comm_rank( comm, &rank ); #endif return rank; } int UnitTest::getSize() { int size = 1; #ifdef USE_MPI int flag=0; MPI_Initialized(&flag); if ( flag ) MPI_Comm_size( comm, &size ); #endif return size; } size_t UnitTest::NumPassGlobal() { size_t num = pass_messages.size(); #ifdef USE_MPI if ( getSize() > 1 ) { int send = static_cast(num); int sum = 0; MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); num = static_cast(sum); } #endif return num; } size_t UnitTest::NumFailGlobal() { size_t num = fail_messages.size(); #ifdef USE_MPI if ( getSize() > 1 ) { int send = static_cast(num); int sum = 0; MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); num = static_cast(sum); } #endif return num; } size_t UnitTest::NumExpectedFailGlobal() { size_t num = expected_fail_messages.size(); #ifdef USE_MPI if ( getSize() > 1 ) { int send = static_cast(num); int sum = 0; MPI_Allreduce( &send, &sum, 1, MPI_INT, MPI_SUM, comm ); num = static_cast(sum); } #endif return num; }