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>
10#include <boost/lexical_cast.hpp>
34fmtdur(
typename clock_type::duration
const& d)
39 return boost::lexical_cast<std::string>(ms.count()) +
"ms";
72 [](
run_time const& t1, clock_type::duration
const& t2) { return t1.second > t2; });
74 if (iter !=
top.end())
84 top.resize(
top.size() - 1);
104 boost::container::static_vector<run_time, 2 * kMaxTop> topResult;
105 topResult.resize(
top.size() + r.
top.size());
107 return t1.second > t2.second;
110 if (topResult.size() >
kMaxTop)
124 s <<
"Longest suite times:\n";
125 for (
auto const& [name, dur] :
top)
136template <
bool IsParent>
143template <
bool IsParent>
150template <
bool IsParent>
154 return anyFailedFlag;
157template <
bool IsParent>
161 anyFailedFlag = anyFailedFlag || v;
164template <
bool IsParent>
169 return results.total;
172template <
bool IsParent>
177 return results.suites;
180template <
bool IsParent>
187template <
bool IsParent>
194template <
bool IsParent>
202template <
bool IsParent>
211template <
bool IsParent>
219 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
223 sharedMem_ = boost::interprocess::shared_memory_object{
226 boost::interprocess::create_only_t,
227 boost::interprocess::open_only_t>{},
229 boost::interprocess::read_write};
235 boost::interprocess::create_only,
246 region_ = boost::interprocess::mapped_region{
sharedMem_, boost::interprocess::read_write};
260 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
267template <
bool IsParent>
273 boost::interprocess::shared_memory_object::remove(
kSharedMemName);
278template <
bool IsParent>
282 return inner_->checkoutTestIndex();
285template <
bool IsParent>
289 return inner_->checkoutJobIndex();
292template <
bool IsParent>
296 return inner_->anyFailed();
299template <
bool IsParent>
303 return inner_->anyFailed(v);
306template <
bool IsParent>
313template <
bool IsParent>
317 inner_->incKeepAliveCount();
320template <
bool IsParent>
324 return inner_->getKeepAliveCount();
327template <
bool IsParent>
335template <
bool IsParent>
345template <
bool IsParent>
352template <
bool IsParent>
359template <
bool IsParent>
364 results.
failed += failures;
395 unsigned int priority = 0;
399 assert(recvdSize == 1);
408 case MessageType::Log:
412 case MessageType::TestStart:
415 case MessageType::TestEnd:
425 std::cerr <<
"Error: " << e.
what() <<
" reading unit test message queue.\n";
430 std::cerr <<
"Unknown error reading unit test message queue.\n";
450 os_ <<
"\nSuite: " << s <<
" failed to complete. The child process may have crashed.\n";
494 if (curCount == lastCount)
499 if (curCount == lastCount)
503 <<
": Assuming parent died, exiting.\n";
507 lastCount = curCount;
601 s <<
"#" <<
caseResults_.total <<
" failed" << (reason.
empty() ?
"" :
": ") << reason <<
'\n';
621template class MultiRunnerBase<true>;
622template 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
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)