1#include <test/unit_test/multi_runner.h>
3#include <xrpl/beast/unit_test/amount.h>
4#include <xrpl/beast/unit_test/suite_info.h>
6#include <boost/container/static_vector.hpp>
7#include <boost/interprocess/creation_tags.hpp>
8#include <boost/interprocess/detail/os_file_functions.hpp>
9#include <boost/interprocess/shared_memory_object.hpp>
33fmtdur(
typename clock_type::duration
const& d)
71 [](
run_time const& t1, clock_type::duration
const& t2) { return t1.second > t2; });
73 if (iter !=
top.end())
83 top.resize(
top.size() - 1);
103 boost::container::static_vector<run_time, 2 * kMaxTop> topResult;
104 topResult.resize(
top.size() + r.
top.size());
106 return t1.second > t2.second;
109 if (topResult.size() >
kMaxTop)
123 s <<
"Longest suite times:\n";
124 for (
auto const& [name, dur] :
top)
135template <
bool IsParent>
142template <
bool IsParent>
149template <
bool IsParent>
156template <
bool IsParent>
160 anyFailedFlag = anyFailedFlag || v;
163template <
bool IsParent>
168 return results.total;
171template <
bool IsParent>
176 return results.suites;
179template <
bool IsParent>
186template <
bool IsParent>
193template <
bool IsParent>
201template <
bool IsParent>
210template <
bool IsParent>
218 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
222 sharedMem_ = boost::interprocess::shared_memory_object{
225 boost::interprocess::create_only_t,
226 boost::interprocess::open_only_t>{},
228 boost::interprocess::read_write};
234 boost::interprocess::create_only,
245 region_ = boost::interprocess::mapped_region{
sharedMem_, boost::interprocess::read_write};
259 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
266template <
bool IsParent>
272 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
277template <
bool IsParent>
281 return inner_->checkoutTestIndex();
284template <
bool IsParent>
288 return inner_->checkoutJobIndex();
291template <
bool IsParent>
295 return inner_->anyFailed();
298template <
bool IsParent>
302 return inner_->anyFailed(v);
305template <
bool IsParent>
312template <
bool IsParent>
316 inner_->incKeepAliveCount();
319template <
bool IsParent>
323 return inner_->getKeepAliveCount();
326template <
bool IsParent>
334template <
bool IsParent>
344template <
bool IsParent>
351template <
bool IsParent>
358template <
bool IsParent>
363 results.
failed += failures;
394 unsigned int priority = 0;
398 assert(recvdSize == 1);
407 case MessageType::Log:
411 case MessageType::TestStart:
414 case MessageType::TestEnd:
424 std::cerr <<
"Error: " << e.
what() <<
" reading unit test message queue.\n";
429 std::cerr <<
"Unknown error reading unit test message queue.\n";
449 os_ <<
"\nSuite: " << s <<
" failed to complete. The child process may have crashed.\n";
493 if (curCount == lastCount)
498 if (curCount == lastCount)
502 <<
": Assuming parent died, exiting.\n";
506 lastCount = curCount;
600 s <<
"#" <<
caseResults_.total <<
" failed" << (reason.
empty() ?
"" :
": ") << reason <<
'\n';
620template class MultiRunnerBase<true>;
621template class MultiRunnerBase<false>;
Utility for producing nicely composed output of amounts with units.
Associates a unit test type with metadata.
std::string fullName() const
Return the canonical suite name as a string.
std::unique_ptr< boost::interprocess::message_queue > messageQueue_
std::size_t checkoutTestIndex()
static constexpr char const * kSharedMemName
void addFailures(std::size_t failures)
void add(Results const &r)
boost::interprocess::shared_memory_object sharedMem_
static constexpr char const * kMessageQueueName
std::size_t checkoutJobIndex()
std::size_t suites() const
std::size_t getKeepAliveCount()
boost::interprocess::mapped_region region_
void messageQueueSend(MessageType mt, std::string const &s)
std::size_t tests() const
void onSuiteEnd() override
Called when a suite ends.
void onFail(std::string const &reason) override
Called for each failing condition.
~MultiRunnerChild() override
void onPass() override
Called for each passing condition.
void onSuiteBegin(beast::unit_test::SuiteInfo const &info) override
Called when a new suite starts.
void onLog(std::string const &s) override
Called when a test logs output.
detail::SuiteResults suiteResults_
std::thread keepAliveThread_
void addFailures(std::size_t failures)
detail::CaseResults caseResults_
void onCaseEnd() override
Called when a new case ends.
std::atomic< bool > continueKeepAlive_
std::size_t suites() const
void onCaseBegin(std::string const &name) override
Called when a new case starts.
MultiRunnerChild(MultiRunnerChild const &)=delete
std::size_t tests() const
void addFailures(std::size_t failures)
std::set< std::string > runningSuites_
std::atomic< bool > continueMessageQueue_
MultiRunnerParent(MultiRunnerParent const &)=delete
std::size_t suites() const
std::thread messageQueueThread_
std::size_t tests() const
T duration_cast(T... args)
std::string fmtdur(std::chrono::duration< Period, Rep > const &d)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T setprecision(T... args)
std::size_t getKeepAliveCount()
std::size_t checkoutJobIndex()
std::atomic< std::size_t > keepAlive
boost::interprocess::interprocess_mutex m
std::atomic< std::size_t > jobIndex
std::atomic< bool > anyFailedFlag
void add(Results const &r)
std::size_t suites() const
std::size_t checkoutTestIndex()
std::atomic< std::size_t > testIndex
std::size_t tests() const
static constexpr auto kMaxTop
std::pair< static_string, clock_type::duration > run_time
boost::container::static_vector< run_time, kMaxTop > top
boost::beast::static_string< 256 > static_string
clock_type::time_point start
void merge(Results const &r)
void add(SuiteResults const &r)
clock_type::time_point start
void add(CaseResults const &r)