I would like to unit-test with Boost.Test a parallel program that uses Boost.MPI. The official documentation of these libraries don't provide instructions on how to do this (or I could not find them). The problem is that MPI code needs initialisation and finalisation done only once which Boost.MPI encapsulates in the environment (and to some extent in the communicator) objects, RAII style. So a Boost.MPI program would normally look like this:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
int main(int argc, char *argv[]) {
boost::mpi::environment env(argc, argv);
boost::mpi::communicator world{};
// ... parallel code here ...
}
However, Boost.Test supplies its own main() function behind the scenes. This I can override by defining #define BOOST_TEST_NO_MAIN and then writing the main() myself, along the lines sketched above.
But then the problems begin. How to tell Boost.Test to run the test cases under MPI? Should they be defined as BOOST_AUTO_TEST_CASE(...) macros as usual or is there another way? And how can one "pass" the communicator object (world) to the test cases? Should it be set up in a global fixture? If yes, then how do global fixtures work together with a user-supplied main?
I have experimented a lot, Googled even more, and found nothing usable. Is there anyone out there who knows how to use these two Boost libraries together? If yes, then a working example would be much appreciated. Thanks.
EDIT SebastianH-s suggestion quickly slapped together:
#define BOOST_TEST_MODULE mpitest
#define BOOST_TEST_NO_MAIN
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
namespace bmpi = boost::mpi;
// Fixture
struct Fix {
Fix(): env{}, world{} {}
bmpi::environment env;
bmpi::communicator world;
};
BOOST_FIXTURE_TEST_CASE(check_mpi, Fix) {
if (world.rank() == 0) {
std::cout << "MPI thread level: " <<
bmpi::environment::thread_level() << std::endl;
}
std::cout << "I am process " << world.rank() << " of " << world.size()
<< "." << std::endl;
}
int main(int argc, char *argv[]) {
// This runs the test cases.
int retval = boost::unit_test::unit_test_main([](){ return true; }, argc, argv );
}
Compiles with g++ 9.3 and Boost 1.71 under Ubuntu. But when I run it:
Running 1 test case...
*** The MPI_Comm_set_errhandler() function was called before MPI_INIT was invoked.
*** This is disallowed by the MPI standard.
*** Your MPI job will now abort.
See, that's the problem: MPI is not correctly initialised.