GEOS
GEOS copied to clipboard
Suggestion for better GTEST output with MPI.
I figured out a way to greatly reduce the extra test output when running gtest with MPI. All the common stuff like
[ RUN ] BoundaryID.info
[ OK ] BoundaryID.info (0 ms)
that is normally printed by every single rank is now only printed by rank 0. Furthermore every EXPECT/ASSERT message includes the rank the error occurred on. If anyone finds this useful go ahead and steal it, the MPI calls will need to be renamed but I think that's it.
/**
*
*/
class MPITestPrinter : public ::testing::TestEventListener
{
public:
MPITestPrinter( ::testing::TestEventListener * defaultListener ):
_defaultListener( defaultListener )
{}
private:
void OnTestProgramStart( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnTestProgramStart( unitTest ); }
void OnTestIterationStart( ::testing::UnitTest const & unitTest, int const iteration ) override
{ if( _rank == 0 ) _defaultListener->OnTestIterationStart( unitTest, iteration ); }
void OnEnvironmentsSetUpStart( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnEnvironmentsSetUpStart( unitTest ); }
void OnEnvironmentsSetUpEnd( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnEnvironmentsSetUpEnd( unitTest ); }
void OnTestStart( ::testing::TestInfo const & testInfo ) override
{
mpi::barrier( MPI_COMM_WORLD );
if( _rank == 0 ) _defaultListener->OnTestStart( testInfo );
}
void OnTestPartResult( ::testing::TestPartResult const & testPartialResult ) override
{
std::cout << "Rank " << _rank << " ";
_defaultListener->OnTestPartResult( testPartialResult );
}
void OnTestEnd( ::testing::TestInfo const & testInfo ) override
{
int const failed = testInfo.result()->Failed();
int const numFailed = mpi::sum( failed, MPI_COMM_WORLD );
if( _rank == 0 )
{
if( numFailed > 0 && !failed )
{
std::string const msg = std::to_string( numFailed ) + " ranks failed this test.";
GTEST_NONFATAL_FAILURE_( msg.data() );
}
_defaultListener->OnTestEnd( testInfo );
}
}
void OnEnvironmentsTearDownStart( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnEnvironmentsTearDownStart( unitTest ); }
void OnEnvironmentsTearDownEnd( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnEnvironmentsTearDownEnd( unitTest ); }
void OnTestIterationEnd( ::testing::UnitTest const & unitTest, int const iteration ) override
{ if( _rank == 0 ) _defaultListener->OnTestIterationEnd( unitTest, iteration ); }
virtual void OnTestProgramEnd( ::testing::UnitTest const & unitTest ) override
{ if( _rank == 0 ) _defaultListener->OnTestProgramEnd( unitTest ); }
std::unique_ptr< ::testing::TestEventListener > _defaultListener;
int const _rank = mpi::commRank( MPI_COMM_WORLD );
};
/**
*
*/
void addMPITestPrinter()
{
::testing::TestEventListeners & listeners = ::testing::UnitTest::GetInstance()->listeners();
listeners.Append( new MPITestPrinter( listeners.Release( listeners.default_result_printer() ) ) );
}
To use call addMPITestPrinter inbetween InitGoogleTest and RUN_ALL_TESTS.
* According to the GTEST docs what I'm doing isn't allowed since it violates point 2 (http://google.github.io/googletest/advanced.html#generating-failures-in-listeners), but it would be simple to make it compliant by adding another listener.