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 ClockType::duration
const& d)
68 top.begin(),
top.end(), elapsed, [](
RunTime const& t1, ClockType::duration
const& t2) {
69 return t1.second > t2;
72 if (iter !=
top.end())
82 top.resize(
top.size() - 1);
102 boost::container::static_vector<RunTime, 2 * kMaxTop> topResult;
103 topResult.resize(
top.size() + r.
top.size());
105 return t1.second > t2.second;
122 s <<
"Longest suite times:\n";
123 for (
auto const& [name, dur] :
top)
134template <
bool IsParent>
141template <
bool IsParent>
148template <
bool IsParent>
155template <
bool IsParent>
159 anyFailedFlag = anyFailedFlag || v;
162template <
bool IsParent>
167 return results.total;
170template <
bool IsParent>
175 return results.suites;
178template <
bool IsParent>
185template <
bool IsParent>
192template <
bool IsParent>
200template <
bool IsParent>
209template <
bool IsParent>
217 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
221 sharedMem_ = boost::interprocess::shared_memory_object{
224 boost::interprocess::create_only_t,
225 boost::interprocess::open_only_t>{},
227 boost::interprocess::read_write};
233 boost::interprocess::create_only,
244 region_ = boost::interprocess::mapped_region{
sharedMem_, boost::interprocess::read_write};
258 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
265template <
bool IsParent>
271 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
276template <
bool IsParent>
280 return inner_->checkoutTestIndex();
283template <
bool IsParent>
287 return inner_->checkoutJobIndex();
290template <
bool IsParent>
294 return inner_->anyFailed();
297template <
bool IsParent>
301 return inner_->anyFailed(v);
304template <
bool IsParent>
311template <
bool IsParent>
315 inner_->incKeepAliveCount();
318template <
bool IsParent>
322 return inner_->getKeepAliveCount();
325template <
bool IsParent>
333template <
bool IsParent>
343template <
bool IsParent>
350template <
bool IsParent>
357template <
bool IsParent>
362 results.
failed += failures;
393 unsigned int priority = 0;
397 assert(recvdSize == 1);
406 case MessageType::Log:
410 case MessageType::TestStart:
413 case MessageType::TestEnd:
423 std::cerr <<
"Error: " << e.
what() <<
" reading unit test message queue.\n";
428 std::cerr <<
"Unknown error reading unit test message queue.\n";
448 os_ <<
"\nSuite: " << s <<
" failed to complete. The child process may have crashed.\n";
492 if (curCount == lastCount)
497 if (curCount == lastCount)
501 <<
": Assuming parent died, exiting.\n";
505 lastCount = curCount;
599 s <<
"#" <<
caseResults_.total <<
" failed" << (reason.
empty() ?
"" :
": ") << reason <<
'\n';
619template class MultiRunnerBase<true>;
620template 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
boost::container::static_vector< RunTime, kMaxTop > top
std::pair< StaticString, ClockType::duration > RunTime
void merge(Results const &r)
boost::beast::static_string< 256 > StaticString
void add(SuiteResults const &r)
ClockType::time_point start
ClockType::time_point start
void add(CaseResults const &r)