diff --git a/beast/unit_test/amount.h b/beast/unit_test/amount.h index ef95014045..25db44411f 100644 --- a/beast/unit_test/amount.h +++ b/beast/unit_test/amount.h @@ -31,28 +31,36 @@ namespace unit_test { class amount { private: - std::size_t n; - std::string const& what; + std::size_t n_; + std::string const& what_; public: amount (amount const&) = default; amount& operator= (amount const&) = delete; - amount (std::size_t n_, std::string const& what_) - : n (n_) - , what (what_) - { - } + template + amount (std::size_t n, std::string const& what); friend std::ostream& - operator<< (std::ostream& s, amount const& t) - { - s << t.n << " " << t.what << ((t.n != 1) ? "s" : ""); - return s; - } + operator<< (std::ostream& s, amount const& t); }; +template +amount::amount (std::size_t n, std::string const& what) + : n_ (n) + , what_ (what) +{ +} + +inline +std::ostream& +operator<< (std::ostream& s, amount const& t) +{ + s << t.n_ << " " << t.what_ << ((t.n_ != 1) ? "s" : ""); + return s; +} + } // unit_test } // beast diff --git a/beast/unit_test/define_print.cpp b/beast/unit_test/define_print.cpp index 00194879fc..27e2c2d7a7 100644 --- a/beast/unit_test/define_print.cpp +++ b/beast/unit_test/define_print.cpp @@ -20,58 +20,79 @@ #include #include #include +#include // Include this .cpp in your project to gain access to the printing suite namespace beast { namespace unit_test { - namespace detail { /** A suite that prints the list of globally defined suites. */ class print_test : public suite { +private: + template + void + do_run(); + public: + template static std::string - prefix (suite_info const& s) - { - if (s.manual()) - return "|M| "; - return " "; - } + prefix (suite_info const& s); + template void - print (suite_list &c) - { - std::size_t manual (0); - for (auto const& s : c) - { - log << - prefix (s) << - s.full_name(); - if (s.manual()) - ++manual; - } - log << - amount (c.size(), "suite") << " total, " << - amount (manual, "manual suite") - ; - } + print (suite_list &c); void run() { - log << "------------------------------------------"; - print (global_suites()); - log << "------------------------------------------"; - pass(); + do_run(); } }; +template +void +print_test::do_run() +{ + log << "------------------------------------------"; + print (global_suites()); + log << "------------------------------------------"; + pass(); +} + +template +std::string +print_test::prefix (suite_info const& s) +{ + if (s.manual()) + return "|M| "; + return " "; +} + +template +void +print_test::print (suite_list &c) +{ + std::size_t manual (0); + for (auto const& s : c) + { + log << + prefix (s) << + s.full_name(); + if (s.manual()) + ++manual; + } + log << + amount (c.size(), "suite") << " total, " << + amount (manual, "manual suite") + ; +} + BEAST_DEFINE_TESTSUITE_MANUAL(print,unit_test,beast); } - } } diff --git a/beast/unit_test/global_suites.h b/beast/unit_test/global_suites.h index eb61b9b62e..8a446c91ed 100644 --- a/beast/unit_test/global_suites.h +++ b/beast/unit_test/global_suites.h @@ -27,8 +27,7 @@ namespace unit_test { namespace detail { -// Non const container is a detail, users are not allowed to modify! -inline +template suite_list& global_suites() { @@ -36,18 +35,23 @@ global_suites() return s; } -// Used to insert suites during static initialization template -struct global_suite_instance +struct insert_suite { - global_suite_instance (char const* name, char const* module, - char const* library, bool manual) - { - global_suites().insert ( - name, module, library, manual); - } + template + insert_suite (char const* name, char const* module, + char const* library, bool manual); }; +template +template +insert_suite::insert_suite (char const* name, + char const* module, char const* library, bool manual) +{ + global_suites().insert ( + name, module, library, manual); +} + } // detail /** Holds suites registered during static initialization. */ @@ -58,7 +62,7 @@ global_suites() return detail::global_suites(); } -} // unit_test -} // beast +} +} #endif diff --git a/beast/unit_test/match.h b/beast/unit_test/match.h index 763c1ac655..6b6cf96e87 100644 --- a/beast/unit_test/match.h +++ b/beast/unit_test/match.h @@ -56,69 +56,80 @@ private: std::string m_library; public: + template explicit - selector (mode_t mode, std::string const& pattern = "") - : m_mode (mode) - , m_pat (pattern) - { - if (m_mode == automatch && pattern.empty()) - m_mode = all; - } + selector (mode_t mode, std::string const& pattern = ""); + template bool - operator() (suite_info const& s) - { - switch (m_mode) - { - case automatch: - // check suite - if (m_pat == s.name()) - { - m_mode = none; - return true; - } - - // check module - if (m_pat == s.module()) - { - m_mode = module; - m_library = s.library(); - return ! s.manual(); - } - - // check library - if (m_pat == s.library()) - { - m_mode = library; - return ! s.manual(); - } - - return false; - - case suite: - return m_pat == s.name(); - - case module: - return m_pat == s.module() && ! s.manual(); - - case library: - return m_pat == s.library() && ! s.manual(); - - case none: - return false; - - case all: - default: - // fall through - break; - }; - - return ! s.manual(); - } + operator() (suite_info const& s); }; //------------------------------------------------------------------------------ +template +selector::selector (mode_t mode, std::string const& pattern) + : m_mode (mode) + , m_pat (pattern) +{ + if (m_mode == automatch && pattern.empty()) + m_mode = all; +} + +template +bool +selector::operator() (suite_info const& s) +{ + switch (m_mode) + { + case automatch: + // check suite + if (m_pat == s.name()) + { + m_mode = none; + return true; + } + + // check module + if (m_pat == s.module()) + { + m_mode = module; + m_library = s.library(); + return ! s.manual(); + } + + // check library + if (m_pat == s.library()) + { + m_mode = library; + return ! s.manual(); + } + + return false; + + case suite: + return m_pat == s.name(); + + case module: + return m_pat == s.module() && ! s.manual(); + + case library: + return m_pat == s.library() && ! s.manual(); + + case none: + return false; + + case all: + default: + // fall through + break; + }; + + return ! s.manual(); +} + +//------------------------------------------------------------------------------ + // Utility functions for producing predicates to select suites. /** Returns a predicate that implements a smart matching rule. diff --git a/beast/unit_test/results.h b/beast/unit_test/results.h index d19687d080..0e4ee1e5fe 100644 --- a/beast/unit_test/results.h +++ b/beast/unit_test/results.h @@ -55,11 +55,11 @@ private: : public const_container > { private: - std::size_t m_failed; + std::size_t failed_; public: tests_t () - : m_failed (0) + : failed_ (0) { } @@ -74,7 +74,7 @@ private: std::size_t failed() const { - return m_failed; + return failed_; } /** Register a successful test condition. */ @@ -88,7 +88,7 @@ private: void fail (std::string const& reason = "") { - ++m_failed; + ++failed_; cont().emplace_back (false, reason); } }; @@ -105,11 +105,11 @@ private: } }; - std::string m_name; + std::string name_; public: explicit case_results (std::string const& name = "") - : m_name (name) + : name_ (name) { } @@ -117,7 +117,7 @@ public: std::string const& name() const { - return m_name; + return name_; } /** Memberspace for a container of test condition outcomes. */ @@ -134,15 +134,13 @@ class suite_results : public const_container > { private: - std::string m_name; - std::size_t m_total; - std::size_t m_failed; + std::string name_; + std::size_t total_ = 0; + std::size_t failed_ = 0; public: explicit suite_results (std::string const& name = "") - : m_name (name) - , m_total (0) - , m_failed (0) + : name_ (name) { } @@ -150,21 +148,21 @@ public: std::string const& name() const { - return m_name; + return name_; } /** Returns the total number of test conditions. */ std::size_t total() const { - return m_total; + return total_; } /** Returns the number of failures. */ std::size_t failed() const { - return m_failed; + return failed_; } /** Insert a set of testcase results. */ @@ -173,16 +171,16 @@ public: insert (case_results&& r) { cont().emplace_back (std::move (r)); - m_total += r.tests.total(); - m_failed += r.tests.failed(); + total_ += r.tests.total(); + failed_ += r.tests.failed(); } void insert (case_results const& r) { cont().push_back (r); - m_total += r.tests.total(); - m_failed += r.tests.failed(); + total_ += r.tests.total(); + failed_ += r.tests.failed(); } /** @} */ }; @@ -196,14 +194,14 @@ class results { private: std::size_t m_cases; - std::size_t m_total; - std::size_t m_failed; + std::size_t total_; + std::size_t failed_; public: results() : m_cases (0) - , m_total (0) - , m_failed (0) + , total_ (0) + , failed_ (0) { } @@ -218,14 +216,14 @@ public: std::size_t total() const { - return m_total; + return total_; } /** Returns the number of failures. */ std::size_t failed() const { - return m_failed; + return failed_; } /** Insert a set of suite results. */ @@ -234,8 +232,8 @@ public: insert (suite_results&& r) { m_cases += r.size(); - m_total += r.total(); - m_failed += r.failed(); + total_ += r.total(); + failed_ += r.failed(); cont().emplace_back (std::move (r)); } @@ -243,8 +241,8 @@ public: insert (suite_results const& r) { m_cases += r.size(); - m_total += r.total(); - m_failed += r.failed(); + total_ += r.total(); + failed_ += r.failed(); cont().push_back (r); } /** @} */ diff --git a/beast/unit_test/runner.h b/beast/unit_test/runner.h index befd699780..164770f628 100644 --- a/beast/unit_test/runner.h +++ b/beast/unit_test/runner.h @@ -21,10 +21,9 @@ #define BEAST_UNIT_TEST_RUNNER_H_INCLUDED #include - #include - #include +#include #include namespace beast { @@ -47,22 +46,22 @@ private: stream_t() = delete; stream_t& operator= (stream_t const&) = delete; - stream_t (runner& owner) - : owner_ (owner) - { - } + template + stream_t (runner& owner); void - write (string_type const& s) + write (string_type const& s) override { owner_.log (s); } }; stream_t stream_; - bool default_; - bool failed_; - bool cond_; + std::string arg_; + bool default_ = false; + bool failed_ = false; + bool cond_ = false; + std::recursive_mutex mutex_; public: virtual ~runner() = default; @@ -72,6 +71,25 @@ public: template runner(); + /** 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_ = s; + } + + /** Returns the argument string. */ + std::string const& + arg() const + { + return arg_; + } + /** Run the specified suite. @return `true` if any conditions failed. */ @@ -201,12 +219,17 @@ private: //------------------------------------------------------------------------------ +template +runner::stream_t::stream_t (runner& owner) + : owner_ (owner) +{ +} + +//------------------------------------------------------------------------------ + template runner::runner() : stream_ (*this) - , default_ (false) - , failed_ (false) - , cond_ (false) { } @@ -272,6 +295,7 @@ template void runner::testcase (std::string const& name) { + std::lock_guard lock(mutex_); // Name may not be empty assert (default_ || ! name.empty()); // Forgot to call pass or fail @@ -287,6 +311,7 @@ template void runner::pass() { + std::lock_guard lock(mutex_); if (default_) testcase (""); on_pass(); @@ -297,6 +322,7 @@ template void runner::fail (std::string const& reason) { + std::lock_guard lock(mutex_); if (default_) testcase (""); on_fail (reason); @@ -308,6 +334,7 @@ template void runner::log (std::string const& s) { + std::lock_guard lock(mutex_); if (default_) testcase (""); on_log (s); diff --git a/beast/unit_test/suite.h b/beast/unit_test/suite.h index 9254ba30f9..b9c4f7d657 100644 --- a/beast/unit_test/suite.h +++ b/beast/unit_test/suite.h @@ -166,6 +166,13 @@ public: bool expect (Condition shouldBeTrue, std::string const& reason = ""); + /** Return the argument associated with the runner. */ + std::string const& + arg() const + { + return runner_->arg(); + } + // DEPRECATED // @return `true` if the test condition indicates success (a false value) template @@ -398,8 +405,8 @@ suite::fail (std::string const& reason) // detail: // This inserts the suite with the given manual flag #define BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,manual) \ - static beast::unit_test::detail::global_suite_instance \ - Library ## Module ## Class ## _test_instance ( \ + static beast::unit_test::detail::insert_suite \ + Library ## Module ## Class ## _test_instance ( \ #Class, #Module, #Library, manual); //------------------------------------------------------------------------------