mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Run unit tests in parallel
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/digest.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
@@ -39,21 +40,30 @@
|
||||
#include <ripple/beast/core/CurrentThreadName.h>
|
||||
#include <ripple/beast/core/Time.h>
|
||||
#include <ripple/beast/utility/Debug.h>
|
||||
|
||||
#include <beast/unit_test/dstream.hpp>
|
||||
#include <beast/unit_test/global_suites.hpp>
|
||||
#include <beast/unit_test/match.hpp>
|
||||
#include <beast/unit_test/reporter.hpp>
|
||||
#include <test/quiet_reporter.h>
|
||||
#include <test/unit_test/multi_runner.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
|
||||
#include <sys/resource.h>
|
||||
#if BOOST_VERSION >= 106400
|
||||
#define HAS_BOOST_PROCESS 1
|
||||
#endif
|
||||
|
||||
#if HAS_BOOST_PROCESS
|
||||
#include <boost/process.hpp>
|
||||
#endif
|
||||
|
||||
namespace po = boost::program_options;
|
||||
@@ -172,23 +182,70 @@ static int runUnitTests(
|
||||
std::string const& pattern,
|
||||
std::string const& argument,
|
||||
bool quiet,
|
||||
bool log)
|
||||
bool log,
|
||||
bool child,
|
||||
std::size_t num_jobs,
|
||||
int argc,
|
||||
char** argv)
|
||||
{
|
||||
using namespace beast::unit_test;
|
||||
using namespace ripple::test;
|
||||
beast::unit_test::dstream dout{std::cout};
|
||||
|
||||
std::unique_ptr<runner> r;
|
||||
if(quiet)
|
||||
r = std::make_unique<quiet_reporter>(dout, log);
|
||||
#if HAS_BOOST_PROCESS
|
||||
if (!child && num_jobs == 1)
|
||||
#endif
|
||||
{
|
||||
multi_runner_parent parent_runner;
|
||||
|
||||
multi_runner_child child_runner{num_jobs, quiet, log};
|
||||
auto const any_failed = child_runner.run_multi(match_auto(pattern));
|
||||
|
||||
if (any_failed)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#if HAS_BOOST_PROCESS
|
||||
if (!child)
|
||||
{
|
||||
multi_runner_parent parent_runner;
|
||||
std::vector<boost::process::child> children;
|
||||
|
||||
std::string const exe_name = argv[0];
|
||||
std::vector<std::string> args;
|
||||
{
|
||||
args.reserve(argc);
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.emplace_back(argv[i]);
|
||||
args.emplace_back("--unittest-child");
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < num_jobs; ++i)
|
||||
children.emplace_back(
|
||||
boost::process::exe = exe_name, boost::process::args = args);
|
||||
|
||||
int bad_child_exits = 0;
|
||||
for(auto& c : children)
|
||||
{
|
||||
c.wait();
|
||||
if (c.exit_code())
|
||||
++bad_child_exits;
|
||||
}
|
||||
|
||||
if (parent_runner.any_failed() || bad_child_exits)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
r = std::make_unique<reporter>(dout);
|
||||
r->arg(argument);
|
||||
bool const anyFailed = r->run_each_if(
|
||||
global_suites(), match_auto(pattern));
|
||||
if(anyFailed)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
{
|
||||
// child
|
||||
multi_runner_child runner{num_jobs, quiet, log};
|
||||
auto const anyFailed = runner.run_multi(match_auto(pattern));
|
||||
|
||||
if (anyFailed)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -227,6 +284,10 @@ int run (int argc, char** argv)
|
||||
("unittest,u", po::value <std::string> ()->implicit_value (""), "Perform unit tests.")
|
||||
("unittest-arg", po::value <std::string> ()->implicit_value (""), "Supplies argument to unit tests.")
|
||||
("unittest-log", po::value <std::string> ()->implicit_value (""), "Force unit test log output, even in quiet mode.")
|
||||
#if HAS_BOOST_PROCESS
|
||||
("unittest-jobs", po::value <std::size_t> (), "Number of unittest jobs to run.")
|
||||
("unittest-child", "For internal use only. Run the process as a unit test child process.")
|
||||
#endif
|
||||
("parameters", po::value< vector<string> > (), "Specify comma separated parameters.")
|
||||
("quiet,q", "Reduce diagnotics.")
|
||||
("quorum", po::value <std::size_t> (), "Override the minimum validation quorum.")
|
||||
@@ -288,10 +349,35 @@ int run (int argc, char** argv)
|
||||
|
||||
if (vm.count("unittest-arg"))
|
||||
argument = vm["unittest-arg"].as<std::string>();
|
||||
|
||||
std::size_t numJobs = 1;
|
||||
bool unittestChild = false;
|
||||
#if HAS_BOOST_PROCESS
|
||||
if (vm.count("unittest-jobs"))
|
||||
numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
|
||||
unittestChild = bool (vm.count("unittest-child"));
|
||||
#endif
|
||||
|
||||
return runUnitTests(
|
||||
vm["unittest"].as<std::string>(), argument,
|
||||
bool (vm.count ("quiet")),
|
||||
bool (vm.count ("unittest-log")));
|
||||
bool (vm.count ("unittest-log")),
|
||||
unittestChild,
|
||||
numJobs,
|
||||
argc,
|
||||
argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if HAS_BOOST_PROCESS
|
||||
if (vm.count("unittest-jobs"))
|
||||
{
|
||||
// unittest jobs only makes sense with `unittest`
|
||||
std::cerr << "rippled: '--unittest-jobs' specified without '--unittest'.\n";
|
||||
std::cerr << "To run the unit tests the '--unittest' option must be present.\n";
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
auto config = std::make_unique<Config>();
|
||||
|
||||
Reference in New Issue
Block a user