GEOS-DEV / GEOS-DEV/GEOS

Suggestion for better GTEST output with MPI.

Open
#1,727 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: testing
Dominant language
C++
Stars
287
Forks
109
Avg merge
4d 41m
Merged PRs (30d)
5

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the GoogleTest listener entry points shown in MPITestPrinter and addMPITestPrinter, then trace the InitGoogleTest-to-RUN_ALL_TESTS setup. Done means common test output appears only on rank 0, assertion messages identify their MPI rank, and the listener behavior follows the stated GoogleTest constraint.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.