forked from boostorg/beast
Refactor unit_test logging:
The log member is changed to derive from std::ostream. A new class dstream is derived from std::ostream to support redirection to the Visual Studio Output Window if a debugger is attached. Obsolete classes abstract_ostream and its derived variants are removed.
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_ABSTRACT_OSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_ABSTRACT_OSTREAM_HPP
|
||||
|
||||
#include <beast/unit_test/basic_abstract_ostream.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** An abstract ostream for `char`. */
|
||||
using abstract_ostream = basic_abstract_ostream <char>;
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -1,85 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_BASIC_ABSTRACT_OSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_BASIC_ABSTRACT_OSTREAM_HPP
|
||||
|
||||
#include <beast/unit_test/basic_scoped_ostream.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Abstraction for an output stream similar to std::basic_ostream. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>
|
||||
>
|
||||
class basic_abstract_ostream
|
||||
{
|
||||
public:
|
||||
using string_type = std::basic_string <CharT, Traits>;
|
||||
using scoped_stream_type = basic_scoped_ostream <CharT, Traits>;
|
||||
|
||||
basic_abstract_ostream() = default;
|
||||
|
||||
virtual
|
||||
~basic_abstract_ostream() = default;
|
||||
|
||||
basic_abstract_ostream (basic_abstract_ostream const&) = default;
|
||||
basic_abstract_ostream& operator= (
|
||||
basic_abstract_ostream const&) = default;
|
||||
|
||||
/** Returns `true` if the stream is active.
|
||||
Inactive streams do not produce output.
|
||||
*/
|
||||
/** @{ */
|
||||
virtual
|
||||
bool
|
||||
active() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return active();
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Called to output each string. */
|
||||
virtual
|
||||
void
|
||||
write (string_type const& s) = 0;
|
||||
|
||||
scoped_stream_type
|
||||
operator<< (std::ostream& manip (std::ostream&))
|
||||
{
|
||||
return scoped_stream_type (manip,
|
||||
[this](string_type const& s)
|
||||
{
|
||||
this->write (s);
|
||||
});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scoped_stream_type
|
||||
operator<< (T const& t)
|
||||
{
|
||||
return scoped_stream_type (t,
|
||||
[this](string_type const& s)
|
||||
{
|
||||
this->write (s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -1,136 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_BASIC_SCOPED_OSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_BASIC_SCOPED_OSTREAM_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
// gcc libstd++ doesn't have move constructors for basic_ostringstream
|
||||
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
|
||||
//
|
||||
#ifndef BEAST_NO_STDLIB_STREAM_MOVE
|
||||
# ifdef __GLIBCXX__
|
||||
# define BEAST_NO_STDLIB_STREAM_MOVE 1
|
||||
# else
|
||||
# define BEAST_NO_STDLIB_STREAM_MOVE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
|
||||
template <
|
||||
class CharT,
|
||||
class Traits
|
||||
>
|
||||
class basic_abstract_ostream;
|
||||
|
||||
/** Scoped output stream that forwards to a functor upon destruction. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>,
|
||||
class Allocator = std::allocator <CharT>
|
||||
>
|
||||
class basic_scoped_ostream
|
||||
{
|
||||
private:
|
||||
using handler_t = std::function <void (
|
||||
std::basic_string <CharT, Traits, Allocator> const&)>;
|
||||
|
||||
using stream_type = std::basic_ostringstream <
|
||||
CharT, Traits, Allocator>;
|
||||
|
||||
handler_t m_handler;
|
||||
|
||||
#if BEAST_NO_STDLIB_STREAM_MOVE
|
||||
std::unique_ptr <stream_type> m_ss;
|
||||
|
||||
stream_type& stream()
|
||||
{
|
||||
return *m_ss;
|
||||
}
|
||||
|
||||
#else
|
||||
stream_type m_ss;
|
||||
|
||||
stream_type& stream()
|
||||
{
|
||||
return m_ss;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
using string_type = std::basic_string <CharT, Traits>;
|
||||
|
||||
// Disallow copy since that would duplicate the output
|
||||
basic_scoped_ostream (basic_scoped_ostream const&) = delete;
|
||||
basic_scoped_ostream& operator= (basic_scoped_ostream const) = delete;
|
||||
|
||||
template <class Handler>
|
||||
explicit basic_scoped_ostream (Handler&& handler)
|
||||
: m_handler (std::forward <Handler> (handler))
|
||||
#if BEAST_NO_STDLIB_STREAM_MOVE
|
||||
, m_ss (new stream_type())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class Handler>
|
||||
basic_scoped_ostream (T const& t, Handler&& handler)
|
||||
: m_handler (std::forward <Handler> (handler))
|
||||
#if BEAST_NO_STDLIB_STREAM_MOVE
|
||||
, m_ss (new stream_type())
|
||||
#endif
|
||||
{
|
||||
stream() << t;
|
||||
}
|
||||
|
||||
basic_scoped_ostream (basic_abstract_ostream <
|
||||
CharT, Traits>& ostream)
|
||||
: m_handler (
|
||||
[&](string_type const& s)
|
||||
{
|
||||
ostream.write (s);
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
basic_scoped_ostream (basic_scoped_ostream&& other)
|
||||
: m_handler (std::move (other.m_handler))
|
||||
, m_ss (std::move (other.m_ss))
|
||||
{
|
||||
}
|
||||
|
||||
~basic_scoped_ostream()
|
||||
{
|
||||
auto const& s (stream().str());
|
||||
if (! s.empty())
|
||||
m_handler (s);
|
||||
}
|
||||
|
||||
basic_scoped_ostream&
|
||||
operator<< (std::ostream& manip (std::ostream&))
|
||||
{
|
||||
stream() << manip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
basic_scoped_ostream&
|
||||
operator<< (T const& t)
|
||||
{
|
||||
stream() << t;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_BASIC_STD_OSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_BASIC_STD_OSTREAM_HPP
|
||||
|
||||
#include <beast/unit_test/basic_abstract_ostream.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Wraps an existing std::basic_ostream as an abstract_ostream. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>
|
||||
>
|
||||
class basic_std_ostream
|
||||
: public basic_abstract_ostream <CharT, Traits>
|
||||
{
|
||||
private:
|
||||
using typename basic_abstract_ostream <CharT, Traits>::string_type;
|
||||
|
||||
std::reference_wrapper <std::ostream> m_stream;
|
||||
|
||||
public:
|
||||
explicit basic_std_ostream (
|
||||
std::basic_ostream <CharT, Traits>& stream)
|
||||
: m_stream (stream)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
m_stream.get() << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
using std_ostream = basic_std_ostream <char>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Returns a basic_std_ostream using template argument deduction. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>
|
||||
>
|
||||
basic_std_ostream <CharT, Traits>
|
||||
make_std_ostream (std::basic_ostream <CharT, Traits>& stream)
|
||||
{
|
||||
return basic_std_ostream <CharT, Traits> (stream);
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -1,78 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_DEBUG_OSTREAM_HPP
|
||||
#define BEAST_UNIT_TEST_DEBUG_OSTREAM_HPP
|
||||
|
||||
#include <beast/unit_test/abstract_ostream.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef WIN32_LEAN_AND_MEAN // VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# else
|
||||
#include <windows.h>
|
||||
# endif
|
||||
# ifdef min
|
||||
# undef min
|
||||
# endif
|
||||
# ifdef max
|
||||
# undef max
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/** A basic_abstract_ostream that redirects output to an attached debugger. */
|
||||
class debug_ostream
|
||||
: public abstract_ostream
|
||||
{
|
||||
private:
|
||||
bool m_debugger;
|
||||
|
||||
public:
|
||||
debug_ostream()
|
||||
: m_debugger (IsDebuggerPresent() != FALSE)
|
||||
{
|
||||
// Note that the check for an attached debugger is made only
|
||||
// during construction time, for efficiency. A stream created before
|
||||
// the debugger is attached will not have output redirected.
|
||||
}
|
||||
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
if (m_debugger)
|
||||
{
|
||||
OutputDebugStringA ((s + "\n").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
class debug_ostream
|
||||
: public abstract_ostream
|
||||
{
|
||||
public:
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -73,8 +73,8 @@ public:
|
||||
int
|
||||
sync() override
|
||||
{
|
||||
write(str().c_str());
|
||||
str("");
|
||||
write(this->str().c_str());
|
||||
this->str("");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -107,8 +107,8 @@ public:
|
||||
int
|
||||
sync() override
|
||||
{
|
||||
write(str().c_str());
|
||||
str("");
|
||||
write(this->str().c_str());
|
||||
this->str("");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -130,7 +130,7 @@ class basic_dstream
|
||||
{
|
||||
public:
|
||||
basic_dstream()
|
||||
: std::basic_ostream<CharT, Traits>(&member)
|
||||
: std::basic_ostream<CharT, Traits>(&this->member)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@@ -15,7 +15,8 @@ namespace unit_test {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class = void>
|
||||
/// Holds test suites registered during static initialization.
|
||||
inline
|
||||
suite_list&
|
||||
global_suites()
|
||||
{
|
||||
@@ -23,26 +24,20 @@ global_suites()
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Suite>
|
||||
template<class Suite>
|
||||
struct insert_suite
|
||||
{
|
||||
template <class = void>
|
||||
insert_suite (char const* name, char const* module,
|
||||
char const* library, bool manual);
|
||||
};
|
||||
|
||||
template <class Suite>
|
||||
template <class>
|
||||
insert_suite<Suite>::insert_suite (char const* name,
|
||||
char const* module, char const* library, bool manual)
|
||||
{
|
||||
global_suites().insert <Suite> (
|
||||
insert_suite(char const* name, char const* module,
|
||||
char const* library, bool manual)
|
||||
{
|
||||
global_suites().insert<Suite>(
|
||||
name, module, library, manual);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
/** Holds suites registered during static initialization. */
|
||||
/// Holds test suites registered during static initialization.
|
||||
inline
|
||||
suite_list const&
|
||||
global_suites()
|
||||
|
@@ -6,12 +6,13 @@
|
||||
//
|
||||
|
||||
#include <beast/unit_test/amount.hpp>
|
||||
#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 <beast/unit_test/suite.hpp>
|
||||
#include <beast/unit_test/debug_ostream.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
@@ -25,11 +26,10 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
static
|
||||
std::string
|
||||
prefix(suite_info const& s)
|
||||
{
|
||||
@@ -38,32 +38,34 @@ prefix(suite_info const& s)
|
||||
return " ";
|
||||
}
|
||||
|
||||
template<class Log>
|
||||
static
|
||||
void
|
||||
print(Log& log, suite_list const& c)
|
||||
print(std::ostream& os, suite_list const& c)
|
||||
{
|
||||
std::size_t manual = 0;
|
||||
for(auto const& s : c)
|
||||
{
|
||||
log <<
|
||||
prefix (s) <<
|
||||
s.full_name();
|
||||
os << prefix (s) << s.full_name() << '\n';
|
||||
if(s.manual())
|
||||
++manual;
|
||||
}
|
||||
log <<
|
||||
os <<
|
||||
amount(c.size(), "suite") << " total, " <<
|
||||
amount(manual, "manual suite")
|
||||
amount(manual, "manual suite") <<
|
||||
'\n'
|
||||
;
|
||||
}
|
||||
|
||||
template<class Log>
|
||||
// Print the list of suites
|
||||
// Used with the --print command line option
|
||||
static
|
||||
void
|
||||
print(Log& log)
|
||||
print(std::ostream& os)
|
||||
{
|
||||
log << "------------------------------------------";
|
||||
print(log, global_suites());
|
||||
log << "------------------------------------------";
|
||||
os << "------------------------------------------\n";
|
||||
print(os, global_suites());
|
||||
os << "------------------------------------------" <<
|
||||
std::endl;
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
@@ -97,11 +99,11 @@ int main(int ac, char const* av[])
|
||||
po::store(po::parse_command_line(ac, av, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
beast::debug_ostream log;
|
||||
dstream log;
|
||||
|
||||
if(vm.count("help"))
|
||||
{
|
||||
log << desc;
|
||||
log << desc << std::endl;
|
||||
}
|
||||
else if(vm.count("print"))
|
||||
{
|
||||
|
@@ -1,67 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_UNIT_TEST_PRINT_H_INCLUDED
|
||||
#define BEAST_UNIT_TEST_PRINT_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/amount.hpp>
|
||||
#include <beast/unit_test/results.hpp>
|
||||
#include <beast/unit_test/abstract_ostream.hpp>
|
||||
#include <beast/unit_test/basic_std_ostream.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** Write test results to the specified output stream. */
|
||||
/** @{ */
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, abstract_ostream& stream)
|
||||
{
|
||||
for (auto const& s : r)
|
||||
{
|
||||
for (auto const& c : s)
|
||||
{
|
||||
stream <<
|
||||
s.name() <<
|
||||
(c.name().empty() ? "" : ("." + c.name()));
|
||||
|
||||
std::size_t i (1);
|
||||
for (auto const& t : c.tests)
|
||||
{
|
||||
if (! t.pass)
|
||||
stream <<
|
||||
"#" << i <<
|
||||
" failed: " << t.reason;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream <<
|
||||
amount (r.size(), "suite") << ", " <<
|
||||
amount (r.cases(), "case") << ", " <<
|
||||
amount (r.total(), "test") << " total, " <<
|
||||
amount (r.failed(), "failure")
|
||||
;
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, std::ostream& stream = std::cout)
|
||||
{
|
||||
auto s (make_std_ostream (stream));
|
||||
print (r, s);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -10,8 +10,6 @@
|
||||
|
||||
#include <beast/unit_test/amount.hpp>
|
||||
#include <beast/unit_test/recorder.hpp>
|
||||
#include <beast/unit_test/abstract_ostream.hpp>
|
||||
#include <beast/unit_test/basic_std_ostream.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -30,7 +28,7 @@ namespace detail {
|
||||
/** A simple test runner that writes everything to a stream in real time.
|
||||
The totals are output when the object is destroyed.
|
||||
*/
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
class reporter : public runner
|
||||
{
|
||||
private:
|
||||
@@ -42,7 +40,11 @@ private:
|
||||
std::size_t total = 0;
|
||||
std::size_t failed = 0;
|
||||
|
||||
case_results (std::string const& name_ = "");
|
||||
explicit
|
||||
case_results(std::string name_ = "")
|
||||
: name(std::move(name_))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct suite_results
|
||||
@@ -51,14 +53,16 @@ private:
|
||||
std::size_t cases = 0;
|
||||
std::size_t total = 0;
|
||||
std::size_t failed = 0;
|
||||
typename clock_type::time_point start =
|
||||
clock_type::now();
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
|
||||
explicit
|
||||
suite_results (std::string const& name_ = "");
|
||||
suite_results(std::string const& name_ = "")
|
||||
: name(std::move(name_))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
add (case_results const& r);
|
||||
add(case_results const& r);
|
||||
};
|
||||
|
||||
struct results
|
||||
@@ -76,35 +80,30 @@ private:
|
||||
std::size_t total = 0;
|
||||
std::size_t failed = 0;
|
||||
std::vector<run_time> top;
|
||||
typename clock_type::time_point start =
|
||||
clock_type::now();
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
|
||||
void
|
||||
add (suite_results const& r);
|
||||
};
|
||||
|
||||
boost::optional <std_ostream> std_ostream_;
|
||||
std::reference_wrapper <beast::abstract_ostream> stream_;
|
||||
std::ostream& os_;
|
||||
results results_;
|
||||
suite_results suite_results_;
|
||||
case_results case_results_;
|
||||
|
||||
public:
|
||||
reporter (reporter const&) = delete;
|
||||
reporter& operator= (reporter const&) = delete;
|
||||
reporter(reporter const&) = delete;
|
||||
reporter& operator=(reporter const&) = delete;
|
||||
|
||||
~reporter();
|
||||
|
||||
explicit
|
||||
reporter (std::ostream& stream = std::cout);
|
||||
|
||||
explicit
|
||||
reporter (beast::abstract_ostream& stream);
|
||||
reporter(std::ostream& os = std::cout);
|
||||
|
||||
private:
|
||||
static
|
||||
std::string
|
||||
fmtdur (typename clock_type::duration const& d);
|
||||
fmtdur(typename clock_type::duration const& d);
|
||||
|
||||
virtual
|
||||
void
|
||||
@@ -137,42 +136,27 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class _>
|
||||
reporter<_>::case_results::case_results (
|
||||
std::string const& name_)
|
||||
: name (name_)
|
||||
{
|
||||
}
|
||||
|
||||
template <class _>
|
||||
reporter<_>::suite_results::suite_results (
|
||||
std::string const& name_)
|
||||
: name (name_)
|
||||
{
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::suite_results::add (case_results const& r)
|
||||
reporter<_>::
|
||||
suite_results::add(case_results const& r)
|
||||
{
|
||||
++cases;
|
||||
total += r.total;
|
||||
failed += r.failed;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::results::add (
|
||||
suite_results const& r)
|
||||
reporter<_>::
|
||||
results::add(suite_results const& r)
|
||||
{
|
||||
++suites;
|
||||
total += r.total;
|
||||
cases += r.cases;
|
||||
failed += r.failed;
|
||||
|
||||
auto const elapsed =
|
||||
clock_type::now() - r.start;
|
||||
if (elapsed >= std::chrono::seconds(1))
|
||||
auto const elapsed = clock_type::now() - r.start;
|
||||
if (elapsed >= std::chrono::seconds{1})
|
||||
{
|
||||
auto const iter = std::lower_bound(top.begin(),
|
||||
top.end(), elapsed,
|
||||
@@ -196,50 +180,40 @@ reporter<_>::results::add (
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class _>
|
||||
reporter<_>::reporter (
|
||||
std::ostream& stream)
|
||||
: std_ostream_ (std::ref (stream))
|
||||
, stream_ (*std_ostream_)
|
||||
template<class _>
|
||||
reporter<_>::
|
||||
reporter(std::ostream& os)
|
||||
: os_(os)
|
||||
{
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
reporter<_>::~reporter()
|
||||
{
|
||||
if (results_.top.size() > 0)
|
||||
if(results_.top.size() > 0)
|
||||
{
|
||||
stream_.get() << "Longest suite times:";
|
||||
for (auto const& i : results_.top)
|
||||
stream_.get() << std::setw(8) <<
|
||||
fmtdur(i.second) << " " << i.first;
|
||||
os_ << "Longest suite times:\n";
|
||||
for(auto const& i : results_.top)
|
||||
os_ << std::setw(8) <<
|
||||
fmtdur(i.second) << " " << i.first << '\n';
|
||||
}
|
||||
auto const elapsed =
|
||||
clock_type::now() - results_.start;
|
||||
stream_.get() <<
|
||||
auto const elapsed = clock_type::now() - results_.start;
|
||||
os_ <<
|
||||
fmtdur(elapsed) << ", " <<
|
||||
amount (results_.suites, "suite") << ", " <<
|
||||
amount (results_.cases, "case") << ", " <<
|
||||
amount (results_.total, "test") << " total, " <<
|
||||
amount (results_.failed, "failure");
|
||||
amount{results_.suites, "suite"} << ", " <<
|
||||
amount{results_.cases, "case"} << ", " <<
|
||||
amount{results_.total, "test"} << " total, " <<
|
||||
amount{results_.failed, "failure"} <<
|
||||
std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
reporter<_>::reporter (
|
||||
abstract_ostream& stream)
|
||||
: stream_ (stream)
|
||||
{
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
std::string
|
||||
reporter<_>::fmtdur (
|
||||
typename clock_type::duration const& d)
|
||||
reporter<_>::fmtdur(typename clock_type::duration const& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto const ms =
|
||||
duration_cast<milliseconds>(d);
|
||||
if (ms < seconds(1))
|
||||
auto const ms = duration_cast<milliseconds>(d);
|
||||
if (ms < seconds{1})
|
||||
return std::to_string(ms.count()) + "ms";
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(1) <<
|
||||
@@ -247,67 +221,67 @@ reporter<_>::fmtdur (
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_suite_begin (
|
||||
suite_info const& info)
|
||||
reporter<_>::
|
||||
on_suite_begin(suite_info const& info)
|
||||
{
|
||||
suite_results_ = suite_results (info.full_name());
|
||||
suite_results_ = suite_results{info.full_name()};
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_suite_end()
|
||||
{
|
||||
results_.add (suite_results_);
|
||||
results_.add(suite_results_);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_case_begin (
|
||||
std::string const& name)
|
||||
reporter<_>::
|
||||
on_case_begin(std::string const& name)
|
||||
{
|
||||
case_results_ = case_results (name);
|
||||
|
||||
stream_.get() <<
|
||||
os_ <<
|
||||
suite_results_.name <<
|
||||
(case_results_.name.empty() ?
|
||||
"" : (" " + case_results_.name));
|
||||
"" : (" " + case_results_.name)) << std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_case_end()
|
||||
reporter<_>::
|
||||
on_case_end()
|
||||
{
|
||||
suite_results_.add (case_results_);
|
||||
suite_results_.add(case_results_);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_pass()
|
||||
reporter<_>::
|
||||
on_pass()
|
||||
{
|
||||
++case_results_.total;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_fail (
|
||||
std::string const& reason)
|
||||
reporter<_>::
|
||||
on_fail(std::string const& reason)
|
||||
{
|
||||
++case_results_.failed;
|
||||
++case_results_.total;
|
||||
stream_.get() <<
|
||||
"#" << case_results_.total <<
|
||||
" failed" <<
|
||||
(reason.empty() ? "" : ": ") << reason;
|
||||
os_ <<
|
||||
"#" << case_results_.total << " failed" <<
|
||||
(reason.empty() ? "" : ": ") << reason << std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template<class _>
|
||||
void
|
||||
reporter<_>::on_log (
|
||||
std::string const& s)
|
||||
reporter<_>::
|
||||
on_log(std::string const& s)
|
||||
{
|
||||
stream_.get() << s;
|
||||
os_ << s;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
@@ -9,9 +9,9 @@
|
||||
#define BEAST_UNIT_TEST_RUNNER_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/suite_info.hpp>
|
||||
#include <beast/unit_test/abstract_ostream.hpp>
|
||||
#include <cassert>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
@@ -23,28 +23,6 @@ namespace unit_test {
|
||||
*/
|
||||
class runner
|
||||
{
|
||||
private:
|
||||
// Reroutes log output to the runner
|
||||
class stream_t : public abstract_ostream
|
||||
{
|
||||
private:
|
||||
runner& owner_;
|
||||
|
||||
public:
|
||||
stream_t() = delete;
|
||||
stream_t& operator= (stream_t const&) = delete;
|
||||
|
||||
template <class = void>
|
||||
stream_t (runner& owner);
|
||||
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
owner_.log (s);
|
||||
}
|
||||
};
|
||||
|
||||
stream_t stream_;
|
||||
std::string arg_;
|
||||
bool default_ = false;
|
||||
bool failed_ = false;
|
||||
@@ -52,21 +30,20 @@ private:
|
||||
std::recursive_mutex mutex_;
|
||||
|
||||
public:
|
||||
runner() = default;
|
||||
virtual ~runner() = default;
|
||||
runner (runner const&) = default;
|
||||
runner& operator= (runner const&) = default;
|
||||
|
||||
template <class = void>
|
||||
runner();
|
||||
runner(runner const&) = delete;
|
||||
runner& operator=(runner const&) = delete;
|
||||
|
||||
/** Set the argument string.
|
||||
|
||||
The argument string is available to suites and
|
||||
allows for customization of the test. Each suite
|
||||
defines its own syntax for the argumnet string.
|
||||
The same argument is passed to all suites.
|
||||
*/
|
||||
void
|
||||
arg (std::string const& s)
|
||||
arg(std::string const& s)
|
||||
{
|
||||
arg_ = s;
|
||||
}
|
||||
@@ -81,7 +58,7 @@ public:
|
||||
/** Run the specified suite.
|
||||
@return `true` if any conditions failed.
|
||||
*/
|
||||
template <class = void>
|
||||
template<class = void>
|
||||
bool
|
||||
run (suite_info const& s);
|
||||
|
||||
@@ -124,69 +101,63 @@ public:
|
||||
bool
|
||||
run_each_if (SequenceContainer const& c, Pred pred = Pred{});
|
||||
|
||||
private:
|
||||
protected:
|
||||
//
|
||||
// Overrides
|
||||
//
|
||||
|
||||
/** Called when a new suite starts. */
|
||||
/// Called when a new suite starts.
|
||||
virtual
|
||||
void
|
||||
on_suite_begin (suite_info const&)
|
||||
on_suite_begin(suite_info const&)
|
||||
{
|
||||
}
|
||||
|
||||
/** Called when a suite ends. */
|
||||
/// Called when a suite ends.
|
||||
virtual
|
||||
void
|
||||
on_suite_end()
|
||||
{
|
||||
}
|
||||
|
||||
/** Called when a new case starts. */
|
||||
/// Called when a new case starts.
|
||||
virtual
|
||||
void
|
||||
on_case_begin (std::string const&)
|
||||
on_case_begin(std::string const&)
|
||||
{
|
||||
}
|
||||
|
||||
/** Called when a new case ends. */
|
||||
/// Called when a new case ends.
|
||||
virtual
|
||||
void
|
||||
on_case_end()
|
||||
{
|
||||
}
|
||||
|
||||
/** Called for each passing condition. */
|
||||
/// Called for each passing condition.
|
||||
virtual
|
||||
void
|
||||
on_pass ()
|
||||
on_pass()
|
||||
{
|
||||
}
|
||||
|
||||
/** Called for each failing condition. */
|
||||
/// Called for each failing condition.
|
||||
virtual
|
||||
void
|
||||
on_fail (std::string const&)
|
||||
on_fail(std::string const&)
|
||||
{
|
||||
}
|
||||
|
||||
/** Called when a test logs output. */
|
||||
/// Called when a test logs output.
|
||||
virtual
|
||||
void
|
||||
on_log (std::string const&)
|
||||
on_log(std::string const&)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class suite;
|
||||
|
||||
abstract_ostream&
|
||||
stream()
|
||||
{
|
||||
return stream_;
|
||||
}
|
||||
|
||||
// Start a new testcase.
|
||||
template <class = void>
|
||||
void
|
||||
@@ -207,20 +178,6 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
runner::stream_t::stream_t (runner& owner)
|
||||
: owner_ (owner)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
runner::runner()
|
||||
: stream_ (*this)
|
||||
{
|
||||
}
|
||||
|
||||
template <class>
|
||||
bool
|
||||
runner::run (suite_info const& s)
|
||||
|
@@ -9,15 +9,23 @@
|
||||
#define BEAST_UNIT_TEST_SUITE_HPP
|
||||
|
||||
#include <beast/unit_test/runner.hpp>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
class thread;
|
||||
|
||||
enum abort_t
|
||||
{
|
||||
no_abort_on_fail,
|
||||
abort_on_fail
|
||||
};
|
||||
|
||||
/** A testsuite class.
|
||||
|
||||
Derived classes execute a series of testcases, where each testcase is
|
||||
a series of pass/fail tests. To provide a unit test using this class,
|
||||
derive from it and use the BEAST_DEFINE_UNIT_TEST macro in a
|
||||
@@ -25,13 +33,6 @@ class thread;
|
||||
*/
|
||||
class suite
|
||||
{
|
||||
public:
|
||||
enum abort_t
|
||||
{
|
||||
no_abort_on_fail,
|
||||
abort_on_fail
|
||||
};
|
||||
|
||||
private:
|
||||
bool abort_ = false;
|
||||
bool aborted_ = false;
|
||||
@@ -44,95 +45,100 @@ private:
|
||||
char const*
|
||||
what() const noexcept override
|
||||
{
|
||||
return "suite aborted";
|
||||
return "test suite aborted";
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
// Memberspace
|
||||
class log_t
|
||||
template<class CharT, class Traits, class Allocator>
|
||||
class log_buf
|
||||
: public std::basic_stringbuf<CharT, Traits, Allocator>
|
||||
{
|
||||
private:
|
||||
friend class suite;
|
||||
suite* suite_ = nullptr;
|
||||
suite& suite_;
|
||||
|
||||
public:
|
||||
log_t () = default;
|
||||
explicit
|
||||
log_buf(suite& self)
|
||||
: suite_(self)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
abstract_ostream::scoped_stream_type
|
||||
operator<< (T const& t);
|
||||
~log_buf()
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
/** Returns the raw stream used for output. */
|
||||
abstract_ostream&
|
||||
stream();
|
||||
int
|
||||
sync() override
|
||||
{
|
||||
auto const& s = this->str();
|
||||
if(s.size() > 0)
|
||||
suite_.runner_->on_log(s);
|
||||
this->str("");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
class CharT,
|
||||
class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>
|
||||
>
|
||||
class log_os : public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
log_buf<CharT, Traits, Allocator> buf_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
log_os(suite& self)
|
||||
: std::basic_ostream<CharT, Traits>(&buf_)
|
||||
, buf_(self)
|
||||
{
|
||||
}
|
||||
};
|
||||
private:
|
||||
|
||||
class scoped_testcase;
|
||||
|
||||
// Memberspace
|
||||
class testcase_t
|
||||
{
|
||||
private:
|
||||
friend class suite;
|
||||
suite* suite_ = nullptr;
|
||||
suite& suite_;
|
||||
std::stringstream ss_;
|
||||
|
||||
public:
|
||||
testcase_t() = default;
|
||||
explicit
|
||||
testcase_t(suite& self)
|
||||
: suite_(self)
|
||||
{
|
||||
}
|
||||
|
||||
/** 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.
|
||||
|
||||
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 Determines if suite continues running after a failure.
|
||||
*/
|
||||
void
|
||||
operator() (std::string const& name,
|
||||
operator()(std::string const& name,
|
||||
abort_t abort = no_abort_on_fail);
|
||||
|
||||
/** Stream style composition of testcase names. */
|
||||
/** @{ */
|
||||
scoped_testcase
|
||||
operator() (abort_t abort);
|
||||
operator()(abort_t abort);
|
||||
|
||||
template <class T>
|
||||
scoped_testcase
|
||||
operator<< (T const& t);
|
||||
/** @} */
|
||||
operator<<(T const& t);
|
||||
};
|
||||
|
||||
public:
|
||||
/** Type for scoped stream logging.
|
||||
To use this type, declare a local variable of the type
|
||||
on the stack in derived class member function and construct
|
||||
it from log.stream();
|
||||
/** Logging output stream.
|
||||
|
||||
@code
|
||||
|
||||
scoped_stream ss (log.stream();
|
||||
|
||||
ss << "Hello" << std::endl;
|
||||
ss << "world" << std::endl;
|
||||
|
||||
@endcode
|
||||
|
||||
Streams constructed in this fashion will not have the line
|
||||
ending automatically appended.
|
||||
|
||||
Thread safety:
|
||||
|
||||
The scoped_stream may only be used by one thread.
|
||||
Multiline output sent to the stream will be atomically
|
||||
written to the underlying abstract_Ostream
|
||||
Text sent to the log output stream will be forwarded to
|
||||
the output stream associated with the runner.
|
||||
*/
|
||||
using scoped_stream = abstract_ostream::scoped_stream_type;
|
||||
|
||||
/** Memberspace for logging. */
|
||||
log_t log;
|
||||
log_os<char> log;
|
||||
|
||||
/** Memberspace for declaring test cases. */
|
||||
testcase_t testcase;
|
||||
@@ -145,6 +151,12 @@ public:
|
||||
return *p_this_suite();
|
||||
}
|
||||
|
||||
suite()
|
||||
: log(*this)
|
||||
, testcase(*this)
|
||||
{
|
||||
}
|
||||
|
||||
/** 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
|
||||
@@ -272,83 +284,50 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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_;
|
||||
suite& suite_;
|
||||
std::stringstream& ss_;
|
||||
|
||||
public:
|
||||
~scoped_testcase();
|
||||
scoped_testcase& operator=(scoped_testcase const&) = delete;
|
||||
|
||||
scoped_testcase (suite* s, std::stringstream* ss);
|
||||
~scoped_testcase()
|
||||
{
|
||||
auto const& name = ss_.str();
|
||||
if(! name.empty())
|
||||
suite_.runner_->testcase (name);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scoped_testcase (suite* s, std::stringstream* ss, T const& t);
|
||||
scoped_testcase(suite& self, std::stringstream& ss)
|
||||
: suite_(self)
|
||||
, ss_(ss)
|
||||
{
|
||||
ss_.clear();
|
||||
ss_.str({});
|
||||
}
|
||||
|
||||
scoped_testcase& operator= (scoped_testcase const&) = delete;
|
||||
template<class T>
|
||||
scoped_testcase(suite& self,
|
||||
std::stringstream& ss, T const& t)
|
||||
: suite_(self)
|
||||
, ss_(ss)
|
||||
{
|
||||
ss_.clear();
|
||||
ss_.str({});
|
||||
ss_ << t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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;
|
||||
operator<<(T const& t)
|
||||
{
|
||||
ss_ << t;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -357,16 +336,16 @@ void
|
||||
suite::testcase_t::operator() (std::string const& name,
|
||||
abort_t abort)
|
||||
{
|
||||
suite_->abort_ = abort == abort_on_fail;
|
||||
suite_->runner_->testcase (name);
|
||||
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_ };
|
||||
suite_.abort_ = abort == abort_on_fail;
|
||||
return { suite_, ss_ };
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -374,7 +353,7 @@ inline
|
||||
suite::scoped_testcase
|
||||
suite::testcase_t::operator<< (T const& t)
|
||||
{
|
||||
return { suite_, &ss_, t };
|
||||
return { suite_, ss_, t };
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -511,8 +490,6 @@ void
|
||||
suite::run (runner& r)
|
||||
{
|
||||
runner_ = &r;
|
||||
log.suite_ = this;
|
||||
testcase.suite_ = this;
|
||||
|
||||
try
|
||||
{
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_UNIT_TEST_SUITE_INFO_HPP
|
||||
#define BEAST_UNIT_TEST_SUITE_INFO_HPP
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -20,19 +21,28 @@ class runner;
|
||||
/** Associates a unit test type with metadata. */
|
||||
class suite_info
|
||||
{
|
||||
private:
|
||||
using run_type = std::function <void (runner&)>;
|
||||
using run_type = std::function<void(runner&)>;
|
||||
|
||||
std::string name_;
|
||||
std::string module_;
|
||||
std::string library_;
|
||||
bool m_manual;
|
||||
run_type m_run;
|
||||
bool manual_;
|
||||
run_type run_;
|
||||
|
||||
public:
|
||||
template <class = void>
|
||||
suite_info (std::string const& name, std::string const& module,
|
||||
std::string const& library, bool manual, run_type run);
|
||||
suite_info(
|
||||
std::string name,
|
||||
std::string module,
|
||||
std::string library,
|
||||
bool manual,
|
||||
run_type run)
|
||||
: name_(std::move(name))
|
||||
, module_(std::move(module))
|
||||
, library_(std::move(library))
|
||||
, manual_(manual)
|
||||
, run_(std::move(run))
|
||||
{
|
||||
}
|
||||
|
||||
std::string const&
|
||||
name() const
|
||||
@@ -52,61 +62,58 @@ public:
|
||||
return library_;
|
||||
}
|
||||
|
||||
/** Returns `true` if this suite only runs manually. */
|
||||
/// Returns `true` if this suite only runs manually.
|
||||
bool
|
||||
manual() const
|
||||
{
|
||||
return m_manual;
|
||||
return manual_;
|
||||
}
|
||||
|
||||
/** Return the canonical suite name as a string. */
|
||||
template <class = void>
|
||||
/// Return the canonical suite name as a string.
|
||||
std::string
|
||||
full_name() const;
|
||||
|
||||
/** Run a new instance of the associated test suite. */
|
||||
void
|
||||
run (runner& r) const
|
||||
full_name() const
|
||||
{
|
||||
m_run (r);
|
||||
return library_ + "." + module_ + "." + name_;
|
||||
}
|
||||
|
||||
/// Run a new instance of the associated test suite.
|
||||
void
|
||||
run(runner& r) const
|
||||
{
|
||||
run_ (r);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator<(suite_info const& lhs, suite_info const& rhs)
|
||||
{
|
||||
return
|
||||
std::tie(lhs.library_, lhs.module_, lhs.name_) <
|
||||
std::tie(rhs.library_, rhs.module_, rhs.name_);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
suite_info::suite_info (std::string const& name, std::string const& module,
|
||||
std::string const& library, bool manual, run_type run)
|
||||
: name_ (name)
|
||||
, module_ (module)
|
||||
, library_ (library)
|
||||
, m_manual (manual)
|
||||
, m_run (std::move (run))
|
||||
{
|
||||
}
|
||||
|
||||
template <class>
|
||||
std::string
|
||||
suite_info::full_name() const
|
||||
{
|
||||
return library_ + "." + module_ + "." + name_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator< (suite_info const& lhs, suite_info const& rhs)
|
||||
{
|
||||
return lhs.full_name() < rhs.full_name();
|
||||
}
|
||||
|
||||
/** Convenience for producing suite_info for a given test type. */
|
||||
template <class Suite>
|
||||
/// Convenience for producing suite_info for a given test type.
|
||||
template<class Suite>
|
||||
suite_info
|
||||
make_suite_info (std::string const& name, std::string const& module,
|
||||
std::string const& library, bool manual)
|
||||
make_suite_info(
|
||||
std::string name,
|
||||
std::string module,
|
||||
std::string library,
|
||||
bool manual)
|
||||
{
|
||||
return suite_info(name, module, library, manual,
|
||||
[](runner& r) { return Suite{}(r); });
|
||||
return suite_info(
|
||||
std::move(name),
|
||||
std::move(module),
|
||||
std::move(library),
|
||||
manual,
|
||||
[](runner& r)
|
||||
{
|
||||
Suite{}(r);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
|
@@ -18,23 +18,27 @@
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** A container of test suites. */
|
||||
/// A container of test suites.
|
||||
class suite_list
|
||||
: public detail::const_container <std::set <suite_info>>
|
||||
{
|
||||
private:
|
||||
#ifndef NDEBUG
|
||||
std::unordered_set <std::string> names_;
|
||||
std::unordered_set <std::type_index> classes_;
|
||||
std::unordered_set<std::string> names_;
|
||||
std::unordered_set<std::type_index> classes_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/** Insert a suite into the set.
|
||||
|
||||
The suite must not already exist.
|
||||
*/
|
||||
template <class Suite>
|
||||
void
|
||||
insert (char const* name, char const* module, char const* library,
|
||||
insert(
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual);
|
||||
};
|
||||
|
||||
@@ -42,7 +46,10 @@ public:
|
||||
|
||||
template <class Suite>
|
||||
void
|
||||
suite_list::insert (char const* name, char const* module, char const* library,
|
||||
suite_list::insert(
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
@@ -59,9 +66,8 @@ suite_list::insert (char const* name, char const* module, char const* library,
|
||||
assert (result.second); // Duplicate type
|
||||
}
|
||||
#endif
|
||||
|
||||
cont().emplace (std::move (make_suite_info <Suite> (
|
||||
name, module, library, manual)));
|
||||
cont().emplace(make_suite_info<Suite>(
|
||||
name, module, library, manual));
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
|
@@ -85,7 +85,7 @@ public:
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using clock_type = std::chrono::high_resolution_clock;
|
||||
log << name;
|
||||
log << name << std::endl;
|
||||
for(std::size_t trial = 1; trial <= repeat; ++trial)
|
||||
{
|
||||
auto const t0 = clock_type::now();
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
auto const elapsed = clock_type::now() - t0;
|
||||
log <<
|
||||
"Trial " << trial << ": " <<
|
||||
duration_cast<milliseconds>(elapsed).count() << " ms";
|
||||
duration_cast<milliseconds>(elapsed).count() << " ms" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@ public:
|
||||
static std::size_t constexpr Repeat = 50;
|
||||
|
||||
log << "sizeof(request parser) == " <<
|
||||
sizeof(basic_parser_v1<true, null_parser<true>>);
|
||||
sizeof(basic_parser_v1<true, null_parser<true>>) << '\n';
|
||||
|
||||
log << "sizeof(response parser) == " <<
|
||||
sizeof(basic_parser_v1<false, null_parser<true>>);
|
||||
sizeof(basic_parser_v1<false, null_parser<true>>)<< '\n';
|
||||
|
||||
testcase << "Parser speed test, " <<
|
||||
((Repeat * size_ + 512) / 1024) << "KB in " <<
|
||||
|
Reference in New Issue
Block a user