mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 11:15:56 +00:00
Support stream composition of testcase names
This commit is contained in:
@@ -362,10 +362,14 @@ public:
|
||||
{
|
||||
typedef UnsignedInteger <Bytes> UInt;
|
||||
|
||||
#if 0
|
||||
std::stringstream ss;
|
||||
ss <<
|
||||
c.name() << " <" << Bytes << ">";
|
||||
testcase (ss.str());
|
||||
#else
|
||||
testcase << c.name() << " <" << Bytes << ">";
|
||||
#endif
|
||||
|
||||
Random r;
|
||||
for (int i = 0; i < 50; ++i)
|
||||
|
||||
@@ -97,7 +97,7 @@ bool PeerTest::Results::report (unit_test::suite& suite,
|
||||
bool beginTestCase) const
|
||||
{
|
||||
if (beginTestCase)
|
||||
suite.testcase (name.toStdString());
|
||||
suite.testcase << name.toStdString();
|
||||
bool success = true;
|
||||
if (! client.report (suite))
|
||||
success = false;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace unit_test {
|
||||
|
||||
/** Write test results to the specified output stream. */
|
||||
/** @{ */
|
||||
inline
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, abstract_ostream& stream)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ print (results const& r, abstract_ostream& stream)
|
||||
;
|
||||
}
|
||||
|
||||
inline
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, std::ostream& stream = std::cout)
|
||||
{
|
||||
|
||||
@@ -35,15 +35,13 @@ private:
|
||||
case_results m_case;
|
||||
|
||||
public:
|
||||
recorder() = default;
|
||||
recorder (recorder const&) = default;
|
||||
recorder& operator= (recorder const&) = default;
|
||||
|
||||
recorder()
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns a report with the results of all completed suites. */
|
||||
results const& report() const
|
||||
results const&
|
||||
report() const
|
||||
{
|
||||
return m_results;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ public:
|
||||
;
|
||||
}
|
||||
|
||||
explicit reporter (abstract_ostream& stream)
|
||||
explicit
|
||||
reporter (abstract_ostream& stream)
|
||||
: m_stream (stream)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -41,59 +41,43 @@ private:
|
||||
class stream_t : public abstract_ostream
|
||||
{
|
||||
private:
|
||||
runner& m_owner;
|
||||
runner& owner_;
|
||||
|
||||
public:
|
||||
stream_t() = delete;
|
||||
stream_t& operator= (stream_t const&) = delete;
|
||||
|
||||
stream_t (runner& owner)
|
||||
: m_owner (owner)
|
||||
: owner_ (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
write (string_type const& s)
|
||||
{
|
||||
m_owner.log (s);
|
||||
owner_.log (s);
|
||||
}
|
||||
};
|
||||
|
||||
stream_t m_stream;
|
||||
bool m_default;
|
||||
bool m_failed;
|
||||
bool m_cond;
|
||||
stream_t stream_;
|
||||
bool default_;
|
||||
bool failed_;
|
||||
bool cond_;
|
||||
|
||||
public:
|
||||
virtual ~runner() = default;
|
||||
runner (runner const&) = default;
|
||||
runner& operator= (runner const&) = default;
|
||||
|
||||
runner()
|
||||
: m_stream (*this)
|
||||
, m_default (false)
|
||||
, m_failed (false)
|
||||
, m_cond (false)
|
||||
{
|
||||
}
|
||||
template <class = void>
|
||||
runner();
|
||||
|
||||
/** Run the specified suite.
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class = void>
|
||||
bool
|
||||
run (suite_info const& s)
|
||||
{
|
||||
// Enable 'default' testcase
|
||||
m_default = true;
|
||||
m_failed = false;
|
||||
on_suite_begin (s);
|
||||
s.run (*this);
|
||||
// Forgot to call pass or fail.
|
||||
assert (m_cond);
|
||||
on_case_end();
|
||||
on_suite_end();
|
||||
return m_failed;
|
||||
}
|
||||
run (suite_info const& s);
|
||||
|
||||
/** Run a sequence of suites.
|
||||
The expression
|
||||
@@ -103,13 +87,7 @@ public:
|
||||
*/
|
||||
template <class FwdIter>
|
||||
bool
|
||||
run (FwdIter first, FwdIter last)
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
failed = run (*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
run (FwdIter first, FwdIter last);
|
||||
|
||||
/** Conditionally run a sequence of suites.
|
||||
pred will be called as:
|
||||
@@ -120,27 +98,14 @@ public:
|
||||
*/
|
||||
template <class FwdIter, class Pred>
|
||||
bool
|
||||
run_if (FwdIter first, FwdIter last, Pred pred = Pred())
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
if (pred (*first))
|
||||
failed = run (*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
run_if (FwdIter first, FwdIter last, Pred pred = Pred{});
|
||||
|
||||
/** Run all suites in a container.
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class SequenceContainer>
|
||||
bool
|
||||
run_each (SequenceContainer const& c)
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
failed = run (s) || failed;
|
||||
return failed;
|
||||
}
|
||||
run_each (SequenceContainer const& c);
|
||||
|
||||
/** Conditionally run suites in a container.
|
||||
pred will be called as:
|
||||
@@ -151,14 +116,7 @@ public:
|
||||
*/
|
||||
template <class SequenceContainer, class Pred>
|
||||
bool
|
||||
run_each_if (SequenceContainer const& c, Pred pred = Pred())
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
if (pred (s))
|
||||
failed = run (s) || failed;
|
||||
return failed;
|
||||
}
|
||||
run_each_if (SequenceContainer const& c, Pred pred = Pred{});
|
||||
|
||||
private:
|
||||
//
|
||||
@@ -220,52 +178,141 @@ private:
|
||||
abstract_ostream&
|
||||
stream()
|
||||
{
|
||||
return m_stream;
|
||||
return stream_;
|
||||
}
|
||||
|
||||
// Start a new testcase.
|
||||
template <class = void>
|
||||
void
|
||||
testcase (std::string const& name)
|
||||
{
|
||||
// Name may not be empty
|
||||
assert (m_default || ! name.empty());
|
||||
// Forgot to call pass or fail
|
||||
assert (m_default || m_cond);
|
||||
if (! m_default)
|
||||
on_case_end();
|
||||
m_default = false;
|
||||
m_cond = false;
|
||||
on_case_begin (name);
|
||||
}
|
||||
testcase (std::string const& name);
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
pass()
|
||||
{
|
||||
if (m_default)
|
||||
testcase ("");
|
||||
on_pass();
|
||||
m_cond = true;
|
||||
}
|
||||
pass();
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
fail (std::string const& reason)
|
||||
{
|
||||
if (m_default)
|
||||
testcase ("");
|
||||
on_fail (reason);
|
||||
m_failed = true;
|
||||
m_cond = true;
|
||||
}
|
||||
fail (std::string const& reason);
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
log (std::string const& s)
|
||||
{
|
||||
if (m_default)
|
||||
testcase ("");
|
||||
on_log (s);
|
||||
}
|
||||
log (std::string const& s);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
runner::runner()
|
||||
: stream_ (*this)
|
||||
, default_ (false)
|
||||
, failed_ (false)
|
||||
, cond_ (false)
|
||||
{
|
||||
}
|
||||
|
||||
template <class>
|
||||
bool
|
||||
runner::run (suite_info const& s)
|
||||
{
|
||||
// Enable 'default' testcase
|
||||
default_ = true;
|
||||
failed_ = false;
|
||||
on_suite_begin (s);
|
||||
s.run (*this);
|
||||
// Forgot to call pass or fail.
|
||||
assert (cond_);
|
||||
on_case_end();
|
||||
on_suite_end();
|
||||
return failed_;
|
||||
}
|
||||
|
||||
template <class FwdIter>
|
||||
bool
|
||||
runner::run (FwdIter first, FwdIter last)
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
failed = run (*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class FwdIter, class Pred>
|
||||
bool
|
||||
runner::run_if (FwdIter first, FwdIter last, Pred pred)
|
||||
{
|
||||
bool failed (false);
|
||||
for (;first != last; ++first)
|
||||
if (pred (*first))
|
||||
failed = run (*first) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class SequenceContainer>
|
||||
bool
|
||||
runner::run_each (SequenceContainer const& c)
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
failed = run (s) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class SequenceContainer, class Pred>
|
||||
bool
|
||||
runner::run_each_if (SequenceContainer const& c, Pred pred)
|
||||
{
|
||||
bool failed (false);
|
||||
for (auto const& s : c)
|
||||
if (pred (s))
|
||||
failed = run (s) || failed;
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
runner::testcase (std::string const& name)
|
||||
{
|
||||
// Name may not be empty
|
||||
assert (default_ || ! name.empty());
|
||||
// Forgot to call pass or fail
|
||||
assert (default_ || cond_);
|
||||
if (! default_)
|
||||
on_case_end();
|
||||
default_ = false;
|
||||
cond_ = false;
|
||||
on_case_begin (name);
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
runner::pass()
|
||||
{
|
||||
if (default_)
|
||||
testcase ("");
|
||||
on_pass();
|
||||
cond_ = true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
runner::fail (std::string const& reason)
|
||||
{
|
||||
if (default_)
|
||||
testcase ("");
|
||||
on_fail (reason);
|
||||
failed_ = true;
|
||||
cond_ = true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
runner::log (std::string const& s)
|
||||
{
|
||||
if (default_)
|
||||
testcase ("");
|
||||
on_log (s);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
@@ -36,53 +37,83 @@ namespace unit_test {
|
||||
*/
|
||||
class suite
|
||||
{
|
||||
private:
|
||||
// This exception is thrown internally to stop the current suite
|
||||
// in the event of a failure, if the option to stop is set.
|
||||
struct abort_exception : public std::exception
|
||||
public:
|
||||
enum abort_t
|
||||
{
|
||||
char const*
|
||||
what() const noexcept override
|
||||
{
|
||||
return "suite aborted on failed condition";
|
||||
}
|
||||
no_abort_on_fail,
|
||||
abort_on_fail
|
||||
};
|
||||
|
||||
private:
|
||||
bool abort_ = false;
|
||||
runner* runner_ = nullptr;
|
||||
|
||||
struct abort_exception;
|
||||
|
||||
// Memberspace
|
||||
class log_t
|
||||
{
|
||||
private:
|
||||
friend class suite;
|
||||
runner* m_runner;
|
||||
|
||||
runner*
|
||||
operator-> ()
|
||||
{
|
||||
return m_runner;
|
||||
}
|
||||
suite* suite_ = nullptr;
|
||||
|
||||
public:
|
||||
log_t ()
|
||||
: m_runner (nullptr)
|
||||
{
|
||||
}
|
||||
log_t () = default;
|
||||
|
||||
template <class T>
|
||||
abstract_ostream::scoped_stream_type
|
||||
operator<< (T const& t)
|
||||
{
|
||||
return m_runner->stream() << t;
|
||||
}
|
||||
operator<< (T const& t);
|
||||
|
||||
/** Returns the raw stream used for output. */
|
||||
abstract_ostream&
|
||||
stream()
|
||||
{
|
||||
return m_runner->stream();
|
||||
}
|
||||
stream();
|
||||
};
|
||||
|
||||
bool m_abort = false;
|
||||
class scoped_testcase;
|
||||
|
||||
// Memberspace
|
||||
class testcase_t
|
||||
{
|
||||
private:
|
||||
friend class suite;
|
||||
suite* suite_ = nullptr;
|
||||
std::stringstream ss_;
|
||||
|
||||
public:
|
||||
testcase_t() = default;
|
||||
|
||||
/** Open a new testcase.
|
||||
A testcase is a series of evaluated test conditions. A test suite
|
||||
may have multiple test cases. A test is associated with the last
|
||||
opened testcase. When the test first runs, a default unnamed
|
||||
case is opened. Tests with only one case may omit the call
|
||||
to testcase.
|
||||
@param abort If `true`, the suite will be stopped on first failure.
|
||||
*/
|
||||
void
|
||||
operator() (std::string const& name,
|
||||
abort_t abort = no_abort_on_fail);
|
||||
|
||||
/** Stream style composition of testcase names. */
|
||||
/** @{ */
|
||||
scoped_testcase
|
||||
operator() (abort_t abort);
|
||||
|
||||
template <class T>
|
||||
scoped_testcase
|
||||
operator<< (T const& t);
|
||||
/** @} */
|
||||
};
|
||||
|
||||
// Hacks to make this header-only
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
run (runner& r);
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
do_fail (std::string const& reason);
|
||||
|
||||
public:
|
||||
/** Type for scoped stream logging.
|
||||
@@ -113,6 +144,9 @@ public:
|
||||
/** Memberspace for logging. */
|
||||
log_t log;
|
||||
|
||||
/** Memberspace for declaring test cases. */
|
||||
testcase_t testcase;
|
||||
|
||||
/** Invokes the test using the specified runner.
|
||||
Data members are set up here instead of the constructor as a
|
||||
convenience to writing the derived class to avoid repetition of
|
||||
@@ -120,50 +154,7 @@ public:
|
||||
Normally this is called by the framework for you.
|
||||
*/
|
||||
void
|
||||
operator() (runner& r)
|
||||
{
|
||||
log.m_runner = &r;
|
||||
|
||||
try
|
||||
{
|
||||
run();
|
||||
}
|
||||
catch (abort_exception const&)
|
||||
{
|
||||
// ends the suite
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
fail (std::string ("unhandled exception: ") +
|
||||
std::string (e.what()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail ("unhandled exception");
|
||||
}
|
||||
}
|
||||
|
||||
enum abort_t
|
||||
{
|
||||
no_abort_on_fail,
|
||||
abort_on_fail
|
||||
};
|
||||
|
||||
/** Open a new testcase.
|
||||
A testcase is a series of evaluated test conditions. A test suite
|
||||
may have multiple test cases. A test is associated with the last
|
||||
opened testcase. When the test first runs, a default unnamed
|
||||
case is opened. Tests with only one case may omit the call
|
||||
to testcase.
|
||||
@param abort If `true`, the suite will be stopped on first failure.
|
||||
*/
|
||||
void
|
||||
testcase (std::string const& name,
|
||||
abort_t abort = no_abort_on_fail)
|
||||
{
|
||||
m_abort = abort == abort_on_fail;
|
||||
log->testcase (name);
|
||||
}
|
||||
operator() (runner& r);
|
||||
|
||||
/** Evaluate a test condition.
|
||||
The condition is passed as a template argument instead of `bool` so
|
||||
@@ -173,43 +164,24 @@ public:
|
||||
*/
|
||||
template <class Condition>
|
||||
bool
|
||||
expect (Condition shouldBeTrue, std::string const& reason = "")
|
||||
{
|
||||
if (shouldBeTrue)
|
||||
pass();
|
||||
else
|
||||
fail (reason);
|
||||
return shouldBeTrue;
|
||||
}
|
||||
expect (Condition shouldBeTrue, std::string const& reason = "");
|
||||
|
||||
// DEPRECATED
|
||||
// @return `true` if the test condition indicates success (a false value)
|
||||
template <class Condition>
|
||||
bool
|
||||
unexpected (Condition shouldBeFalse, std::string const& reason = "")
|
||||
{
|
||||
if (! shouldBeFalse)
|
||||
pass();
|
||||
else
|
||||
fail (reason);
|
||||
return ! shouldBeFalse;
|
||||
}
|
||||
unexpected (Condition shouldBeFalse, std::string const& reason = "");
|
||||
|
||||
/** Record a successful test condition. */
|
||||
void
|
||||
pass()
|
||||
{
|
||||
log->pass();
|
||||
runner_->pass();
|
||||
}
|
||||
|
||||
/** Record a failure. */
|
||||
void
|
||||
fail (std::string const& reason= "")
|
||||
{
|
||||
log->fail (reason);
|
||||
if (m_abort)
|
||||
throw abort_exception();
|
||||
}
|
||||
fail (std::string const& reason = "");
|
||||
|
||||
private:
|
||||
/** Runs the suite. */
|
||||
@@ -218,6 +190,206 @@ private:
|
||||
run() = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// This exception is thrown internally to stop the current suite
|
||||
// in the event of a failure, if the option to stop is set.
|
||||
struct suite::abort_exception : public std::exception
|
||||
{
|
||||
char const*
|
||||
what() const noexcept override;
|
||||
};
|
||||
|
||||
inline
|
||||
char const*
|
||||
suite::abort_exception::what() const noexcept
|
||||
{
|
||||
return "suite aborted on failed condition";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
abstract_ostream::scoped_stream_type
|
||||
suite::log_t::operator<< (T const& t)
|
||||
{
|
||||
return suite_->runner_->stream() << t;
|
||||
}
|
||||
|
||||
/** Returns the raw stream used for output. */
|
||||
inline
|
||||
abstract_ostream&
|
||||
suite::log_t::stream()
|
||||
{
|
||||
return suite_->runner_->stream();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Helper for streaming testcase names
|
||||
class suite::scoped_testcase
|
||||
{
|
||||
private:
|
||||
suite* suite_;
|
||||
std::stringstream* ss_;
|
||||
|
||||
public:
|
||||
~scoped_testcase();
|
||||
|
||||
scoped_testcase (suite* s, std::stringstream* ss);
|
||||
|
||||
template <class T>
|
||||
scoped_testcase (suite* s, std::stringstream* ss, T const& t);
|
||||
|
||||
scoped_testcase& operator= (scoped_testcase const&) = delete;
|
||||
|
||||
template <class T>
|
||||
scoped_testcase&
|
||||
operator<< (T const& t);
|
||||
};
|
||||
|
||||
inline
|
||||
suite::scoped_testcase::~scoped_testcase()
|
||||
{
|
||||
auto const& name (ss_->str());
|
||||
if (! name.empty())
|
||||
suite_->runner_->testcase (name);
|
||||
}
|
||||
|
||||
inline
|
||||
suite::scoped_testcase::scoped_testcase (suite* s, std::stringstream* ss)
|
||||
: suite_ (s)
|
||||
, ss_ (ss)
|
||||
{
|
||||
ss_->clear();
|
||||
ss_->str({});
|
||||
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
suite::scoped_testcase::scoped_testcase (suite* s, std::stringstream* ss, T const& t)
|
||||
: suite_ (s)
|
||||
, ss_ (ss)
|
||||
{
|
||||
ss_->clear();
|
||||
ss_->str({});
|
||||
*ss_ << t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
suite::scoped_testcase&
|
||||
suite::scoped_testcase::operator<< (T const& t)
|
||||
{
|
||||
*ss_ << t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
void
|
||||
suite::testcase_t::operator() (std::string const& name,
|
||||
abort_t abort)
|
||||
{
|
||||
suite_->abort_ = abort == abort_on_fail;
|
||||
suite_->runner_->testcase (name);
|
||||
}
|
||||
|
||||
inline
|
||||
suite::scoped_testcase
|
||||
suite::testcase_t::operator() (abort_t abort)
|
||||
{
|
||||
suite_->abort_ = abort == abort_on_fail;
|
||||
return { suite_, &ss_ };
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
suite::scoped_testcase
|
||||
suite::testcase_t::operator<< (T const& t)
|
||||
{
|
||||
return { suite_, &ss_, t };
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
void
|
||||
suite::run (runner& r)
|
||||
{
|
||||
runner_ = &r;
|
||||
log.suite_ = this;
|
||||
testcase.suite_ = this;
|
||||
|
||||
try
|
||||
{
|
||||
run();
|
||||
}
|
||||
catch (abort_exception const&)
|
||||
{
|
||||
// ends the suite
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
fail (std::string ("unhandled exception: ") +
|
||||
std::string (e.what()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail ("unhandled exception");
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
suite::operator() (runner& r)
|
||||
{
|
||||
run (r);
|
||||
}
|
||||
|
||||
template <class Condition>
|
||||
inline
|
||||
bool
|
||||
suite::expect (Condition shouldBeTrue, std::string const& reason)
|
||||
{
|
||||
if (shouldBeTrue)
|
||||
pass();
|
||||
else
|
||||
do_fail (reason);
|
||||
return shouldBeTrue;
|
||||
}
|
||||
|
||||
template <class Condition>
|
||||
inline
|
||||
bool
|
||||
suite::unexpected (Condition shouldBeFalse, std::string const& reason)
|
||||
{
|
||||
if (! shouldBeFalse)
|
||||
pass();
|
||||
else
|
||||
do_fail (reason);
|
||||
return ! shouldBeFalse;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
suite::do_fail (std::string const& reason)
|
||||
{
|
||||
runner_->fail (reason);
|
||||
if (abort_)
|
||||
throw abort_exception();
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
suite::fail (std::string const& reason)
|
||||
{
|
||||
do_fail (reason);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
|
||||
@@ -42,19 +42,9 @@ private:
|
||||
run_type m_run;
|
||||
|
||||
public:
|
||||
suite_info (
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual,
|
||||
run_type run)
|
||||
: m_name (name)
|
||||
, m_module (module)
|
||||
, m_library (library)
|
||||
, m_manual (manual)
|
||||
, m_run (std::move (run))
|
||||
{
|
||||
}
|
||||
template <class = void>
|
||||
suite_info (char const* name, char const* module, char const* library,
|
||||
bool manual, run_type run);
|
||||
|
||||
char const*
|
||||
name() const
|
||||
@@ -82,14 +72,9 @@ public:
|
||||
}
|
||||
|
||||
/** Return the canonical suite name as a string. */
|
||||
template <class = void>
|
||||
std::string
|
||||
full_name() const
|
||||
{
|
||||
return
|
||||
std::string (m_library) + "." +
|
||||
std::string (m_module) + "." +
|
||||
std::string (m_name);
|
||||
}
|
||||
full_name() const;
|
||||
|
||||
/** Run a new instance of the associated test suite. */
|
||||
void
|
||||
@@ -99,6 +84,33 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
suite_info::suite_info (
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual,
|
||||
run_type run)
|
||||
: m_name (name)
|
||||
, m_module (module)
|
||||
, m_library (library)
|
||||
, m_manual (manual)
|
||||
, m_run (std::move (run))
|
||||
{
|
||||
}
|
||||
|
||||
template <class>
|
||||
std::string
|
||||
suite_info::full_name() const
|
||||
{
|
||||
return
|
||||
std::string (m_library) + "." +
|
||||
std::string (m_module) + "." +
|
||||
std::string (m_name);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator< (suite_info const& lhs, suite_info const& rhs)
|
||||
@@ -108,8 +120,9 @@ operator< (suite_info const& lhs, suite_info const& rhs)
|
||||
|
||||
/** Convenience for producing suite_info for a given test type. */
|
||||
template <class Suite>
|
||||
suite_info make_suite_info (char const* name, char const* module,
|
||||
char const* library, bool manual)
|
||||
suite_info
|
||||
make_suite_info (char const* name, char const* module, char const* library,
|
||||
bool manual)
|
||||
{
|
||||
return suite_info (name, module, library, manual,
|
||||
[](runner& r)
|
||||
|
||||
@@ -35,15 +35,12 @@ namespace unit_test {
|
||||
|
||||
/** A container of test suites. */
|
||||
class suite_list
|
||||
: public const_container <
|
||||
std::set <suite_info>
|
||||
//std::list <suite_info>
|
||||
>
|
||||
: public const_container <std::set <suite_info>>
|
||||
{
|
||||
private:
|
||||
#ifndef NDEBUG
|
||||
std::unordered_set <std::string> m_names;
|
||||
std::unordered_set <std::type_index> m_classes;
|
||||
std::unordered_set <std::string> names_;
|
||||
std::unordered_set <std::type_index> classes_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -52,28 +49,34 @@ public:
|
||||
*/
|
||||
template <class Suite>
|
||||
void
|
||||
insert (char const* name,
|
||||
char const* module, char const* library,
|
||||
bool manual)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
auto const result (m_names.insert (name));
|
||||
assert (result.second); // Duplicate name
|
||||
}
|
||||
|
||||
{
|
||||
auto const result (m_classes.insert (
|
||||
std::type_index (typeid(Suite))));
|
||||
assert (result.second); // Duplicate type
|
||||
}
|
||||
#endif
|
||||
|
||||
cont().emplace (std::move (make_suite_info <Suite> (
|
||||
name, module, library, manual)));
|
||||
}
|
||||
insert (char const* name, char const* module, char const* library,
|
||||
bool manual);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Suite>
|
||||
void
|
||||
suite_list::insert (char const* name, char const* module, char const* library,
|
||||
bool manual)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
auto const result (names_.insert (name));
|
||||
assert (result.second); // Duplicate name
|
||||
}
|
||||
|
||||
{
|
||||
auto const result (classes_.insert (
|
||||
std::type_index (typeid(Suite))));
|
||||
assert (result.second); // Duplicate type
|
||||
}
|
||||
#endif
|
||||
|
||||
cont().emplace (std::move (make_suite_info <Suite> (
|
||||
name, module, library, manual)));
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
|
||||
Reference in New Issue
Block a user