diff --git a/BeastConfig.h b/BeastConfig.h index 40d2da93..0765cc3b 100644 --- a/BeastConfig.h +++ b/BeastConfig.h @@ -27,6 +27,19 @@ @file BeastConfig.h */ +//------------------------------------------------------------------------------ +// +// Unit Tests +// +//------------------------------------------------------------------------------ + +/** Config: BEAST_NO_UNIT_TEST_INLINE + Prevents unit test definitions from being inserted into a global table. +*/ +#ifndef BEAST_NO_UNIT_TEST_INLINE +#define BEAST_NO_UNIT_TEST_INLINE 0 +#endif + //------------------------------------------------------------------------------ // // Diagnostics diff --git a/Builds/VisualStudio2013/beast.vcxproj b/Builds/VisualStudio2013/beast.vcxproj index 1df00296..9dbccaa5 100644 --- a/Builds/VisualStudio2013/beast.vcxproj +++ b/Builds/VisualStudio2013/beast.vcxproj @@ -93,6 +93,7 @@ + @@ -224,6 +225,24 @@ + + + + true + true + true + true + + + + + + + + + + + @@ -284,7 +303,6 @@ - @@ -300,7 +318,6 @@ - @@ -380,7 +397,7 @@ true true - + true true true @@ -392,13 +409,13 @@ true true - + true true true true - + true true true @@ -406,38 +423,32 @@ - - true - true - true - true - true true true true - - true - true - true - true - - - true - true - true - true - true true true true + + true + true + true + true + + + true + true + true + true + - + true true true @@ -450,12 +461,6 @@ true - - true - true - true - true - true true @@ -492,6 +497,18 @@ true true + + true + true + true + true + + + true + true + true + true + true @@ -548,6 +565,12 @@ true true + + true + true + true + true + true true @@ -597,12 +620,6 @@ true true - - true - true - true - true - true true @@ -622,8 +639,19 @@ true - + + true + true + true + true + + + true + true + true + true + true true @@ -637,12 +665,6 @@ true - - true - true - true - true - true true @@ -673,13 +695,19 @@ true true - - + true true true true + + true + true + true + true + + true true @@ -716,6 +744,12 @@ true true + + true + true + true + true + true true @@ -800,12 +834,6 @@ true true - - true - true - true - true - true true @@ -871,12 +899,6 @@ true true - - true - true - true - true - true true @@ -943,12 +965,6 @@ true true - - true - true - true - true - true true @@ -1285,7 +1301,7 @@ Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - $(ProjectDir);%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) false true diff --git a/Builds/VisualStudio2013/beast.vcxproj.filters b/Builds/VisualStudio2013/beast.vcxproj.filters index e2c6b8d5..eb91f1d7 100644 --- a/Builds/VisualStudio2013/beast.vcxproj.filters +++ b/Builds/VisualStudio2013/beast.vcxproj.filters @@ -264,9 +264,6 @@ {48c7ee12-704c-42cb-99ea-9a486bb4b57e} - - {e30eda19-95b4-4831-b86a-ee5fae88abd2} - {a4dca8cc-7d1f-4353-b7e1-15eab33e8bd4} @@ -291,6 +288,27 @@ {3c58ba5e-1855-4865-8a9f-c0afd5014e74} + + {09aa885d-9607-4f8c-80d2-43673e541fd0} + + + {afec071b-bc2c-4d32-a5e3-e99273a81a1c} + + + {3e1fc57f-e3c0-4889-a1d8-25145aa535a1} + + + {1e86eefc-51b3-4270-b472-dd3f323e9875} + + + {a8c4a672-6264-45a5-8c22-e3ce2391300e} + + + {94cc3672-688a-46e4-8df0-c3523a521c43} + + + {63c495fa-b6b2-42ed-8ae3-9f3582e76bf5} + @@ -416,9 +434,6 @@ beast_core\diagnostic - - beast_core\diagnostic - beast_core\files @@ -656,9 +671,6 @@ beast_core\time - - beast_core\misc - beast_core\diagnostic @@ -749,9 +761,6 @@ beast - - beast - beast @@ -1170,6 +1179,54 @@ beast\streams + + beast\unit_test + + + beast\unit_test + + + beast\unit_test + + + beast\unit_test + + + beast\unit_test + + + beast + + + beast\unit_test + + + beast + + + beast\unit_test + + + beast\container + + + beast\unit_test + + + beast\unit_test + + + beast\unit_test + + + beast\unit_test + + + beast\chrono + + + beast\unit_test + @@ -1274,9 +1331,6 @@ beast_core\native - - beast_core\diagnostic - beast_core\files @@ -1355,9 +1409,6 @@ beast_asio\basics - - beast_asio\system - beast_asio\tests @@ -1418,9 +1469,6 @@ beast_core\time - - beast_core\misc - beast_core\diagnostic @@ -1499,15 +1547,6 @@ beast_asio\http - - beast\chrono\impl - - - beast\smart_ptr - - - beast\threads\impl - beast\threads\impl @@ -1565,15 +1604,6 @@ beast\insight\impl - - beast\chrono\impl - - - beast\chrono\impl - - - beast\crypto\impl - beast\crypto\impl @@ -1583,9 +1613,6 @@ beast\insight\impl - - beast\net\impl - beast\net\impl @@ -1595,21 +1622,12 @@ beast\net\impl - - beast\utility\impl - beast\chrono - - beast\chrono\impl - beast\container - - beast\container\impl - beast\container\tests @@ -1622,15 +1640,6 @@ beast\asio - - beast\asio\tests - - - beast\asio\tests - - - beast\asio\tests - beast\asio\tests @@ -1640,11 +1649,56 @@ beast\http\impl + + beast\utility\tests + + + beast\container\tests + + + beast\asio\tests + + + beast\asio\tests + + + beast\asio\tests + + + beast\chrono\tests + + + beast\crypto\tests + + + beast\crypto\tests + + + beast\utility\tests + + + beast\threads\tests + + + beast\chrono\tests + + + beast\chrono\impl + + + beast\http\tests + + + beast\net\tests + + + beast\streams\tests + beast\streams - - beast\utility\tests + + beast\threads\tests diff --git a/beast/asio/Asio.cpp b/beast/asio/Asio.cpp index fb60b4fd..4f964be9 100644 --- a/beast/asio/Asio.cpp +++ b/beast/asio/Asio.cpp @@ -23,10 +23,10 @@ #include "impl/IPAddressConversion.cpp" -#include "tests/wrap_handler_tests.cpp" -#include "tests/bind_handler_tests.cpp" +#include "tests/wrap_handler.test.cpp" +#include "tests/bind_handler.test.cpp" #include "tests/enable_wait_for_async.test.cpp" -#include "tests/shared_handler_tests.cpp" +#include "tests/shared_handler.test.cpp" #include "abstract_socket.cpp" // TEMPORARY! diff --git a/beast/asio/tests/bind_handler_tests.cpp b/beast/asio/tests/bind_handler.test.cpp similarity index 78% rename from beast/asio/tests/bind_handler_tests.cpp rename to beast/asio/tests/bind_handler.test.cpp index 7992e1f1..c9e8d5a7 100644 --- a/beast/asio/tests/bind_handler_tests.cpp +++ b/beast/asio/tests/bind_handler.test.cpp @@ -21,7 +21,7 @@ #include "../../../BeastConfig.h" #endif -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" #include "../bind_handler.h" @@ -30,31 +30,24 @@ namespace beast { namespace asio { -class bind_handler_Tests : public UnitTest +class bind_handler_test : public unit_test::suite { public: static void foo (int) { } - void runTest() + void run() { - beginTestCase ("call"); - - auto f (bind_handler (std::bind (&foo, std::placeholders::_1), + auto f (bind_handler ( + std::bind (&foo, std::placeholders::_1), 42)); - f(); - pass(); } - - bind_handler_Tests() : UnitTest ("bind_handler", "beast", runManual) - { - } }; -static bind_handler_Tests bind_handler_tests; +BEAST_DEFINE_TESTSUITE(bind_handler,asio,beast); } } diff --git a/beast/asio/tests/enable_wait_for_async.test.cpp b/beast/asio/tests/enable_wait_for_async.test.cpp index 191cbb4b..f09f53e4 100644 --- a/beast/asio/tests/enable_wait_for_async.test.cpp +++ b/beast/asio/tests/enable_wait_for_async.test.cpp @@ -21,7 +21,7 @@ #include "../../../BeastConfig.h" #endif -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" #include "../bind_handler.h" #include "../enable_wait_for_async.h" @@ -30,7 +30,7 @@ namespace beast { -class enable_wait_for_async_Tests : public UnitTest +class enable_wait_for_async_test : public unit_test::suite { public: typedef boost::system::error_code error_code; @@ -89,22 +89,17 @@ public: } }; - beginTestCase ("wait_for_async"); owner o; o(); expect (o.notified); } - void runTest() + void run() { test(); } - - enable_wait_for_async_Tests() : UnitTest ("enable_wait_for_async", "beast") - { - } }; -static enable_wait_for_async_Tests enable_wait_for_async_tests; +BEAST_DEFINE_TESTSUITE(enable_wait_for_async,asio,beast); } diff --git a/beast/asio/tests/shared_handler_tests.cpp b/beast/asio/tests/shared_handler.test.cpp similarity index 95% rename from beast/asio/tests/shared_handler_tests.cpp rename to beast/asio/tests/shared_handler.test.cpp index 358ff798..686c0f08 100644 --- a/beast/asio/tests/shared_handler_tests.cpp +++ b/beast/asio/tests/shared_handler.test.cpp @@ -21,7 +21,7 @@ #include "../../../BeastConfig.h" #endif -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" #include "../shared_handler.h" @@ -37,7 +37,7 @@ namespace beast { -class shared_handler_Tests : public UnitTest +class shared_handler_test : public unit_test::suite { public: struct test_results @@ -139,10 +139,8 @@ public: async_op (handler); } - void runTest() + void run() { - beginTestCase ("hooks"); - #if ! BEAST_NO_STD_FUNCTION_CONSTRUCTIBLE static_assert (! std::is_constructible < std::function , int&&>::value, @@ -230,12 +228,8 @@ public: expect (r.cont); } } - - shared_handler_Tests() : UnitTest ("shared_handler", "beast") - { - } }; -static shared_handler_Tests shared_handler_tests; +BEAST_DEFINE_TESTSUITE(shared_handler,asio,beast); } diff --git a/beast/asio/tests/wrap_handler_tests.cpp b/beast/asio/tests/wrap_handler.test.cpp similarity index 90% rename from beast/asio/tests/wrap_handler_tests.cpp rename to beast/asio/tests/wrap_handler.test.cpp index de368f74..be72dbb0 100644 --- a/beast/asio/tests/wrap_handler_tests.cpp +++ b/beast/asio/tests/wrap_handler.test.cpp @@ -21,7 +21,7 @@ #include "../../../BeastConfig.h" #endif -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" #include "../wrap_handler.h" @@ -38,7 +38,7 @@ namespace asio { // Displays the order of destruction of parameters in the bind wrapper // -class boost_bind_Tests : public UnitTest +class boost_bind_test : public unit_test::suite { public: struct Result @@ -84,10 +84,8 @@ public: { } - void runTest() + void run() { - beginTestCase ("order"); - { Result r; { @@ -96,7 +94,8 @@ public: Arg (r, "two"), Arg (r, "three")); } - logMessage (std::string ("boost::bind (") + r.text + ")"); + log << + std::string ("boost::bind (") + r.text + ")"; } { @@ -107,22 +106,20 @@ public: Arg (r, "two"), Arg (r, "three")); } - logMessage (std::string ("std::bind (") + r.text + ")"); + + log << + std::string ("std::bind (") + r.text + ")"; } pass(); } - - boost_bind_Tests() : UnitTest ("bind", "beast", runManual) - { - } }; -static boost_bind_Tests boost_bind_tests; +BEAST_DEFINE_TESTSUITE(boost_bind,asio,beast); //------------------------------------------------------------------------------ -class wrap_handler_handler_Tests : public UnitTest +class wrap_handler_test : public unit_test::suite { public: struct test_results @@ -218,10 +215,8 @@ public: return boost_asio_handler_cont_helpers::is_continuation (handler); } - void runTest() + void run() { - beginTestCase ("hooks"); - // Hooks called when using the raw handler { test_results r; @@ -276,13 +271,9 @@ public: expect (f.call); } } - - wrap_handler_handler_Tests() : UnitTest ("wrap_handler", "beast") - { - } }; -static wrap_handler_handler_Tests wrap_handler_handler_tests; +BEAST_DEFINE_TESTSUITE(wrap_handler,asio,beast); } } diff --git a/beast/chrono/Chrono.cpp b/beast/chrono/Chrono.cpp index 2dae1197..4306d7e8 100644 --- a/beast/chrono/Chrono.cpp +++ b/beast/chrono/Chrono.cpp @@ -22,10 +22,9 @@ #endif #include "../Config.h" -#include "../../modules/beast_core/beast_core.h" // for UnitTest -#include "impl/abstract_clock.cpp" #include "impl/chrono_io.cpp" -#include "impl/basic_seconds_clock.cpp" - #include "impl/RelativeTime.cpp" + +#include "tests/abstract_clock.test.cpp" +#include "tests/basic_seconds_clock.test.cpp" diff --git a/beast/chrono/abstract_clock.h b/beast/chrono/abstract_clock.h index 54c19444..d085825c 100644 --- a/beast/chrono/abstract_clock.h +++ b/beast/chrono/abstract_clock.h @@ -20,8 +20,6 @@ #ifndef BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED #define BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED -#include "chrono_io.h" - #include #include @@ -75,9 +73,10 @@ public: /** Returns the current time. */ virtual time_point now () const = 0; +#if 0 /** Convert the specified time point to a string. */ /** @{ */ - virtual std::string to_string (time_point const& tp) const = 0; + //virtual std::string to_string (time_point const& tp) const = 0; template std::string to_string ( @@ -87,6 +86,7 @@ public: std::chrono::time_point_cast (tp)); } /** @} */ +#endif /** Returning elapsed ticks since the epoch. */ rep elapsed () const @@ -123,6 +123,7 @@ struct abstract_clock_wrapper : public basic_abstract_clock_wrapper { // generic conversion displays the duration + /* std::string to_string (typename basic_abstract_clock_wrapper < TrivialClock, Duration>::time_point const& tp) const { @@ -130,6 +131,7 @@ struct abstract_clock_wrapper ss << tp.time_since_epoch(); return ss.str (); } + */ }; /* diff --git a/beast/chrono/impl/basic_seconds_clock.cpp b/beast/chrono/abstract_clock_io.h similarity index 69% rename from beast/chrono/impl/basic_seconds_clock.cpp rename to beast/chrono/abstract_clock_io.h index 6c12ac19..bd2ad993 100644 --- a/beast/chrono/impl/basic_seconds_clock.cpp +++ b/beast/chrono/abstract_clock_io.h @@ -17,30 +17,21 @@ */ //============================================================================== -#include "../basic_seconds_clock.h" +#ifndef BEAST_CHRONO_ABSTRACT_CLOCK_IO_H_INCLUDED +#define BEAST_CHRONO_ABSTRACT_CLOCK_IO_H_INCLUDED -#include "../../Config.h" -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "chrono_io.h" namespace beast { -class basic_seconds_clock_Tests : public UnitTest +template +std::basic_ostream & +operator<< (std::basic_ostream & os, + std::chrono::time_point , Duration> const& tp) { -public: - void runTest () - { - beginTestCase ("now"); - - basic_seconds_clock ::now (); - - pass (); - } - - basic_seconds_clock_Tests() : UnitTest("basic_seconds_clock", "beast") - { - } -}; - -static basic_seconds_clock_Tests basic_seconds_clock_tests; + return os << tp.time_since_epoch() << " since epoch"; +} } + +#endif diff --git a/beast/chrono/manual_clock.h b/beast/chrono/manual_clock.h index ad373725..8342c7d4 100644 --- a/beast/chrono/manual_clock.h +++ b/beast/chrono/manual_clock.h @@ -53,12 +53,14 @@ public: return m_now; } +#if 0 std::string to_string (time_point const& tp) const { std::stringstream ss; ss << tp.time_since_epoch() << " from start"; return ss.str (); } +#endif /** Set the current time of the manual clock. Precondition: diff --git a/beast/chrono/impl/abstract_clock.cpp b/beast/chrono/tests/abstract_clock.test.cpp similarity index 74% rename from beast/chrono/impl/abstract_clock.cpp rename to beast/chrono/tests/abstract_clock.test.cpp index 11cc5614..7cf098d1 100644 --- a/beast/chrono/impl/abstract_clock.cpp +++ b/beast/chrono/tests/abstract_clock.test.cpp @@ -18,16 +18,18 @@ //============================================================================== #include "../abstract_clock.h" +#include "../abstract_clock_io.h" #include "../manual_clock.h" -#include +#include "../../unit_test/suite.h" -#include #include +#include +#include namespace beast { -class abstract_clock_tests : public UnitTest +class abstract_clock_test : public unit_test::suite { public: void test (abstract_clock & c) @@ -40,10 +42,10 @@ public: std::stringstream ss; ss << - "t1= " << c.to_string (t1) << - ", t2= " << c.to_string (t2) << + "t1= " << t1.time_since_epoch() << + ", t2= " << t2.time_since_epoch() << ", elapsed= " << (t2 - t1); - logMessage (ss.str()); + log << ss.str(); } } @@ -54,45 +56,38 @@ public: std::stringstream ss; - ss << "now() = " << c.to_string (c.now ()) << std::endl; + ss << "now() = " << c.now () << std::endl; c.set (clock_type::time_point (std::chrono::seconds (1))); - ss << "now() = " << c.to_string (c.now ()) << std::endl; + ss << "now() = " << c.now () << std::endl; c.set (clock_type::time_point (std::chrono::seconds (2))); - ss << "now() = " << c.to_string (c.now ()) << std::endl; + ss << "now() = " << c.now () << std::endl; - logMessage (ss.str()); + log << ss.str(); } - void runTest () + void run () { - beginTestCase ("Syntax"); - - logMessage ("steady_clock"); + log << "steady_clock"; test (get_abstract_clock ()); - logMessage ("system_clock"); + log << "system_clock"; test (get_abstract_clock ()); - logMessage ("high_resolution_clock"); + log << "high_resolution_clock"; test (get_abstract_clock ()); - logMessage ("manual_clock"); + log << "manual_clock"; test_manual (); pass (); } - - abstract_clock_tests () - : UnitTest ("abstract_clock", "beast", runManual) - { - } }; -static abstract_clock_tests abstract_clock_tests_; +BEAST_DEFINE_TESTSUITE(abstract_clock,chrono,beast); } diff --git a/beast/smart_ptr/SmartPtr.cpp b/beast/chrono/tests/basic_seconds_clock.test.cpp similarity index 75% rename from beast/smart_ptr/SmartPtr.cpp rename to beast/chrono/tests/basic_seconds_clock.test.cpp index f7f12356..e8e9c58d 100644 --- a/beast/smart_ptr/SmartPtr.cpp +++ b/beast/chrono/tests/basic_seconds_clock.test.cpp @@ -17,15 +17,24 @@ */ //============================================================================== -#if BEAST_INCLUDE_BEASTCONFIG -#include "../../BeastConfig.h" -#endif +#include "../../unit_test/suite.h" -#include "../Config.h" +#include "../basic_seconds_clock.h" -#include "ContainerDeletePolicy.h" -#include "ScopedPointer.h" -#include "SharedObject.h" -#include "SharedPtr.h" +namespace beast { -#include "../../modules/beast_core/beast_core.h" // for UnitTest +class basic_seconds_clock_test : public unit_test::suite +{ +public: + void + run() + { + basic_seconds_clock < + std::chrono::steady_clock>::now (); + pass (); + } +}; + +BEAST_DEFINE_TESTSUITE(basic_seconds_clock,chrono,beast); + +} diff --git a/beast/container/Container.cpp b/beast/container/Container.cpp index 1cf70c77..c11ccfa8 100644 --- a/beast/container/Container.cpp +++ b/beast/container/Container.cpp @@ -21,7 +21,5 @@ #include "../../BeastConfig.h" #endif -#include "impl/aged_associative_container.cpp" - +#include "tests/aged_associative_container.test.cpp" #include "tests/buffer_view.test.cpp" - diff --git a/beast/container/buffer_view.h b/beast/container/buffer_view.h index f9e2ddee..1336b69e 100644 --- a/beast/container/buffer_view.h +++ b/beast/container/buffer_view.h @@ -22,6 +22,7 @@ #include "../Config.h" +#include #include "../cxx14/algorithm.h" // #include #include diff --git a/beast/container/detail/aged_ordered_container.h b/beast/container/detail/aged_ordered_container.h index dd151b31..dd77b28e 100644 --- a/beast/container/detail/aged_ordered_container.h +++ b/beast/container/detail/aged_ordered_container.h @@ -23,9 +23,6 @@ #include "aged_container_iterator.h" #include "aged_associative_container.h" -#include "../../cxx14/algorithm.h" -#include "../../cxx14/type_traits.h" - #include "../aged_container.h" #include "../../chrono/abstract_clock.h" @@ -34,10 +31,12 @@ #include #include +#include "../../cxx14/algorithm.h" // #include #include #include #include +#include "../../cxx14/type_traits.h" // #include namespace beast { diff --git a/beast/container/detail/aged_unordered_container.h b/beast/container/detail/aged_unordered_container.h index 2eac2783..5a1054fe 100644 --- a/beast/container/detail/aged_unordered_container.h +++ b/beast/container/detail/aged_unordered_container.h @@ -31,12 +31,12 @@ #include #include -#include "../../cxx14/algorithm.h" -#include "../../cxx14/type_traits.h" +#include "../../cxx14/algorithm.h" // #include #include #include #include +#include "../../cxx14/type_traits.h" // #include /* diff --git a/beast/container/impl/aged_associative_container.cpp b/beast/container/tests/aged_associative_container.test.cpp similarity index 86% rename from beast/container/impl/aged_associative_container.cpp rename to beast/container/tests/aged_associative_container.test.cpp index c1671ba7..7c410fcf 100644 --- a/beast/container/impl/aged_associative_container.cpp +++ b/beast/container/tests/aged_associative_container.test.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -#include "../../../modules/beast_core/beast_core.h" // for UnitTest #include "../../chrono/manual_clock.h" +#include "../../unit_test/suite.h" + #include "../aged_set.h" #include "../aged_map.h" #include "../aged_multiset.h" @@ -28,6 +29,9 @@ #include "../aged_unordered_multiset.h" #include "../aged_unordered_multimap.h" +#include +#include + #ifndef BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR # ifdef _MSC_VER # define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 0 @@ -46,7 +50,7 @@ namespace beast { -class aged_associative_container_TestsBase : public UnitTest +class aged_associative_container_test_base : public unit_test::suite { public: template @@ -392,56 +396,6 @@ public: //-------------------------------------------------------------------------- - // Compile time checks - // - void checkAliases () - { - typedef std::string Key; - typedef int T; - - static_assert (std::is_same < - aged_set , - detail::aged_ordered_container >::value, - "bad alias: aged_set"); - - static_assert (std::is_same < - aged_multiset , - detail::aged_ordered_container >::value, - "bad alias: aged_multiset"); - - static_assert (std::is_same < - aged_map , - detail::aged_ordered_container >::value, - "bad alias: aged_map"); - - static_assert (std::is_same < - aged_multimap , - detail::aged_ordered_container >::value, - "bad alias: aged_multimap"); - - static_assert (std::is_same < - aged_unordered_set , - detail::aged_unordered_container >::value, - "bad alias: aged_unordered_set"); - - static_assert (std::is_same < - aged_unordered_multiset , - detail::aged_unordered_container >::value, - "bad alias: aged_unordered_multiset"); - - static_assert (std::is_same < - aged_unordered_map , - detail::aged_unordered_container >::value, - "bad alias: aged_unordered_map"); - - static_assert (std::is_same < - aged_unordered_multimap , - detail::aged_unordered_container >::value, - "bad alias: aged_unordered_multimap"); - } - - //-------------------------------------------------------------------------- - template < class Container, class Values @@ -603,11 +557,6 @@ public: template void testMaybeUnordered(); - - aged_associative_container_TestsBase () : UnitTest ( - "aged_associative_container", "beast") - { - } }; //------------------------------------------------------------------------------ @@ -620,7 +569,7 @@ template < > typename std::enable_if < Container::is_map::value && ! Container::is_multi::value>::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkMapContents (Container& c, Values const& v) { if (v.empty()) @@ -651,7 +600,7 @@ template < > typename std::enable_if < std::remove_reference ::type::is_unordered::value>::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkUnorderedContentsRefRef (C&& c, Values const& v) { typedef typename std::remove_reference ::type Cont; @@ -685,7 +634,7 @@ checkUnorderedContentsRefRef (C&& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkContentsRefRef (C&& c, Values const& v) { typedef typename std::remove_reference ::type Cont; @@ -715,7 +664,7 @@ checkContentsRefRef (C&& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkContents (Cont& c, Values const& v) { checkContentsRefRef (c, v); @@ -725,7 +674,7 @@ checkContents (Cont& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkContents (Cont& c) { typedef TestTraits < @@ -746,7 +695,7 @@ checkContents (Cont& c) // ordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructEmpty () { typedef TestTraits Traits; @@ -760,7 +709,8 @@ testConstructEmpty () typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; - beginTestCase (Traits::name() + " empty"); + //testcase (Traits::name() + " empty"); + testcase ("empty"); { typename Traits::template Cont c ( @@ -790,7 +740,7 @@ testConstructEmpty () // unordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructEmpty () { typedef TestTraits Traits; @@ -806,8 +756,8 @@ testConstructEmpty () typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; - beginTestCase (Traits::name() + " empty"); - + //testcase (Traits::name() + " empty"); + testcase ("empty"); { typename Traits::template Cont c ( clock); @@ -860,7 +810,7 @@ testConstructEmpty () // ordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructRange () { typedef TestTraits Traits; @@ -875,7 +825,8 @@ testConstructRange () typename Traits::Clock clock; auto const v (Traits::values()); - beginTestCase (Traits::name() + " range"); + //testcase (Traits::name() + " range"); + testcase ("range"); { typename Traits::template Cont c ( @@ -922,7 +873,7 @@ testConstructRange () // unordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructRange () { typedef TestTraits Traits; @@ -939,7 +890,8 @@ testConstructRange () typename Traits::Clock clock; auto const v (Traits::values()); - beginTestCase (Traits::name() + " range"); + //testcase (Traits::name() + " range"); + testcase ("range"); { typename Traits::template Cont c ( @@ -1001,7 +953,7 @@ testConstructRange () // ordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructInitList () { typedef TestTraits Traits; @@ -1015,7 +967,8 @@ testConstructInitList () typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; - beginTestCase (Traits::name() + " init-list"); + //testcase (Traits::name() + " init-list"); + testcase ("init-list"); // VFALCO TODO @@ -1025,7 +978,7 @@ testConstructInitList () // unordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testConstructInitList () { typedef TestTraits Traits; @@ -1041,7 +994,9 @@ testConstructInitList () typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; - beginTestCase (Traits::name() + " init-list"); + //testcase (Traits::name() + " init-list"); + testcase ("init-list"); + // VFALCO TODO pass(); } @@ -1054,7 +1009,7 @@ testConstructInitList () template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testCopyMove () { typedef TestTraits Traits; @@ -1063,7 +1018,8 @@ testCopyMove () typename Traits::Clock clock; auto const v (Traits::values()); - beginTestCase (Traits::name() + " copy/move"); + //testcase (Traits::name() + " copy/move"); + testcase ("copy/move"); // copy @@ -1136,7 +1092,7 @@ testCopyMove () template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkInsertCopy (Container& c, Values const& v) { for (auto const& e : v) @@ -1146,7 +1102,7 @@ checkInsertCopy (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkInsertMove (Container& c, Values const& v) { Values v2 (v); @@ -1157,7 +1113,7 @@ checkInsertMove (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkInsertHintCopy (Container& c, Values const& v) { for (auto const& e : v) @@ -1167,7 +1123,7 @@ checkInsertHintCopy (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkInsertHintMove (Container& c, Values const& v) { Values v2 (v); @@ -1178,7 +1134,7 @@ checkInsertHintMove (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkEmplace (Container& c, Values const& v) { for (auto const& e : v) @@ -1188,7 +1144,7 @@ checkEmplace (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: checkEmplaceHint (Container& c, Values const& v) { for (auto const& e : v) @@ -1198,7 +1154,7 @@ checkEmplaceHint (Container& c, Values const& v) template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testModifiers() { typedef TestTraits Traits; @@ -1206,7 +1162,8 @@ testModifiers() auto const v (Traits::values()); auto const l (make_list (v)); - beginTestCase (Traits::name() + " modify"); + //testcase (Traits::name() + " modify"); + testcase ("modify"); { typename Traits::template Cont <> c (clock); @@ -1257,7 +1214,7 @@ testModifiers() template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testChronological () { typedef TestTraits Traits; @@ -1265,7 +1222,8 @@ testChronological () typename Traits::Clock clock; auto const v (Traits::values()); - beginTestCase (Traits::name() + " chronological"); + //testcase (Traits::name() + " chronological"); + testcase ("chronological"); typename Traits::template Cont <> c ( v.begin(), v.end(), clock); @@ -1297,14 +1255,15 @@ testChronological () // map, unordered_map template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testArrayCreate() { typedef TestTraits Traits; typename Traits::Clock clock; auto v (Traits::values()); - beginTestCase (Traits::name() + " array create"); + //testcase (Traits::name() + " array create"); + testcase ("array create"); { // Copy construct key @@ -1332,7 +1291,7 @@ testArrayCreate() // ordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testCompare () { typedef TestTraits Traits; @@ -1340,7 +1299,8 @@ testCompare () typename Traits::Clock clock; auto const v (Traits::values()); - beginTestCase (Traits::name() + " array create"); + //testcase (Traits::name() + " array create"); + testcase ("array create"); typename Traits::template Cont <> c1 ( v.begin(), v.end(), clock); @@ -1366,13 +1326,14 @@ testCompare () // ordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testObservers() { typedef TestTraits Traits; typename Traits::Clock clock; - beginTestCase (Traits::name() + " observers"); + //testcase (Traits::name() + " observers"); + testcase ("observers"); typename Traits::template Cont <> c (clock); c.key_comp(); @@ -1384,13 +1345,14 @@ testObservers() // unordered template typename std::enable_if ::type -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testObservers() { typedef TestTraits Traits; typename Traits::Clock clock; - beginTestCase (Traits::name() + " observers"); + //testcase (Traits::name() + " observers"); + testcase ("observers"); typename Traits::template Cont <> c (clock); c.hash_function(); @@ -1407,7 +1369,7 @@ testObservers() template void -aged_associative_container_TestsBase:: +aged_associative_container_test_base:: testMaybeUnorderedMultiMap () { typedef TestTraits Traits; @@ -1423,38 +1385,133 @@ testMaybeUnorderedMultiMap () testObservers (); } -template -void -aged_associative_container_TestsBase:: -testMaybeUnorderedMulti() -{ - testMaybeUnorderedMultiMap (); - testMaybeUnorderedMultiMap (); -} - -template -void -aged_associative_container_TestsBase:: -testMaybeUnordered() -{ - testMaybeUnorderedMulti (); - testMaybeUnorderedMulti (); -} - //------------------------------------------------------------------------------ -class aged_associative_container_Tests : - public aged_associative_container_TestsBase +class aged_set_test : public aged_associative_container_test_base { public: - void runTest () + // Compile time checks + + typedef std::string Key; + typedef int T; + + static_assert (std::is_same < + aged_set , + detail::aged_ordered_container >::value, + "bad alias: aged_set"); + + static_assert (std::is_same < + aged_multiset , + detail::aged_ordered_container >::value, + "bad alias: aged_multiset"); + + static_assert (std::is_same < + aged_map , + detail::aged_ordered_container >::value, + "bad alias: aged_map"); + + static_assert (std::is_same < + aged_multimap , + detail::aged_ordered_container >::value, + "bad alias: aged_multimap"); + + static_assert (std::is_same < + aged_unordered_set , + detail::aged_unordered_container >::value, + "bad alias: aged_unordered_set"); + + static_assert (std::is_same < + aged_unordered_multiset , + detail::aged_unordered_container >::value, + "bad alias: aged_unordered_multiset"); + + static_assert (std::is_same < + aged_unordered_map , + detail::aged_unordered_container >::value, + "bad alias: aged_unordered_map"); + + static_assert (std::is_same < + aged_unordered_multimap , + detail::aged_unordered_container >::value, + "bad alias: aged_unordered_multimap"); + + void run () { - checkAliases (); - testMaybeUnordered (); - testMaybeUnordered (); + testMaybeUnorderedMultiMap (); } }; -static aged_associative_container_Tests aged_associative_container_tests; +class aged_map_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +class aged_multiset_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +class aged_multimap_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + + +class aged_unordered_set_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +class aged_unordered_map_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +class aged_unordered_multiset_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +class aged_unordered_multimap_test : public aged_associative_container_test_base +{ +public: + void run () + { + testMaybeUnorderedMultiMap (); + } +}; + +BEAST_DEFINE_TESTSUITE(aged_set,container,beast); +BEAST_DEFINE_TESTSUITE(aged_map,container,beast); +BEAST_DEFINE_TESTSUITE(aged_multiset,container,beast); +BEAST_DEFINE_TESTSUITE(aged_multimap,container,beast); +BEAST_DEFINE_TESTSUITE(aged_unordered_set,container,beast); +BEAST_DEFINE_TESTSUITE(aged_unordered_map,container,beast); +BEAST_DEFINE_TESTSUITE(aged_unordered_multiset,container,beast); +BEAST_DEFINE_TESTSUITE(aged_unordered_multimap,container,beast); } diff --git a/beast/container/tests/buffer_view.test.cpp b/beast/container/tests/buffer_view.test.cpp index 3bc21728..743430cb 100644 --- a/beast/container/tests/buffer_view.test.cpp +++ b/beast/container/tests/buffer_view.test.cpp @@ -17,14 +17,15 @@ */ //============================================================================== -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" + #include "../buffer_view.h" #include "../../cxx14/algorithm.h" // namespace beast { -class buffer_view_Tests : public UnitTest +class buffer_view_test : public unit_test::suite { public: // Returns `true` if the iterator distance matches the size @@ -153,7 +154,7 @@ public: // Test empty containers void testEmpty() { - beginTestCase ("empty"); + testcase ("empty"); buffer_view v1; checkEmpty (v1); @@ -239,11 +240,11 @@ public: void testConstruct() { - beginTestCase ("std::vector "); + testcase ("std::vector "); testConstruct ( std::vector ({'h', 'e', 'l', 'l', 'o'})); - beginTestCase ("std::string "); + testcase ("std::string "); testConstruct ( std::basic_string ("hello")); } @@ -252,7 +253,7 @@ public: void testCoerce() { - beginTestCase ("coerce"); + testcase ("coerce"); std::string const s ("hello"); const_buffer_view v (s); @@ -264,7 +265,7 @@ public: void testAssign() { - beginTestCase ("testAssign"); + testcase ("testAssign"); std::vector v1({1, 2, 3}); buffer_view r1(v1); std::vector v2({4, 5, 6, 7}); @@ -305,19 +306,15 @@ public: static_assert (std::is_nothrow_move_assignable < buffer_view >::value, ""); - void runTest() + void run() { testEmpty(); testConstruct(); testCoerce(); testAssign(); } - - buffer_view_Tests() : UnitTest ("buffer_view", "beast") - { - } }; -static buffer_view_Tests buffer_view_tests; +BEAST_DEFINE_TESTSUITE(buffer_view,container,beast); } diff --git a/beast/crypto/Crypto.cpp b/beast/crypto/Crypto.cpp index f4c1eb1c..327df57d 100644 --- a/beast/crypto/Crypto.cpp +++ b/beast/crypto/Crypto.cpp @@ -21,9 +21,9 @@ #include "../../BeastConfig.h" #endif -#include "../../modules/beast_core/beast_core.h" // for UnitTest - -#include "impl/BinaryEncoding.cpp" #include "impl/MurmurHash.cpp" #include "impl/Sha256.cpp" #include "impl/UnsignedInteger.cpp" + +#include "tests/BinaryEncoding.test.cpp" +#include "tests/UnsignedInteger.test.cpp" diff --git a/beast/crypto/UnsignedInteger.h b/beast/crypto/UnsignedInteger.h index b276e128..a810b60b 100644 --- a/beast/crypto/UnsignedInteger.h +++ b/beast/crypto/UnsignedInteger.h @@ -23,6 +23,8 @@ #include "UnsignedIntegerCalc.h" #include "MurmurHash.h" +#include "../../modules/beast_core/beast_core.h" // FIX ASAP + #include #include diff --git a/beast/crypto/UnsignedIntegerCalc.h b/beast/crypto/UnsignedIntegerCalc.h index ef1d4812..2f480493 100644 --- a/beast/crypto/UnsignedIntegerCalc.h +++ b/beast/crypto/UnsignedIntegerCalc.h @@ -20,6 +20,7 @@ #ifndef BEAST_CRYPTO_UNSIGNEDINTEGERCALC_H_INCLUDED #define BEAST_CRYPTO_UNSIGNEDINTEGERCALC_H_INCLUDED +#include #include namespace beast { @@ -155,7 +156,7 @@ public: */ UnsignedIntegerCalc& operator= (UnsignedIntegerCalc const& other) { - bassert (other.size() <= size()); + assert (other.size() <= size()); size_type n (size()); UInt* dest (m_values + size()); for (; n-- > other.size();) @@ -335,7 +336,7 @@ public: } *lhs++ = UInt (part); } - bassert (carry == 0); // overflow + assert (carry == 0); // overflow return *this; } @@ -359,7 +360,7 @@ public: carry = part >> numBits; *lhs = UInt (part & maxUInt); } - bassert (carry == 0); // overflow + assert (carry == 0); // overflow return *this; } diff --git a/beast/crypto/impl/UnsignedInteger.cpp b/beast/crypto/impl/UnsignedInteger.cpp index 2cd24625..a35bb2d5 100644 --- a/beast/crypto/impl/UnsignedInteger.cpp +++ b/beast/crypto/impl/UnsignedInteger.cpp @@ -5,8 +5,7 @@ Portions are Copyright (c) 2013 the authors listed at the following URL, and/or the authors of referenced articles or incorporated external code: - http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)?action=history&offset=20100923155004 - + http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C) Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. @@ -23,6 +22,8 @@ #include "../UnsignedInteger.h" +#include "../../unit_test/suite.h" + namespace beast { namespace multiprecsion { @@ -31,7 +32,7 @@ namespace multiprecsion { /* Copyright (c) 2013 the authors listed at the following URL, and/or the authors of referenced articles or incorporated external code: - http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C)?action=history&offset=20100923155004 + http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -342,63 +343,4 @@ char* integer_to_string(integer x) { } -//------------------------------------------------------------------------------ - -class UnsignedIntegerTests : public UnitTest -{ -public: - UnsignedIntegerTests () : UnitTest ("UnsignedInteger", "beast") - { - } - - template - void runTest () - { - typedef UnsignedInteger UInt; - - String s; - - s << "Bytes=" << String(Bytes); - - beginTestCase (s); - - UInt zero; - zero.fill (0); - expect (zero.isZero (), "should be zero"); - expect (! zero.isNotZero (), "sould not be non-zero"); - - UInt one (UInt::createFromInteger (1U)); - expect (one == UInt::createFromInteger (1U), "should be equal"); - - expect (! one.isZero (), "should not be zero"); - expect (one.isNotZero (), "sould be non-zero"); - - expect (zero < one, "should be less"); - expect (one > zero, "should be greater"); - expect (zero >= zero, "should be less than or equal"); - expect (one <= one, "should be less than or equal"); - - expect (zero == zero, "should be equal"); - expect (zero != one, "should not be equal"); - - expect (zero == UInt::createFromInteger (0U), "should be zero"); - expect (one == UInt::createFromInteger (1U), "should be one"); - expect (one != UInt::createFromInteger (2U), "should not be two"); - - UInt largest = UInt::createFilled (0xff); - - expect (largest > zero && largest > one, "should be greater"); - } - - void runTest() - { - runTest <16> (); - runTest <33> (); - } - -private: -}; - -static UnsignedIntegerTests unsignedIntegerTests; - } diff --git a/beast/crypto/impl/BinaryEncoding.cpp b/beast/crypto/tests/BinaryEncoding.test.cpp similarity index 93% rename from beast/crypto/impl/BinaryEncoding.cpp rename to beast/crypto/tests/BinaryEncoding.test.cpp index dfdca1bc..f66185f5 100644 --- a/beast/crypto/impl/BinaryEncoding.cpp +++ b/beast/crypto/tests/BinaryEncoding.test.cpp @@ -20,6 +20,8 @@ #include "../BinaryEncoding.h" #include "../UnsignedInteger.h" +#include "../../unit_test/suite.h" + #include #include @@ -276,19 +278,20 @@ public: //------------------------------------------------------------------------------ -class BinaryEncodingTests : public UnitTest +class BinaryEncoding_test : public unit_test::suite { public: // This is a baseline for the other tests template void testBase16 () { - beginTestCase ("base16"); + Random r; + testcase ("base16"); for (int i = 0; i < 50; ++i) { typedef UnsignedInteger UInt; UInt v0; - random().fillBitsRandomly (v0.begin(), UInt::size); + r.fillBitsRandomly (v0.begin(), UInt::size); std::string const good (HexEncoding::encode (v0)); UInt v1; @@ -299,8 +302,8 @@ public: Base16Conversion c; std::string const check (BinaryEncoding::encode (v0, c)); - if (! expect (good == check)) - logMessage (String ("expected ") + good + " but got " + check); + expect (good == check, + std::string ("expected ") + good + " but got " + check); } } } @@ -313,7 +316,8 @@ public: typedef UnsignedInteger UInt; UInt v1 (vin.c_str()); std::string const s1 (BinaryEncoding::encode (v1, c)); - logMessage (vout + " to " + s1); + log << + vout + " to " + s1; expect (vout == s1); UInt v2; @@ -321,14 +325,14 @@ public: if (expect (success)) { std::string const s2 (BinaryEncoding::encode (v2, c)); - logMessage (vin + " to " + s2); - //expect (vin == v2); + log << + vin + " to " + s2; } } void testBase64 () { - beginTestCase ("Base64"); + testcase ("Base64"); // input (uint) std::string const vin [] = { @@ -354,12 +358,16 @@ public: { typedef UnsignedInteger UInt; - beginTestCase (String (c.name()) + " <" + String::fromNumber (Bytes) + ">"); + std::stringstream ss; + ss << + c.name() << " <" << Bytes << ">"; + testcase (ss.str()); + Random r; for (int i = 0; i < 50; ++i) { UInt v1; - random().fillBitsRandomly (v1.begin(), UInt::size); + r.fillBitsRandomly (v1.begin(), UInt::size); std::string const s1 (BinaryEncoding::encode (v1, c)); UInt v2; @@ -369,7 +377,7 @@ public: } } - void runTest () + void run () { testBase16 <10> (); @@ -394,12 +402,8 @@ public: testEncode (); #endif } - - BinaryEncodingTests () : UnitTest ("BinaryEncoding", "beast", runManual) - { - } }; -static BinaryEncodingTests BinaryEncodingTests; +BEAST_DEFINE_TESTSUITE_MANUAL(BinaryEncoding,crypto,beast); } diff --git a/beast/crypto/tests/UnsignedInteger.test.cpp b/beast/crypto/tests/UnsignedInteger.test.cpp new file mode 100644 index 00000000..2263e61e --- /dev/null +++ b/beast/crypto/tests/UnsignedInteger.test.cpp @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions are Copyright (c) 2013 the authors listed at the following URL, + and/or the authors of referenced articles or incorporated external code: + http://en.literateprograms.org/Arbitrary-precision_integer_arithmetic_(C) + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../UnsignedInteger.h" + +#include "../../unit_test/suite.h" + +namespace beast { + +class UnsignedInteger_test : public unit_test::suite +{ +public: + template + void test () + { + typedef UnsignedInteger UInt; + + std::stringstream ss; + ss << + "bytes=" << Bytes; + testcase (ss.str()); + + UInt zero; + zero.fill (0); + expect (zero.isZero (), "should be zero"); + expect (! zero.isNotZero (), "sould not be non-zero"); + + UInt one (UInt::createFromInteger (1U)); + expect (one == UInt::createFromInteger (1U), "should be equal"); + + expect (! one.isZero (), "should not be zero"); + expect (one.isNotZero (), "sould be non-zero"); + + expect (zero < one, "should be less"); + expect (one > zero, "should be greater"); + expect (zero >= zero, "should be less than or equal"); + expect (one <= one, "should be less than or equal"); + + expect (zero == zero, "should be equal"); + expect (zero != one, "should not be equal"); + + expect (zero == UInt::createFromInteger (0U), "should be zero"); + expect (one == UInt::createFromInteger (1U), "should be one"); + expect (one != UInt::createFromInteger (2U), "should not be two"); + + UInt largest = UInt::createFilled (0xff); + + expect (largest > zero && largest > one, "should be greater"); + } + + void run() + { + test <16> (); + test <33> (); + } + +private: +}; + +BEAST_DEFINE_TESTSUITE(UnsignedInteger,crypto,beast); + +} diff --git a/beast/cxx14/tests/integer_sequence.test.cpp b/beast/cxx14/tests/integer_sequence.test.cpp index 5846cfe6..f7360baa 100644 --- a/beast/cxx14/tests/integer_sequence.test.cpp +++ b/beast/cxx14/tests/integer_sequence.test.cpp @@ -23,12 +23,12 @@ #include "../utility.h" -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" namespace beast { namespace asio { -class integer_sequence_Tests : public UnitTest +class integer_sequence_test : public unit_test::suite { public: template @@ -41,10 +41,8 @@ public: return std::make_tuple (std::get (t)...); } - void runTest() + void run() { - beginTestCase ("call"); - // Code from // http://llvm.org/svn/llvm-project/libcxx/trunk/test/utilities/intseq/intseq.general/integer_seq.pass.cpp @@ -103,13 +101,9 @@ public: expect ( tsizemix == std::make_tuple ( 11, 11, 12, 13, 15 )); pass(); } - - integer_sequence_Tests() : UnitTest ("integer_sequence", "beast") - { - } }; -static integer_sequence_Tests integer_sequence_tests; +BEAST_DEFINE_TESTSUITE(integer_sequence,cxx14,beast); } } diff --git a/beast/http/HTTP.cpp b/beast/http/HTTP.cpp index 25a22864..c8c010e9 100644 --- a/beast/http/HTTP.cpp +++ b/beast/http/HTTP.cpp @@ -25,3 +25,5 @@ #include "impl/ParsedURL.cpp" #include "impl/joyent_parser.cpp" #include "impl/raw_parser.cpp" + +#include "tests/ParsedURL.test.cpp" diff --git a/beast/http/impl/ParsedURL.cpp b/beast/http/impl/ParsedURL.cpp index d1b97dd1..f889f398 100644 --- a/beast/http/impl/ParsedURL.cpp +++ b/beast/http/impl/ParsedURL.cpp @@ -18,11 +18,12 @@ //============================================================================== #include "../ParsedURL.h" - -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../strings/String.h" #include "joyent_parser.h" +#include + namespace beast { ParsedURL::ParsedURL () @@ -146,35 +147,4 @@ URL ParsedURL::url () const return m_url; } -//------------------------------------------------------------------------------ - -class ParsedURLTests : public UnitTest -{ -public: - void checkURL (String const& url) - { - ParsedURL result (url); - expect (result.error () == 0); - expect (result.url ().toString () == url); - } - - void testURL () - { - beginTestCase ("parse URL"); - - checkURL ("http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html"); - } - - void runTest () - { - testURL (); - } - - ParsedURLTests () : UnitTest ("ParsedURL", "beast", runManual) - { - } -}; - -static ParsedURLTests parsedURLTests; - } diff --git a/beast/http/tests/ParsedURL.test.cpp b/beast/http/tests/ParsedURL.test.cpp new file mode 100644 index 00000000..ca236210 --- /dev/null +++ b/beast/http/tests/ParsedURL.test.cpp @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../ParsedURL.h" + +#include "../../unit_test/suite.h" + +#include "../impl/joyent_parser.h" + +namespace beast { + +class ParsedURL_test : public unit_test::suite +{ +public: + void checkURL (String const& url) + { + ParsedURL result (url); + expect (result.error () == 0); + expect (result.url ().toString () == url); + } + + void testURL () + { + checkURL ("http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html"); + } + + void run () + { + testURL (); + } +}; + +BEAST_DEFINE_TESTSUITE(ParsedURL,http,beast); + +} diff --git a/beast/insight/BaseImpl.h b/beast/insight/BaseImpl.h index 86953efe..6c3d7821 100644 --- a/beast/insight/BaseImpl.h +++ b/beast/insight/BaseImpl.h @@ -20,6 +20,9 @@ #ifndef BEAST_INSIGHT_BASEIMPL_H_INCLUDED #define BEAST_INSIGHT_BASEIMPL_H_INCLUDED +#include +#include +#include #include namespace beast { diff --git a/beast/insight/Collector.h b/beast/insight/Collector.h index 74bb8998..6325ad37 100644 --- a/beast/insight/Collector.h +++ b/beast/insight/Collector.h @@ -20,14 +20,14 @@ #ifndef BEAST_INSIGHT_COLLECTOR_H_INCLUDED #define BEAST_INSIGHT_COLLECTOR_H_INCLUDED -#include - #include "Counter.h" #include "Event.h" #include "Gauge.h" #include "Hook.h" #include "Meter.h" +#include + namespace beast { namespace insight { diff --git a/beast/insight/Counter.h b/beast/insight/Counter.h index 9f27128b..2da42226 100644 --- a/beast/insight/Counter.h +++ b/beast/insight/Counter.h @@ -20,11 +20,11 @@ #ifndef BEAST_INSIGHT_COUNTER_H_INCLUDED #define BEAST_INSIGHT_COUNTER_H_INCLUDED -#include - #include "Base.h" #include "CounterImpl.h" +#include + namespace beast { namespace insight { @@ -60,32 +60,58 @@ public: /** Increment the counter. */ /** @{ */ - void increment (value_type amount) const + void + increment (value_type amount) const { if (m_impl) m_impl->increment (amount); } - Counter const& operator+= (value_type amount) const - { increment (amount); return *this; } + Counter const& + operator+= (value_type amount) const + { + increment (amount); + return *this; + } - Counter const& operator-= (value_type amount) const - { increment (-amount); return *this; } + Counter const& + operator-= (value_type amount) const + { + increment (-amount); + return *this; + } - Counter const& operator++ () const - { increment (1); return *this; } + Counter const& + operator++ () const + { + increment (1); + return *this; + } - Counter const& operator++ (int) const - { increment (1); return *this; } + Counter const& + operator++ (int) const + { + increment (1); + return *this; + } - Counter const& operator-- () const - { increment (-1); return *this; } + Counter const& + operator-- () const + { + increment (-1); + return *this; + } - Counter const& operator-- (int) const - { increment (-1); return *this; } + Counter const& + operator-- (int) const + { + increment (-1); + return *this; + } /** @} */ - std::shared_ptr const& impl () const + std::shared_ptr const& + impl () const { return m_impl; } diff --git a/beast/insight/CounterImpl.h b/beast/insight/CounterImpl.h index c1a0254b..61f15050 100644 --- a/beast/insight/CounterImpl.h +++ b/beast/insight/CounterImpl.h @@ -20,8 +20,6 @@ #ifndef BEAST_INSIGHT_COUNTERIMPL_H_INCLUDED #define BEAST_INSIGHT_COUNTERIMPL_H_INCLUDED -#include - #include "BaseImpl.h" namespace beast { @@ -34,7 +32,7 @@ class CounterImpl , public BaseImpl { public: - typedef int64 value_type; + typedef std::int64_t value_type; virtual ~CounterImpl () = 0; virtual void increment (value_type amount) = 0; diff --git a/beast/insight/Event.h b/beast/insight/Event.h index 0bcf6df5..52189a50 100644 --- a/beast/insight/Event.h +++ b/beast/insight/Event.h @@ -20,14 +20,14 @@ #ifndef BEAST_INSIGHT_EVENT_H_INCLUDED #define BEAST_INSIGHT_EVENT_H_INCLUDED -#include -#include - #include "Base.h" #include "EventImpl.h" #include "../chrono/chrono_util.h" +#include +#include + namespace beast { namespace insight { @@ -62,7 +62,8 @@ public: /** Push an event notification. */ template - void notify (std::chrono::duration const& value) const + void + notify (std::chrono::duration const& value) const { if (m_impl) m_impl->notify (ceil (value)); diff --git a/beast/insight/EventImpl.h b/beast/insight/EventImpl.h index d2d684e5..4113d59d 100644 --- a/beast/insight/EventImpl.h +++ b/beast/insight/EventImpl.h @@ -20,8 +20,6 @@ #ifndef BEAST_INSIGHT_EVENTIMPL_H_INCLUDED #define BEAST_INSIGHT_EVENTIMPL_H_INCLUDED -#include - #include "BaseImpl.h" namespace beast { diff --git a/beast/insight/Gauge.h b/beast/insight/Gauge.h index 22875214..d02a68d3 100644 --- a/beast/insight/Gauge.h +++ b/beast/insight/Gauge.h @@ -20,11 +20,11 @@ #ifndef BEAST_INSIGHT_GAUGE_H_INCLUDED #define BEAST_INSIGHT_GAUGE_H_INCLUDED -#include - #include "Base.h" #include "GaugeImpl.h" +#include + namespace beast { namespace insight { @@ -40,7 +40,7 @@ namespace insight { class Gauge : public Base { public: - typedef GaugeImpl::value_type value_type; + typedef GaugeImpl::value_type value_type; typedef GaugeImpl::difference_type difference_type; /** Create a null metric. @@ -84,26 +84,51 @@ public: m_impl->increment (amount); } - Gauge const& operator+= (difference_type amount) const - { increment (amount); return *this; } + Gauge const& + operator+= (difference_type amount) const + { + increment (amount); + return *this; + } - Gauge const& operator-= (difference_type amount) const - { increment (-amount); return *this; } + Gauge const& + operator-= (difference_type amount) const + { + increment (-amount); + return *this; + } - Gauge const& operator++ () const - { increment (1); return *this; } + Gauge const& + operator++ () const + { + increment (1); + return *this; + } - Gauge const& operator++ (int) const - { increment (1); return *this; } + Gauge const& + operator++ (int) const + { + increment (1); + return *this; + } - Gauge const& operator-- () const - { increment (-1); return *this; } + Gauge const& + operator-- () const + { + increment (-1); + return *this; + } - Gauge const& operator-- (int) const - { increment (-1); return *this; } + Gauge const& + operator-- (int) const + { + increment (-1); + return *this; + } /** @} */ - std::shared_ptr const& impl () const + std::shared_ptr const& + impl () const { return m_impl; } diff --git a/beast/insight/GaugeImpl.h b/beast/insight/GaugeImpl.h index 1f5794e9..081c534b 100644 --- a/beast/insight/GaugeImpl.h +++ b/beast/insight/GaugeImpl.h @@ -20,8 +20,6 @@ #ifndef BEAST_INSIGHT_GAUGEIMPL_H_INCLUDED #define BEAST_INSIGHT_GAUGEIMPL_H_INCLUDED -#include - #include "BaseImpl.h" namespace beast { @@ -34,8 +32,8 @@ class GaugeImpl , public BaseImpl { public: - typedef uint64 value_type; - typedef int64 difference_type; + typedef std::uint64_t value_type; + typedef std::int64_t difference_type; virtual ~GaugeImpl () = 0; virtual void set (value_type value) = 0; diff --git a/beast/insight/Group.h b/beast/insight/Group.h index 27347291..f47c72a2 100644 --- a/beast/insight/Group.h +++ b/beast/insight/Group.h @@ -20,10 +20,11 @@ #ifndef BEAST_INSIGHT_GROUP_H_INCLUDED #define BEAST_INSIGHT_GROUP_H_INCLUDED -#include - #include "Collector.h" +#include +#include + namespace beast { namespace insight { diff --git a/beast/insight/Groups.h b/beast/insight/Groups.h index 61389382..be4f2976 100644 --- a/beast/insight/Groups.h +++ b/beast/insight/Groups.h @@ -20,12 +20,12 @@ #ifndef BEAST_INSIGHT_GROUPS_H_INCLUDED #define BEAST_INSIGHT_GROUPS_H_INCLUDED -#include -#include - #include "Collector.h" #include "Group.h" +#include +#include + namespace beast { namespace insight { @@ -37,9 +37,12 @@ public: /** Find or create a new collector with a given name. */ /** @{ */ - virtual Group::ptr const& get (std::string const& name) = 0; + virtual + Group::ptr const& + get (std::string const& name) = 0; - Group::ptr const& operator[] (std::string const& name) + Group::ptr const& + operator[] (std::string const& name) { return get (name); } diff --git a/beast/insight/Hook.h b/beast/insight/Hook.h index 783477a4..696fe681 100644 --- a/beast/insight/Hook.h +++ b/beast/insight/Hook.h @@ -20,11 +20,11 @@ #ifndef BEAST_INSIGHT_HOOK_H_INCLUDED #define BEAST_INSIGHT_HOOK_H_INCLUDED -#include - #include "Base.h" #include "HookImpl.h" +#include + namespace beast { namespace insight { diff --git a/beast/insight/HookImpl.h b/beast/insight/HookImpl.h index 84b2b3e7..78ecb0e4 100644 --- a/beast/insight/HookImpl.h +++ b/beast/insight/HookImpl.h @@ -20,9 +20,6 @@ #ifndef BEAST_INSIGHT_HOOKIMPL_H_INCLUDED #define BEAST_INSIGHT_HOOKIMPL_H_INCLUDED -#include -#include - #include "BaseImpl.h" namespace beast { diff --git a/beast/insight/Insight.cpp b/beast/insight/Insight.cpp index 20936478..5ab9a4df 100644 --- a/beast/insight/Insight.cpp +++ b/beast/insight/Insight.cpp @@ -23,8 +23,6 @@ #include "../Config.h" -#include "../../modules/beast_core/beast_core.h" // for UnitTest - #include "../Insight.h" #include "impl/Collector.cpp" diff --git a/beast/insight/MeterImpl.h b/beast/insight/MeterImpl.h index 21dae58a..301f86e6 100644 --- a/beast/insight/MeterImpl.h +++ b/beast/insight/MeterImpl.h @@ -20,8 +20,6 @@ #ifndef BEAST_INSIGHT_METERIMPL_H_INCLUDED #define BEAST_INSIGHT_METERIMPL_H_INCLUDED -#include - #include "BaseImpl.h" namespace beast { @@ -34,7 +32,7 @@ class MeterImpl , public BaseImpl { public: - typedef uint64 value_type; + typedef std::uint64_t value_type; virtual ~MeterImpl () = 0; virtual void increment (value_type amount) = 0; diff --git a/beast/insight/StatsDCollector.h b/beast/insight/StatsDCollector.h index b5efbbc8..ea5bf61e 100644 --- a/beast/insight/StatsDCollector.h +++ b/beast/insight/StatsDCollector.h @@ -22,6 +22,7 @@ #include "Collector.h" +#include "../utility/Journal.h" #include "../net/IPEndpoint.h" namespace beast { @@ -39,7 +40,9 @@ public: @param prefix A string pre-pended before each metric name. @param journal Destination for logging output. */ - static std::shared_ptr New (IP::Endpoint const& address, + static + std::shared_ptr + New (IP::Endpoint const& address, std::string const& prefix, Journal journal); }; diff --git a/beast/insight/impl/StatsDCollector.cpp b/beast/insight/impl/StatsDCollector.cpp index 85271097..cc547693 100644 --- a/beast/insight/impl/StatsDCollector.cpp +++ b/beast/insight/impl/StatsDCollector.cpp @@ -18,19 +18,21 @@ //============================================================================== #include "../../asio/IPAddressConversion.h" +#include "../../intrusive/List.h" #include "../../threads/SharedData.h" -#include -#include -#include -#include -#include - -#include +#include #include #include #include +#include +#include +#include +#include +#include +#include + #ifndef BEAST_STATSDCOLLECTOR_TRACING_ENABLED #define BEAST_STATSDCOLLECTOR_TRACING_ENABLED 0 #endif @@ -364,7 +366,7 @@ public: { std::string const& buffer (*iter); std::size_t const length (buffer.size ()); - check_precondition (! buffer.empty ()); + assert (! buffer.empty ()); if (! buffers.empty () && (size + length) > max_packet_size) { #if BEAST_STATSDCOLLECTOR_TRACING_ENABLED diff --git a/beast/net/Net.cpp b/beast/net/Net.cpp index 6180dfa1..d65e14aa 100644 --- a/beast/net/Net.cpp +++ b/beast/net/Net.cpp @@ -17,18 +17,11 @@ */ //============================================================================== -#if BEAST_INCLUDE_BEASTCONFIG -#include "../../BeastConfig.h" -#endif - #include "../Config.h" -#include "../../modules/beast_core/beast_core.h" // for UnitTest - #include "impl/DynamicBuffer.cpp" -#include "impl/IPAddress.cpp" #include "impl/IPAddressV4.cpp" #include "impl/IPAddressV6.cpp" #include "impl/IPEndpoint.cpp" - +#include "tests/IPEndpoint.test.cpp" diff --git a/beast/net/impl/DynamicBuffer.cpp b/beast/net/impl/DynamicBuffer.cpp index 4dec2d5d..459c2231 100644 --- a/beast/net/impl/DynamicBuffer.cpp +++ b/beast/net/impl/DynamicBuffer.cpp @@ -17,10 +17,15 @@ */ //============================================================================== -#include +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif #include "../DynamicBuffer.h" +#include +#include + namespace beast { DynamicBuffer::DynamicBuffer (size_type blocksize) diff --git a/beast/net/impl/IPAddressV4.cpp b/beast/net/impl/IPAddressV4.cpp index a74daacf..37af00ef 100644 --- a/beast/net/impl/IPAddressV4.cpp +++ b/beast/net/impl/IPAddressV4.cpp @@ -17,7 +17,14 @@ */ //============================================================================== +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + #include "../IPAddressV4.h" +#include "../detail/Parse.h" + +#include namespace beast { namespace IP { diff --git a/beast/net/impl/IPAddressV6.cpp b/beast/net/impl/IPAddressV6.cpp index 4c9baa31..30862282 100644 --- a/beast/net/impl/IPAddressV6.cpp +++ b/beast/net/impl/IPAddressV6.cpp @@ -17,6 +17,10 @@ */ //============================================================================== +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + #include "../IPAddressV6.h" namespace beast { diff --git a/beast/net/impl/IPEndpoint.cpp b/beast/net/impl/IPEndpoint.cpp index 0f6f2325..f401c315 100644 --- a/beast/net/impl/IPEndpoint.cpp +++ b/beast/net/impl/IPEndpoint.cpp @@ -17,6 +17,11 @@ */ //============================================================================== +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + +#include "../IPEndpoint.h" #include "../detail/Parse.h" namespace beast { diff --git a/beast/net/impl/IPAddress.cpp b/beast/net/tests/IPEndpoint.test.cpp similarity index 94% rename from beast/net/impl/IPAddress.cpp rename to beast/net/tests/IPEndpoint.test.cpp index 61c3b707..ccbee18c 100644 --- a/beast/net/impl/IPAddress.cpp +++ b/beast/net/tests/IPEndpoint.test.cpp @@ -17,17 +17,23 @@ */ //============================================================================== -#include +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif #include "../IPEndpoint.h" #include "../detail/Parse.h" +#include "../../unit_test/suite.h" + +#include + namespace beast { namespace IP { //------------------------------------------------------------------------------ -class IPAddressTests : public UnitTest +class IPEndpoint_test : public unit_test::suite { public: void shouldParseV4 (std::string const& s, uint32 value) @@ -51,7 +57,7 @@ public: void testAddressV4 () { - beginTestCase ("AddressV4"); + testcase ("AddressV4"); expect (AddressV4().value == 0); expect (is_unspecified (AddressV4())); @@ -100,7 +106,7 @@ public: void testAddressV4Proxy () { - beginTestCase ("AddressV4::Proxy"); + testcase ("AddressV4::Proxy"); AddressV4 v4 (10, 0, 0, 1); expect (v4[0]==10); @@ -122,7 +128,7 @@ public: void testAddress () { - beginTestCase ("Address"); + testcase ("Address"); std::pair result ( Address::from_string ("1.2.3.4")); @@ -135,7 +141,7 @@ public: void testEndpoint () { - beginTestCase ("Endpoint"); + testcase ("Endpoint"); { std::pair result ( @@ -220,7 +226,7 @@ public: template void testParse (char const* name) { - beginTestCase (name); + testcase (name); shouldPass ("0.0.0.0"); shouldPass ("192.168.0.1"); @@ -235,7 +241,7 @@ public: shouldFail ("1.2.3:80"); } - void runTest () + void run () { testAddressV4 (); testAddressV4Proxy(); @@ -244,13 +250,9 @@ public: testParse ("Parse Endpoint"); } - - IPAddressTests () : UnitTest ("IP::Endpoint", "beast") - { - } }; -static IPAddressTests ipEndpointTests; +BEAST_DEFINE_TESTSUITE(IPEndpoint,net,beast); } } diff --git a/beast/streams/basic_scoped_ostream.h b/beast/streams/basic_scoped_ostream.h index 71f97bb3..d1a001ad 100644 --- a/beast/streams/basic_scoped_ostream.h +++ b/beast/streams/basic_scoped_ostream.h @@ -21,6 +21,7 @@ #define BEAST_STREAMS_BASIC_SCOPED_OSTREAM_H_INCLUDED #include "../cxx14/memory.h" // + #include #include #include diff --git a/beast/streams/streams.cpp b/beast/streams/streams.cpp index a38a0f11..a9574159 100644 --- a/beast/streams/streams.cpp +++ b/beast/streams/streams.cpp @@ -17,54 +17,4 @@ */ //============================================================================== -#if BEAST_INCLUDE_BEASTCONFIG -#include "../../BeastConfig.h" -#endif - -#include "../../modules/beast_core/beast_core.h" - -#include "basic_abstract_ostream.h" - -namespace beast { - -class streams_Tests : public UnitTest -{ -public: - class test_stream : public basic_abstract_ostream - { - public: - explicit test_stream (UnitTest& test) - : m_test (test) - { - } - - void write (string_type const& s) override - { - m_test.logMessage (s); - } - - test_stream& operator= (test_stream const&) = delete; - - private: - UnitTest& m_test; - }; - - void runTest() - { - beginTestCase ("stream"); - - test_stream ts (*this); - - ts << "Hello"; - - pass(); - } - - streams_Tests() : UnitTest ("streams", "beast") - { - } -}; - -static streams_Tests streams_tests; - -} +#include "tests/basic_abstract_ostream.test.cpp" diff --git a/beast/streams/tests/basic_abstract_ostream.test.cpp b/beast/streams/tests/basic_abstract_ostream.test.cpp new file mode 100644 index 00000000..1ef7687a --- /dev/null +++ b/beast/streams/tests/basic_abstract_ostream.test.cpp @@ -0,0 +1,66 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + +#include "../basic_abstract_ostream.h" + +#include "../../unit_test/suite.h" + +namespace beast { + +class basic_abstract_ostream_test : public unit_test::suite +{ +public: + class test_stream : public basic_abstract_ostream + { + public: + test_stream& + operator= (test_stream const&) = delete; + + explicit + test_stream (unit_test::suite& suite_) + : m_suite (suite_) + { + } + + void write (string_type const& s) override + { + m_suite.log << s; + } + + private: + unit_test::suite& m_suite; + }; + + void run() + { + test_stream ts (*this); + + ts << "Hello"; + + pass(); + } +}; + +BEAST_DEFINE_TESTSUITE(basic_abstract_ostream,streams,beast); + +} diff --git a/beast/strings/Strings.cpp b/beast/strings/Strings.cpp index 09b32a34..15f2ddad 100644 --- a/beast/strings/Strings.cpp +++ b/beast/strings/Strings.cpp @@ -17,9 +17,5 @@ */ //============================================================================== -#if BEAST_INCLUDE_BEASTCONFIG -#include "../../BeastConfig.h" -#endif - #include "impl/CharacterFunctions.cpp" #include "impl/String.cpp" diff --git a/beast/strings/impl/CharacterFunctions.cpp b/beast/strings/impl/CharacterFunctions.cpp index 6158f70a..51210569 100644 --- a/beast/strings/impl/CharacterFunctions.cpp +++ b/beast/strings/impl/CharacterFunctions.cpp @@ -21,6 +21,10 @@ */ //============================================================================== +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + #include "../CharacterFunctions.h" #include diff --git a/beast/strings/impl/String.cpp b/beast/strings/impl/String.cpp index b12f397a..8a52c1ec 100644 --- a/beast/strings/impl/String.cpp +++ b/beast/strings/impl/String.cpp @@ -21,7 +21,9 @@ */ //============================================================================== -#include +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif #include "../String.h" #include "../NewLine.h" @@ -32,7 +34,7 @@ #include "../../Arithmetic.h" #include "../../HeapBlock.h" -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include namespace beast { @@ -1976,364 +1978,4 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) #pragma warning (pop) #endif -//============================================================================== -//============================================================================== - -#ifdef BEAST_UNITTEST_H_INCLUDED - -class StringTests : public UnitTest -{ -public: - StringTests() : UnitTest ("String", "beast") - { - } - - template - struct TestUTFConversion - { - static void test (UnitTest& test) - { - String s (createRandomWideCharString()); - - typename CharPointerType::CharType buffer [300]; - - memset (buffer, 0xff, sizeof (buffer)); - CharPointerType (buffer).writeAll (s.toUTF32()); - test.expectEquals (String (CharPointerType (buffer)), s); - - memset (buffer, 0xff, sizeof (buffer)); - CharPointerType (buffer).writeAll (s.toUTF16()); - test.expectEquals (String (CharPointerType (buffer)), s); - - memset (buffer, 0xff, sizeof (buffer)); - CharPointerType (buffer).writeAll (s.toUTF8()); - test.expectEquals (String (CharPointerType (buffer)), s); - - test.expect (CharPointerType::isValidString (buffer, (int) strlen ((const char*) buffer))); - } - }; - - static String createRandomWideCharString() - { - beast_wchar buffer[50] = { 0 }; - Random r; - - for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) - { - if (r.nextBool()) - { - do - { - buffer[i] = (beast_wchar) (1 + r.nextInt (0x10ffff - 1)); - } - while (! CharPointer_UTF16::canRepresent (buffer[i])); - } - else - buffer[i] = (beast_wchar) (1 + r.nextInt (0xff)); - } - - return CharPointer_UTF32 (buffer); - } - - void runTest() - { - { - beginTestCase ("Basics"); - - expect (String().length() == 0); - expect (String() == String::empty); - String s1, s2 ("abcd"); - expect (s1.isEmpty() && ! s1.isNotEmpty()); - expect (s2.isNotEmpty() && ! s2.isEmpty()); - expect (s2.length() == 4); - s1 = "abcd"; - expect (s2 == s1 && s1 == s2); - expect (s1 == "abcd" && s1 == L"abcd"); - expect (String ("abcd") == String (L"abcd")); - expect (String ("abcdefg", 4) == L"abcd"); - expect (String ("abcdefg", 4) == String (L"abcdefg", 4)); - expect (String::charToString ('x') == "x"); - expect (String::charToString (0) == String::empty); - expect (s2 + "e" == "abcde" && s2 + 'e' == "abcde"); - expect (s2 + L'e' == "abcde" && s2 + L"e" == "abcde"); - expect (s1.equalsIgnoreCase ("abcD") && s1 < "abce" && s1 > "abbb"); - expect (s1.startsWith ("ab") && s1.startsWith ("abcd") && ! s1.startsWith ("abcde")); - expect (s1.startsWithIgnoreCase ("aB") && s1.endsWithIgnoreCase ("CD")); - expect (s1.endsWith ("bcd") && ! s1.endsWith ("aabcd")); - expectEquals (s1.indexOf (String::empty), 0); - expectEquals (s1.indexOfIgnoreCase (String::empty), 0); - expect (s1.startsWith (String::empty) && s1.endsWith (String::empty) && s1.contains (String::empty)); - expect (s1.contains ("cd") && s1.contains ("ab") && s1.contains ("abcd")); - expect (s1.containsChar ('a')); - expect (! s1.containsChar ('x')); - expect (! s1.containsChar (0)); - expect (String ("abc foo bar").containsWholeWord ("abc") && String ("abc foo bar").containsWholeWord ("abc")); - } - - { - beginTestCase ("Operations"); - - String s ("012345678"); - expect (s.hashCode() != 0); - expect (s.hashCode64() != 0); - expect (s.hashCode() != (s + s).hashCode()); - expect (s.hashCode64() != (s + s).hashCode64()); - expect (s.compare (String ("012345678")) == 0); - expect (s.compare (String ("012345679")) < 0); - expect (s.compare (String ("012345676")) > 0); - expect (s.substring (2, 3) == String::charToString (s[2])); - expect (s.substring (0, 1) == String::charToString (s[0])); - expect (s.getLastCharacter() == s [s.length() - 1]); - expect (String::charToString (s.getLastCharacter()) == s.getLastCharacters (1)); - expect (s.substring (0, 3) == L"012"); - expect (s.substring (0, 100) == s); - expect (s.substring (-1, 100) == s); - expect (s.substring (3) == "345678"); - expect (s.indexOf (L"45") == 4); - expect (String ("444445").indexOf ("45") == 4); - expect (String ("444445").lastIndexOfChar ('4') == 4); - expect (String ("45454545x").lastIndexOf (L"45") == 6); - expect (String ("45454545x").lastIndexOfAnyOf ("456") == 7); - expect (String ("45454545x").lastIndexOfAnyOf (L"456x") == 8); - expect (String ("abABaBaBa").lastIndexOfIgnoreCase ("aB") == 6); - expect (s.indexOfChar (L'4') == 4); - expect (s + s == "012345678012345678"); - expect (s.startsWith (s)); - expect (s.startsWith (s.substring (0, 4))); - expect (s.startsWith (s.dropLastCharacters (4))); - expect (s.endsWith (s.substring (5))); - expect (s.endsWith (s)); - expect (s.contains (s.substring (3, 6))); - expect (s.contains (s.substring (3))); - expect (s.startsWithChar (s[0])); - expect (s.endsWithChar (s.getLastCharacter())); - expect (s [s.length()] == 0); - expect (String ("abcdEFGH").toLowerCase() == String ("abcdefgh")); - expect (String ("abcdEFGH").toUpperCase() == String ("ABCDEFGH")); - - String s2 ("123"); - s2 << ((int) 4) << ((short) 5) << "678" << L"9" << '0'; - s2 += "xyz"; - expect (s2 == "1234567890xyz"); - - beginTestCase ("Numeric conversions"); - expect (String::empty.getIntValue() == 0); - expect (String::empty.getDoubleValue() == 0.0); - expect (String::empty.getFloatValue() == 0.0f); - expect (s.getIntValue() == 12345678); - expect (s.getLargeIntValue() == (int64) 12345678); - expect (s.getDoubleValue() == 12345678.0); - expect (s.getFloatValue() == 12345678.0f); - expect (String (-1234).getIntValue() == -1234); - expect (String ((int64) -1234).getLargeIntValue() == -1234); - expect (String (-1234.56).getDoubleValue() == -1234.56); - expect (String (-1234.56f).getFloatValue() == -1234.56f); - expect (String (std::numeric_limits::max()).getIntValue() == std::numeric_limits::max()); - expect (String (std::numeric_limits::min()).getIntValue() == std::numeric_limits::min()); - expect (String (std::numeric_limits::max()).getLargeIntValue() == std::numeric_limits::max()); - expect (String (std::numeric_limits::min()).getLargeIntValue() == std::numeric_limits::min()); - expect (("xyz" + s).getTrailingIntValue() == s.getIntValue()); - expect (s.getHexValue32() == 0x12345678); - expect (s.getHexValue64() == (int64) 0x12345678); - expect (String::toHexString (0x1234abcd).equalsIgnoreCase ("1234abcd")); - expect (String::toHexString ((int64) 0x1234abcd).equalsIgnoreCase ("1234abcd")); - expect (String::toHexString ((short) 0x12ab).equalsIgnoreCase ("12ab")); - - expectEquals (String (int (0)), "0"); - expectEquals (String (short (0)), "0"); - expectEquals (String (int64 (0)), "0"); - expectEquals (String ((unsigned int) 0), "0"); - expectEquals (String ((unsigned short) 0), "0"); - expectEquals (String (uint64 (0)), "0"); - - expectEquals (String (int (-1)), "-1"); - expectEquals (String (short (-1)), "-1"); - expectEquals (String (int64 (-1)), "-1"); - - expectEquals (String (int (1)), "1"); - expectEquals (String (short (1)), "1"); - expectEquals (String (int64 (1)), "1"); - expectEquals (String ((unsigned int) 1), "1"); - expectEquals (String ((unsigned short) 1), "1"); - expectEquals (String (uint64 (1)), "1"); - - unsigned char data[] = { 1, 2, 3, 4, 0xa, 0xb, 0xc, 0xd }; - expect (String::toHexString (data, 8, 0).equalsIgnoreCase ("010203040a0b0c0d")); - expect (String::toHexString (data, 8, 1).equalsIgnoreCase ("01 02 03 04 0a 0b 0c 0d")); - expect (String::toHexString (data, 8, 2).equalsIgnoreCase ("0102 0304 0a0b 0c0d")); - - beginTestCase ("Subsections"); - String s3; - s3 = "abcdeFGHIJ"; - expect (s3.equalsIgnoreCase ("ABCdeFGhiJ")); - expect (s3.compareIgnoreCase (L"ABCdeFGhiJ") == 0); - expect (s3.containsIgnoreCase (s3.substring (3))); - expect (s3.indexOfAnyOf ("xyzf", 2, true) == 5); - expect (s3.indexOfAnyOf (L"xyzf", 2, false) == -1); - expect (s3.indexOfAnyOf ("xyzF", 2, false) == 5); - expect (s3.containsAnyOf (L"zzzFs")); - expect (s3.startsWith ("abcd")); - expect (s3.startsWithIgnoreCase (L"abCD")); - expect (s3.startsWith (String::empty)); - expect (s3.startsWithChar ('a')); - expect (s3.endsWith (String ("HIJ"))); - expect (s3.endsWithIgnoreCase (L"Hij")); - expect (s3.endsWith (String::empty)); - expect (s3.endsWithChar (L'J')); - expect (s3.indexOf ("HIJ") == 7); - expect (s3.indexOf (L"HIJK") == -1); - expect (s3.indexOfIgnoreCase ("hij") == 7); - expect (s3.indexOfIgnoreCase (L"hijk") == -1); - expect (s3.toStdString() == s3.toRawUTF8()); - - String s4 (s3); - s4.append (String ("xyz123"), 3); - expect (s4 == s3 + "xyz"); - - expect (String (1234) < String (1235)); - expect (String (1235) > String (1234)); - expect (String (1234) >= String (1234)); - expect (String (1234) <= String (1234)); - expect (String (1235) >= String (1234)); - expect (String (1234) <= String (1235)); - - String s5 ("word word2 word3"); - expect (s5.containsWholeWord (String ("word2"))); - expect (s5.indexOfWholeWord ("word2") == 5); - expect (s5.containsWholeWord (L"word")); - expect (s5.containsWholeWord ("word3")); - expect (s5.containsWholeWord (s5)); - expect (s5.containsWholeWordIgnoreCase (L"Word2")); - expect (s5.indexOfWholeWordIgnoreCase ("Word2") == 5); - expect (s5.containsWholeWordIgnoreCase (L"Word")); - expect (s5.containsWholeWordIgnoreCase ("Word3")); - expect (! s5.containsWholeWordIgnoreCase (L"Wordx")); - expect (! s5.containsWholeWordIgnoreCase ("xWord2")); - expect (s5.containsNonWhitespaceChars()); - expect (s5.containsOnly ("ordw23 ")); - expect (! String (" \n\r\t").containsNonWhitespaceChars()); - - expect (s5.matchesWildcard (L"wor*", false)); - expect (s5.matchesWildcard ("wOr*", true)); - expect (s5.matchesWildcard (L"*word3", true)); - expect (s5.matchesWildcard ("*word?", true)); - expect (s5.matchesWildcard (L"Word*3", true)); - expect (! s5.matchesWildcard (L"*34", true)); - expect (String ("xx**y").matchesWildcard ("*y", true)); - expect (String ("xx**y").matchesWildcard ("x*y", true)); - expect (String ("xx**y").matchesWildcard ("xx*y", true)); - expect (String ("xx**y").matchesWildcard ("xx*", true)); - expect (String ("xx?y").matchesWildcard ("x??y", true)); - expect (String ("xx?y").matchesWildcard ("xx?y", true)); - expect (! String ("xx?y").matchesWildcard ("xx?y?", true)); - expect (String ("xx?y").matchesWildcard ("xx??", true)); - - expectEquals (s5.fromFirstOccurrenceOf (String::empty, true, false), s5); - expectEquals (s5.fromFirstOccurrenceOf ("xword2", true, false), s5.substring (100)); - expectEquals (s5.fromFirstOccurrenceOf (L"word2", true, false), s5.substring (5)); - expectEquals (s5.fromFirstOccurrenceOf ("Word2", true, true), s5.substring (5)); - expectEquals (s5.fromFirstOccurrenceOf ("word2", false, false), s5.getLastCharacters (6)); - expectEquals (s5.fromFirstOccurrenceOf (L"Word2", false, true), s5.getLastCharacters (6)); - - expectEquals (s5.fromLastOccurrenceOf (String::empty, true, false), s5); - expectEquals (s5.fromLastOccurrenceOf (L"wordx", true, false), s5); - expectEquals (s5.fromLastOccurrenceOf ("word", true, false), s5.getLastCharacters (5)); - expectEquals (s5.fromLastOccurrenceOf (L"worD", true, true), s5.getLastCharacters (5)); - expectEquals (s5.fromLastOccurrenceOf ("word", false, false), s5.getLastCharacters (1)); - expectEquals (s5.fromLastOccurrenceOf (L"worD", false, true), s5.getLastCharacters (1)); - - expect (s5.upToFirstOccurrenceOf (String::empty, true, false).isEmpty()); - expectEquals (s5.upToFirstOccurrenceOf ("word4", true, false), s5); - expectEquals (s5.upToFirstOccurrenceOf (L"word2", true, false), s5.substring (0, 10)); - expectEquals (s5.upToFirstOccurrenceOf ("Word2", true, true), s5.substring (0, 10)); - expectEquals (s5.upToFirstOccurrenceOf (L"word2", false, false), s5.substring (0, 5)); - expectEquals (s5.upToFirstOccurrenceOf ("Word2", false, true), s5.substring (0, 5)); - - expectEquals (s5.upToLastOccurrenceOf (String::empty, true, false), s5); - expectEquals (s5.upToLastOccurrenceOf ("zword", true, false), s5); - expectEquals (s5.upToLastOccurrenceOf ("word", true, false), s5.dropLastCharacters (1)); - expectEquals (s5.dropLastCharacters(1).upToLastOccurrenceOf ("word", true, false), s5.dropLastCharacters (1)); - expectEquals (s5.upToLastOccurrenceOf ("Word", true, true), s5.dropLastCharacters (1)); - expectEquals (s5.upToLastOccurrenceOf ("word", false, false), s5.dropLastCharacters (5)); - expectEquals (s5.upToLastOccurrenceOf ("Word", false, true), s5.dropLastCharacters (5)); - - expectEquals (s5.replace ("word", L"xyz", false), String ("xyz xyz2 xyz3")); - expect (s5.replace (L"Word", "xyz", true) == "xyz xyz2 xyz3"); - expect (s5.dropLastCharacters (1).replace ("Word", String ("xyz"), true) == L"xyz xyz2 xyz"); - expect (s5.replace ("Word", "", true) == " 2 3"); - expectEquals (s5.replace ("Word2", L"xyz", true), String ("word xyz word3")); - expect (s5.replaceCharacter (L'w', 'x') != s5); - expectEquals (s5.replaceCharacter ('w', L'x').replaceCharacter ('x', 'w'), s5); - expect (s5.replaceCharacters ("wo", "xy") != s5); - expectEquals (s5.replaceCharacters ("wo", "xy").replaceCharacters ("xy", L"wo"), s5); - expectEquals (s5.retainCharacters ("1wordxya"), String ("wordwordword")); - expect (s5.retainCharacters (String::empty).isEmpty()); - expect (s5.removeCharacters ("1wordxya") == " 2 3"); - expectEquals (s5.removeCharacters (String::empty), s5); - expect (s5.initialSectionContainingOnly ("word") == L"word"); - expect (String ("word").initialSectionContainingOnly ("word") == L"word"); - expectEquals (s5.initialSectionNotContaining (String ("xyz ")), String ("word")); - expectEquals (s5.initialSectionNotContaining (String (";[:'/")), s5); - expect (! s5.isQuotedString()); - expect (s5.quoted().isQuotedString()); - expect (! s5.quoted().unquoted().isQuotedString()); - expect (! String ("x'").isQuotedString()); - expect (String ("'x").isQuotedString()); - - String s6 (" \t xyz \t\r\n"); - expectEquals (s6.trim(), String ("xyz")); - expect (s6.trim().trim() == "xyz"); - expectEquals (s5.trim(), s5); - expectEquals (s6.trimStart().trimEnd(), s6.trim()); - expectEquals (s6.trimStart().trimEnd(), s6.trimEnd().trimStart()); - expectEquals (s6.trimStart().trimStart().trimEnd().trimEnd(), s6.trimEnd().trimStart()); - expect (s6.trimStart() != s6.trimEnd()); - expectEquals (("\t\r\n " + s6 + "\t\n \r").trim(), s6.trim()); - expect (String::repeatedString ("xyz", 3) == L"xyzxyzxyz"); - } - - { - beginTestCase ("UTF conversions"); - - TestUTFConversion ::test (*this); - TestUTFConversion ::test (*this); - TestUTFConversion ::test (*this); - } - - { - beginTestCase ("StringArray"); - - StringArray s; - s.addTokens ("4,3,2,1,0", ";,", "x"); - expectEquals (s.size(), 5); - - expectEquals (s.joinIntoString ("-"), String ("4-3-2-1-0")); - s.remove (2); - expectEquals (s.joinIntoString ("--"), String ("4--3--1--0")); - expectEquals (s.joinIntoString (String::empty), String ("4310")); - s.clear(); - expectEquals (s.joinIntoString ("x"), String::empty); - - StringArray toks; - toks.addTokens ("x,,", ";,", ""); - expectEquals (toks.size(), 3); - expectEquals (toks.joinIntoString ("-"), String ("x--")); - toks.clear(); - - toks.addTokens (",x,", ";,", ""); - expectEquals (toks.size(), 3); - expectEquals (toks.joinIntoString ("-"), String ("-x-")); - toks.clear(); - - toks.addTokens ("x,'y,z',", ";,", "'"); - expectEquals (toks.size(), 3); - expectEquals (toks.joinIntoString ("-"), String ("x-'y,z'-")); - } - } -}; - -static StringTests stringUnitTests; - -#endif - } diff --git a/beast/threads/Thread.h b/beast/threads/Thread.h index 1ea34f7c..4a89fe46 100644 --- a/beast/threads/Thread.h +++ b/beast/threads/Thread.h @@ -24,6 +24,7 @@ #ifndef BEAST_THREADS_THREAD_H_INCLUDED #define BEAST_THREADS_THREAD_H_INCLUDED +#include "../strings/String.h" #include "../utility/LeakChecked.h" #include "RecursiveMutex.h" #include "WaitableEvent.h" diff --git a/beast/threads/Threads.cpp b/beast/threads/Threads.cpp index a2e94916..283e0811 100644 --- a/beast/threads/Threads.cpp +++ b/beast/threads/Threads.cpp @@ -21,9 +21,11 @@ #include "../../BeastConfig.h" #endif -#include "impl/Atomic.cpp" #include "impl/RecursiveMutex.cpp" #include "impl/ServiceQueue.cpp" #include "impl/Stoppable.cpp" #include "impl/Thread.cpp" #include "impl/WaitableEvent.cpp" + +#include "tests/Atomic.test.cpp" +#include "tests/ServiceQueue.test.cpp" diff --git a/beast/threads/impl/ServiceQueue.cpp b/beast/threads/impl/ServiceQueue.cpp index 317d7a61..0b284e35 100644 --- a/beast/threads/impl/ServiceQueue.cpp +++ b/beast/threads/impl/ServiceQueue.cpp @@ -19,8 +19,6 @@ #include "../ServiceQueue.h" -#include "../../../modules/beast_core/beast_core.h" // for UnitTest - namespace beast { class ServiceQueueBase::ScopedServiceThread : public List ::Node @@ -185,275 +183,4 @@ bool ServiceQueueBase::empty() // ThreadLocalValue ServiceQueueBase::s_service; -//------------------------------------------------------------------------------ - -namespace detail { - -//------------------------------------------------------------------------------ - -class ServiceQueueTimingTests - : public UnitTest -{ -public: - class Stopwatch - { - public: - Stopwatch () { start(); } - void start () { m_startTime = Time::getHighResolutionTicks (); } - double getElapsed () - { - int64 const now = Time::getHighResolutionTicks(); - return Time::highResolutionTicksToSeconds (now - m_startTime); - } - private: - int64 m_startTime; - }; - - static int const callsPerThread = 50000; - - //-------------------------------------------------------------------------- - - template - struct Consumer : Thread - { - ServiceType& m_service; - Random m_random; - String m_string; - - Consumer (int id, int64 seedValue, ServiceType& service) - : Thread ("C#" + String::fromNumber (id)) - , m_service (service) - , m_random (seedValue) - { startThread(); } - - ~Consumer () - { stopThread(); } - - static Consumer*& thread() - { - static ThreadLocalValue local; - return local.get(); - } - - static void stop_one () - { thread()->signalThreadShouldExit(); } - - static void handler () - { thread()->do_handler(); } - - void do_handler() - { - String const s (String::fromNumber (m_random.nextInt())); - m_string += s; - if (m_string.length() > 100) - m_string = String::empty; - } - - void run () - { - thread() = this; - while (! threadShouldExit()) - m_service.run_one(); - } - }; - - //-------------------------------------------------------------------------- - - template - struct Producer : Thread - { - ServiceType& m_service; - Random m_random; - String m_string; - - Producer (int id, int64 seedValue, ServiceType& service) - : Thread ("P#" + String::fromNumber (id)) - , m_service (service) - , m_random (seedValue) - { } - - ~Producer () - { stopThread(); } - - void run () - { - for (std::size_t i = 0; i < callsPerThread; ++i) - { - String const s (String::fromNumber (m_random.nextInt())); - m_string += s; - if (m_string.length() > 100) - m_string = String::empty; - m_service.dispatch (bind (&Consumer::handler)); - } - } - }; - - //-------------------------------------------------------------------------- - - template - void testThreads (std::size_t nConsumers, std::size_t nProducers) - { - beginTestCase (String::fromNumber (nConsumers) + " consumers, " + - String::fromNumber (nProducers) + " producers, " + - "Allocator = " + std::string(typeid(Allocator).name())); - - typedef ServiceQueueType ServiceType; - - ServiceType service (nConsumers); - std::vector > > consumers; - std::vector > > producers; - consumers.reserve (nConsumers); - producers.reserve (nProducers); - - for (std::size_t i = 0; i < nConsumers; ++i) - consumers.push_back (new Consumer (i + 1, - random().nextInt64(), service)); - - for (std::size_t i = 0; i < nProducers; ++i) - producers.push_back (new Producer (i + 1, - random().nextInt64(), service)); - - Stopwatch t; - - for (std::size_t i = 0; i < producers.size(); ++i) - producers[i]->startThread(); - - for (std::size_t i = 0; i < producers.size(); ++i) - producers[i]->waitForThreadToExit(); - - for (std::size_t i = 0; i < consumers.size(); ++i) - service.dispatch (bind (&Consumer ::stop_one)); - - for (std::size_t i = 0; i < consumers.size(); ++i) - consumers[i]->waitForThreadToExit(); - - double const seconds (t.getElapsed()); - logMessage (String (seconds, 2) + " seconds"); - - pass(); - } - - void runTest() - { -#if 1 - testThreads > (1, 1); - testThreads > (1, 4); - testThreads > (1, 16); - testThreads > (4, 1); - testThreads > (8, 16); -#endif - -#if 0 - testThreads > (1, 1); - testThreads > (1, 4); - testThreads > (1, 16); - testThreads > (4, 1); - testThreads > (8, 16); -#endif - } - - ServiceQueueTimingTests () : UnitTest ("ServiceQueueTiming", "beast", runManual) - { - } -}; - -static ServiceQueueTimingTests serviceQueueTimingTests; - -//------------------------------------------------------------------------------ - -class ServiceQueueTests - : public UnitTest -{ -public: - struct ServiceThread : Thread - { - Random m_random; - ServiceQueue& m_service; - String m_string; - - ServiceThread (int id, int64 seedValue, - ServiceQueue& service) - : Thread ("#" + String::fromNumber (id)) - , m_random (seedValue) - , m_service (service) - { - startThread(); - } - - ~ServiceThread () - { - stopThread(); - } - - static ServiceThread*& thread() - { - static ThreadLocalValue local; - return local.get(); - } - - static void stop_one () - { - thread()->signalThreadShouldExit(); - } - - static void handler () - { - thread()->do_handler(); - } - - void do_handler() - { -#if 1 - String const s (String::fromNumber (m_random.nextInt())); - m_string += s; - if (m_string.length() > 100) - m_string = String::empty; -#endif - } - - void run () - { - thread() = this; - while (! threadShouldExit()) - m_service.run_one(); - } - }; - - static std::size_t const totalCalls = 10000; - - void testThreads (std::size_t n) - { - std::size_t const callsPerThread (totalCalls / n); - beginTestCase (String::fromNumber (n) + " threads"); - ServiceQueue service (n); - std::vector > threads; - threads.reserve (n); - for (std::size_t i = 0; i < n; ++i) - threads.push_back (new ServiceThread (i + 1, - random().nextInt64(), service)); - for (std::size_t i = n * callsPerThread; i; --i) - service.dispatch (bind (&ServiceThread::handler)); - for (std::size_t i = 0; i < threads.size(); ++i) - service.dispatch (bind (&ServiceThread::stop_one)); - for (std::size_t i = 0; i < threads.size(); ++i) - threads[i]->waitForThreadToExit(); - pass(); - } - - void runTest() - { - testThreads (1); - testThreads (4); - testThreads (16); - } - - ServiceQueueTests () : UnitTest ("ServiceQueue", "beast") - { - } -}; - -static ServiceQueueTests serviceQueueTests; - -} - } diff --git a/beast/threads/impl/Thread.cpp b/beast/threads/impl/Thread.cpp index f04782d9..34c2b71f 100644 --- a/beast/threads/impl/Thread.cpp +++ b/beast/threads/impl/Thread.cpp @@ -22,6 +22,11 @@ //============================================================================== #include "../Thread.h" +#include "../../smart_ptr/SharedObject.h" +#include "../../smart_ptr/SharedPtr.h" +#include "../../../modules/beast_core/time/Time.h" + +#include namespace beast { @@ -44,7 +49,7 @@ Thread::~Thread() To avoid this type of nastiness, always make sure you call stopThread() before or during your subclass's destructor. */ - check_precondition (! isThreadRunning()); + assert (! isThreadRunning()); stopThread (); } diff --git a/beast/threads/impl/Atomic.cpp b/beast/threads/tests/Atomic.test.cpp similarity index 84% rename from beast/threads/impl/Atomic.cpp rename to beast/threads/tests/Atomic.test.cpp index 5f1790fd..a348c435 100644 --- a/beast/threads/impl/Atomic.cpp +++ b/beast/threads/tests/Atomic.test.cpp @@ -21,15 +21,21 @@ */ //============================================================================== -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#if BEAST_INCLUDE_BEASTCONFIG +#include "../../BeastConfig.h" +#endif + +#include "../../Atomic.h" +#include "../../Arithmetic.h" +#include "../../ByteOrder.h" + +#include "../../unit_test/suite.h" namespace beast { -class AtomicTests : public UnitTest +class Atomic_test : public unit_test::suite { public: - AtomicTests() : UnitTest ("Atomic", "beast") {} - template void testFloat () { @@ -78,9 +84,9 @@ public: testFloat (); } - void runTest() + void run() { - beginTestCase ("Misc"); + testcase ("Misc"); char a1[7]; expect (numElementsInArray(a1) == 7); @@ -91,43 +97,43 @@ public: expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211)); - beginTestCase ("int"); + testcase ("int"); testInteger (); - beginTestCase ("unsigned int"); + testcase ("unsigned int"); testInteger (); - beginTestCase ("int32"); + testcase ("int32"); testInteger (); - beginTestCase ("uint32"); + testcase ("uint32"); testInteger (); - beginTestCase ("long"); + testcase ("long"); testInteger (); - beginTestCase ("void*"); + testcase ("void*"); testInteger (); - beginTestCase ("int*"); + testcase ("int*"); testInteger (); - beginTestCase ("float"); + testcase ("float"); testFloat (); #if ! BEAST_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms - beginTestCase ("int64"); + testcase ("int64"); testInteger (); - beginTestCase ("uint64"); + testcase ("uint64"); testInteger (); - beginTestCase ("double"); + testcase ("double"); testFloat (); #endif } }; -static AtomicTests atomicTests; +BEAST_DEFINE_TESTSUITE(Atomic,thread,beast); } diff --git a/beast/threads/tests/ServiceQueue.test.cpp b/beast/threads/tests/ServiceQueue.test.cpp new file mode 100644 index 00000000..f079d574 --- /dev/null +++ b/beast/threads/tests/ServiceQueue.test.cpp @@ -0,0 +1,295 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../ServiceQueue.h" + +#include "../../unit_test/suite.h" + +#include "../../../modules/beast_core/time/Time.h" +#include "../../../modules/beast_core/maths/Random.h" + +#include +#include + +namespace beast { + +class ServiceQueue_timing_test : public unit_test::suite +{ +public: + class Stopwatch + { + public: + Stopwatch () { start(); } + void start () { m_startTime = Time::getHighResolutionTicks (); } + double getElapsed () + { + int64 const now = Time::getHighResolutionTicks(); + return Time::highResolutionTicksToSeconds (now - m_startTime); + } + private: + int64 m_startTime; + }; + + static int const callsPerThread = 50000; + + //-------------------------------------------------------------------------- + + template + struct Consumer : Thread + { + ServiceType& m_service; + Random m_random; + String m_string; + + Consumer (int id, int64 seedValue, ServiceType& service) + : Thread ("C#" + String::fromNumber (id)) + , m_service (service) + , m_random (seedValue) + { startThread(); } + + ~Consumer () + { stopThread(); } + + static Consumer*& thread() + { + static ThreadLocalValue local; + return local.get(); + } + + static void stop_one () + { thread()->signalThreadShouldExit(); } + + static void handler () + { thread()->do_handler(); } + + void do_handler() + { + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; + } + + void run () + { + thread() = this; + while (! threadShouldExit()) + m_service.run_one(); + } + }; + + //-------------------------------------------------------------------------- + + template + struct Producer : Thread + { + ServiceType& m_service; + Random m_random; + String m_string; + + Producer (int id, int64 seedValue, ServiceType& service) + : Thread ("P#" + String::fromNumber (id)) + , m_service (service) + , m_random (seedValue) + { } + + ~Producer () + { stopThread(); } + + void run () + { + for (std::size_t i = 0; i < callsPerThread; ++i) + { + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; + m_service.dispatch (std::bind (&Consumer::handler)); + } + } + }; + + //-------------------------------------------------------------------------- + + template + void testThreads (std::size_t nConsumers, std::size_t nProducers) + { + std::stringstream ss; + ss << + nConsumers << " consumers, " << + nProducers << " producers, Allocator = " << + typeid(Allocator).name(); + testcase (ss.str()); + + typedef ServiceQueueType ServiceType; + + ServiceType service (nConsumers); + std::vector > > consumers; + std::vector > > producers; + consumers.reserve (nConsumers); + producers.reserve (nProducers); + + Random r; + + for (std::size_t i = 0; i < nConsumers; ++i) + consumers.emplace_back (new Consumer (i + 1, + r.nextInt64(), service)); + + for (std::size_t i = 0; i < nProducers; ++i) + producers.emplace_back (new Producer (i + 1, + r.nextInt64(), service)); + + Stopwatch t; + + for (std::size_t i = 0; i < producers.size(); ++i) + producers[i]->startThread(); + + for (std::size_t i = 0; i < producers.size(); ++i) + producers[i]->waitForThreadToExit(); + + for (std::size_t i = 0; i < consumers.size(); ++i) + service.dispatch (std::bind (&Consumer ::stop_one)); + + for (std::size_t i = 0; i < consumers.size(); ++i) + consumers[i]->waitForThreadToExit(); + + double const seconds (t.getElapsed()); + log << seconds << " seconds"; + + pass(); + } + + void run() + { +#if 1 + testThreads > (1, 1); + testThreads > (1, 4); + testThreads > (1, 16); + testThreads > (4, 1); + testThreads > (8, 16); +#endif + +#if 0 + testThreads > (1, 1); + testThreads > (1, 4); + testThreads > (1, 16); + testThreads > (4, 1); + testThreads > (8, 16); +#endif + } +}; + +BEAST_DEFINE_TESTSUITE_MANUAL(ServiceQueue_timing,threads,beast); + +//------------------------------------------------------------------------------ + +class ServiceQueue_test : public unit_test::suite +{ +public: + struct ServiceThread : Thread + { + Random m_random; + ServiceQueue& m_service; + String m_string; + + ServiceThread (int id, int64 seedValue, + ServiceQueue& service) + : Thread ("#" + String::fromNumber (id)) + , m_random (seedValue) + , m_service (service) + { + startThread(); + } + + ~ServiceThread () + { + stopThread(); + } + + static ServiceThread*& thread() + { + static ThreadLocalValue local; + return local.get(); + } + + static void stop_one () + { + thread()->signalThreadShouldExit(); + } + + static void handler () + { + thread()->do_handler(); + } + + void do_handler() + { +#if 1 + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; +#endif + } + + void run () + { + thread() = this; + while (! threadShouldExit()) + m_service.run_one(); + } + }; + + static std::size_t const totalCalls = 10000; + + void testThreads (std::size_t n) + { + std::stringstream ss; + ss << n << " threads"; + testcase (ss.str()); + + Random r; + std::size_t const callsPerThread (totalCalls / n); + + ServiceQueue service (n); + std::vector > threads; + threads.reserve (n); + for (std::size_t i = 0; i < n; ++i) + threads.emplace_back (new ServiceThread (i + 1, + r.nextInt64(), service)); + for (std::size_t i = n * callsPerThread; i; --i) + service.dispatch (std::bind (&ServiceThread::handler)); + for (std::size_t i = 0; i < threads.size(); ++i) + service.dispatch (std::bind (&ServiceThread::stop_one)); + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i]->waitForThreadToExit(); + pass(); + } + + void run() + { + testThreads (1); + testThreads (4); + testThreads (16); + } +}; + +BEAST_DEFINE_TESTSUITE(ServiceQueue,threads,beast); + +} diff --git a/beast/unit_test.h b/beast/unit_test.h new file mode 100644 index 00000000..81764936 --- /dev/null +++ b/beast/unit_test.h @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_H_INCLUDED +#define BEAST_UNIT_TEST_H_INCLUDED + +#include "./unit_test/amount.h" +#include "./unit_test/print.h" +#include "./unit_test/global_suites.h" +#include "./unit_test/match.h" +#include "./unit_test/recorder.h" +#include "./unit_test/reporter.h" +#include "./unit_test/results.h" +#include "./unit_test/runner.h" +#include "./unit_test/suite.h" +#include "./unit_test/suite_info.h" +#include "./unit_test/suite_list.h" + +#endif diff --git a/beast/unit_test/README.md b/beast/unit_test/README.md new file mode 100644 index 00000000..0382e282 --- /dev/null +++ b/beast/unit_test/README.md @@ -0,0 +1,3 @@ +# beast.unit_test + +This provides a framework for defining and running unit tests. diff --git a/beast/unit_test/amount.h b/beast/unit_test/amount.h new file mode 100644 index 00000000..ef950140 --- /dev/null +++ b/beast/unit_test/amount.h @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_AMOUNT_H_INLCUDED +#define BEAST_UNIT_TEST_AMOUNT_H_INLCUDED + +#include +#include +#include + +namespace beast { +namespace unit_test { + +/** Utility for producing nicely composed output of amounts with units. */ +class amount +{ +private: + 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_) + { + } + + friend + std::ostream& + operator<< (std::ostream& s, amount const& t) + { + s << t.n << " " << t.what << ((t.n != 1) ? "s" : ""); + return s; + } +}; + +} // unit_test +} // beast + +#endif diff --git a/modules/beast_vflib/threads/GuiServiceQueue.h b/beast/unit_test/define_print.cpp similarity index 51% rename from modules/beast_vflib/threads/GuiServiceQueue.h rename to beast/unit_test/define_print.cpp index 2f8d8750..47770109 100644 --- a/modules/beast_vflib/threads/GuiServiceQueue.h +++ b/beast/unit_test/define_print.cpp @@ -2,7 +2,6 @@ /* This file is part of Beast: https://github.com/vinniefalco/Beast Copyright 2013, Vinnie Falco - Copyright Patrick Dehne (www.sonicweb-radio.de) Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -15,58 +14,64 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ +*/ //============================================================================== -#ifndef BEAST_VFLIB_GUISERVICEQUEUE_H_INCLUDED -#define BEAST_VFLIB_GUISERVICEQUEUE_H_INCLUDED +#include "amount.h" +#include "global_suites.h" +#include "suite.h" -#include "AppConfig.h" -#include "modules/juce_core/juce_core.h" -#include "modules/juce_events/juce_events.h" - -#include "CallQueue.h" +// Include this .cpp in your project to gain access to the printing suite namespace beast { +namespace unit_test { -class GuiServiceQueue -: public CallQueue -, private juce::AsyncUpdater -, private ThreadWithServiceQueue::EntryPoints +namespace detail { + +/** A suite that prints the list of globally defined suites. */ +class print_test : public suite { public: - explicit GuiServiceQueue (const String& name) - : CallQueue(name) - , m_thread(name) + static + std::string + prefix (suite_info const& s) { - bassert (juce::MessageManager::getInstance()->isThisTheMessageThread()); - - m_thread.start (this); + if (s.manual()) + return "|M| "; + return " "; } - - void close () + + void + print (suite_list &c) { - m_thread.stop (true); - - CallQueue::close (); + 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") + ; } - - void enqueue (ServiceQueueBase::Item* item) + + void + run() { - CallQueue::enqueue (item); - - m_thread.call (&juce::AsyncUpdater::triggerAsyncUpdate, (AsyncUpdater*)this); + log << "------------------------------------------"; + print (global_suites()); + log << "------------------------------------------"; + pass(); } - - void handleAsyncUpdate() - { - poll(); - } - -private: - ThreadWithServiceQueue m_thread; }; +BEAST_DEFINE_TESTSUITE_MANUAL(print,unit_test,beast); + } -#endif +} +} diff --git a/beast/unit_test/global_suites.h b/beast/unit_test/global_suites.h new file mode 100644 index 00000000..8fd39d5d --- /dev/null +++ b/beast/unit_test/global_suites.h @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_GLOBAL_SUITES_H_INCLUDED +#define BEAST_UNIT_TEST_GLOBAL_SUITES_H_INCLUDED + +#include "suite_list.h" + +namespace beast { +namespace unit_test { + +namespace detail { + +// Non const container is a detail, users are not allowed to modify! +inline +suite_list& +global_suites() +{ + static suite_list s; + return s; +} + +// Used to insert suites during static initialization +template +struct global_suite_instance +{ + global_suite_instance (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. */ +inline +suite_list const& +global_suites() +{ + return detail::global_suites(); +} + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/match.h b/beast/unit_test/match.h new file mode 100644 index 00000000..ad0d1f07 --- /dev/null +++ b/beast/unit_test/match.h @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_MATCH_H_INLCUDED +#define BEAST_UNIT_TEST_MATCH_H_INLCUDED + +#include "suite_info.h" + +namespace beast { +namespace unit_test { + +// Predicate for implementing matches +class selector +{ +public: + enum mode_t + { + // Run all tests except manual ones + all, + + // Run tests that match in any field + automatch, + + // Match on suite + suite, + + // Match on library + library, + + // Match on module (used internally) + module, + + // Match nothing (used internally) + none + }; + +private: + mode_t m_mode; + std::string m_pat; + std::string m_library; + +public: + explicit + selector (mode_t mode, std::string const& pattern = "") + : m_mode (mode) + , m_pat (pattern) + { + if (m_mode == automatch && pattern.empty()) + m_mode = all; + } + + 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(); + } +}; + +//------------------------------------------------------------------------------ + +// Utility functions for producing predicates to select suites. + +/** Returns a predicate that implements a smart matching rule. + The predicate checks the suite, module, and library fields of the + suite_info in that order. When it finds a match, it changes modes + depending on what was found: + + If a suite is matched first, then only the suite is selected. The + suite may be marked manual. + + If a module is matched first, then only suites from that module + and library not marked manual are selected from then on. + + If a library is matched first, then only suites from that library + not marked manual are selected from then on. + +*/ +inline +selector +match_auto (std::string const& name) +{ + return selector (selector::automatch, name); +} + +/** Return a predicate that matches all suites not marked manual. */ +inline +selector +match_all() +{ + return selector (selector::all); +} + +/** Returns a predicate that matches a specific suite. */ +inline +selector +match_suite (std::string const& name) +{ + return selector (selector::suite, name); +} + +/** Returns a predicate that matches all suites in a library. */ +inline +selector +match_library (std::string const& name) +{ + return selector (selector::library, name); +} + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/print.h b/beast/unit_test/print.h new file mode 100644 index 00000000..b4cd355e --- /dev/null +++ b/beast/unit_test/print.h @@ -0,0 +1,80 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_PRINT_H_INLCUDED +#define BEAST_UNIT_TEST_PRINT_H_INLCUDED + +#include "amount.h" +#include "results.h" + +#include "../streams/abstract_ostream.h" +#include "../streams/basic_std_ostream.h" + +#include +#include + +namespace beast { +namespace unit_test { + +/** Write test results to the specified output stream. */ +/** @{ */ +inline +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") + ; +} + +inline +void +print (results const& r, std::ostream& stream = std::cout) +{ + auto s (make_std_ostream (stream)); + print (r, s); +} + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/recorder.h b/beast/unit_test/recorder.h new file mode 100644 index 00000000..565167e7 --- /dev/null +++ b/beast/unit_test/recorder.h @@ -0,0 +1,106 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_RECORDER_H_INLCUDED +#define BEAST_UNIT_TEST_RECORDER_H_INLCUDED + +#include "results.h" +#include "runner.h" + +namespace beast { +namespace unit_test { + +/** A test runner that stores the results. */ +class recorder : public runner +{ +private: + results m_results; + suite_results m_suite; + case_results m_case; + +public: + recorder (recorder const&) = default; + recorder& operator= (recorder const&) = default; + + recorder() + { + } + + /** Returns a report with the results of all completed suites. */ + results const& report() const + { + return m_results; + } + +private: + virtual + void + on_suite_begin (suite_info const& info) override + { + m_suite = suite_results (info.full_name()); + } + + virtual + void + on_suite_end() override + { + m_results.insert (std::move (m_suite)); + } + + virtual + void + on_case_begin (std::string const& name) override + { + m_case = case_results (name); + } + + virtual + void + on_case_end() override + { + if (m_case.tests.size() > 0) + m_suite.insert (std::move (m_case)); + } + + virtual + void + on_pass() override + { + m_case.tests.pass(); + } + + virtual + void + on_fail (std::string const& reason) override + { + m_case.tests.fail (reason); + } + + virtual + void + on_log (std::string const& s) override + { + m_case.log.insert (s); + } +}; + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/reporter.h b/beast/unit_test/reporter.h new file mode 100644 index 00000000..ac2937ee --- /dev/null +++ b/beast/unit_test/reporter.h @@ -0,0 +1,207 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_REPORTER_H_INLCUDED +#define BEAST_UNIT_TEST_REPORTER_H_INLCUDED + +#include "amount.h" +#include "recorder.h" + +#include "../streams/abstract_ostream.h" +#include "../streams/basic_std_ostream.h" + +#include +#include + +#include +#include + +namespace beast { +namespace unit_test { + +/** A simple test runner that writes everything to a stream in real time. + The totals are output when the object is destroyed. +*/ +class reporter : public runner +{ +private: + struct case_results + { + std::string name; + std::size_t total; + std::size_t failed; + + case_results (std::string const& name_ = "") + : name (name_) + , total (0) + , failed (0) + { + } + }; + + struct suite_results + { + std::string name; + std::size_t cases; + std::size_t total; + std::size_t failed; + + explicit + suite_results (std::string const& name_ = "") + : name (name_) + , cases (0) + , total (0) + , failed (0) + { + } + + void + add (case_results const& r) + { + ++cases; + total += r.total; + failed += r.failed; + } + }; + + struct results + { + std::size_t suites; + std::size_t cases; + std::size_t total; + std::size_t failed; + + results() + : suites (0) + , cases (0) + , total (0) + , failed (0) + { + } + + void + add (suite_results const& r) + { + ++suites; + total += r.total; + cases += r.cases; + failed += r.failed; + } + }; + + boost::optional m_std_ostream; + std::reference_wrapper m_stream; + results m_results; + suite_results m_suite; + case_results m_case; + +public: + reporter (reporter const&) = delete; + reporter& operator= (reporter const&) = delete; + + explicit reporter (std::ostream& stream = std::cout) + : m_std_ostream (boost::ref (stream)) + , m_stream (*m_std_ostream) + { + } + + ~reporter() + { + m_stream.get() << + amount (m_results.suites, "suite") << ", " << + amount (m_results.cases, "case") << ", " << + amount (m_results.total, "test") << " total, " << + amount (m_results.failed, "failure") + ; + } + + explicit reporter (abstract_ostream& stream) + : m_stream (stream) + { + } + +private: + virtual + void + on_suite_begin (suite_info const& info) override + { + m_suite = suite_results (info.full_name()); + } + + virtual + void + on_suite_end() override + { + m_results.add (m_suite); + } + + virtual + void + on_case_begin (std::string const& name) override + { + m_case = case_results (name); + + m_stream.get() << + m_suite.name << + (m_case.name.empty() ? + "" : (" " + m_case.name)) + ; + } + + virtual + void + on_case_end() override + { + m_suite.add (m_case); + } + + virtual + void + on_pass() override + { + ++m_case.total; + } + + virtual + void + on_fail (std::string const& reason) override + { + ++m_case.failed; + ++m_case.total; + + m_stream.get() << + "#" << m_case.total << + " failed" << + (reason.empty() ? "" : ": ") << reason + ; + } + + virtual + void + on_log (std::string const& s) override + { + m_stream.get() << + s; + } +}; + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/results.h b/beast/unit_test/results.h new file mode 100644 index 00000000..6dcecd84 --- /dev/null +++ b/beast/unit_test/results.h @@ -0,0 +1,256 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_RESULTS_H_INLCUDED +#define BEAST_UNIT_TEST_RESULTS_H_INLCUDED + +#include "../container/const_container.h" + +#include +#include + +namespace beast { +namespace unit_test { + +/** Holds a set of test condition outcomes in a testcase. */ +class case_results +{ +public: + /** Holds the result of evaluating one test condition. */ + struct test + { + explicit test (bool pass_) + : pass (pass_) + { + } + + test (bool pass_, std::string const& reason_) + : pass (pass_) + , reason (reason_) + { + } + + bool pass; + std::string reason; + }; + +private: + class tests_t + : public const_container > + { + private: + std::size_t m_failed; + + public: + tests_t () + : m_failed (0) + { + } + + /** Returns the total number of test conditions. */ + std::size_t + total() const + { + return cont().size(); + } + + /** Returns the number of failed test conditions. */ + std::size_t + failed() const + { + return m_failed; + } + + /** Register a successful test condition. */ + void + pass() + { + cont().emplace_back (true); + } + + /** Register a failed test condition. */ + void + fail (std::string const& reason = "") + { + ++m_failed; + cont().emplace_back (false, reason); + } + }; + + class log_t + : public const_container > + { + public: + /** Insert a string into the log. */ + void + insert (std::string const& s) + { + cont().push_back (s); + } + }; + + std::string m_name; + +public: + explicit case_results (std::string const& name = "") + : m_name (name) + { + } + + /** Returns the name of this testcase. */ + std::string const& + name() const + { + return m_name; + } + + /** Memberspace for a container of test condition outcomes. */ + tests_t tests; + + /** Memberspace for a container of testcase log messages. */ + log_t log; +}; + +//-------------------------------------------------------------------------- + +/** Holds the set of testcase results in a suite. */ +class suite_results + : public const_container > +{ +private: + std::string m_name; + std::size_t m_total; + std::size_t m_failed; + +public: + explicit suite_results (std::string const& name = "") + : m_name (name) + , m_total (0) + , m_failed (0) + { + } + + /** Returns the name of this suite. */ + std::string const& + name() const + { + return m_name; + } + + /** Returns the total number of test conditions. */ + std::size_t + total() const + { + return m_total; + } + + /** Returns the number of failures. */ + std::size_t + failed() const + { + return m_failed; + } + + /** Insert a set of testcase results. */ + /** @{ */ + void + insert (case_results&& r) + { + cont().emplace_back (std::move (r)); + m_total += r.tests.total(); + m_failed += r.tests.failed(); + } + + void + insert (case_results const& r) + { + cont().push_back (r); + m_total += r.tests.total(); + m_failed += r.tests.failed(); + } + /** @} */ +}; + +//------------------------------------------------------------------------------ + +// VFALCO TODO Make this a template class using scoped allocators +/** Holds the results of running a set of testsuites. */ +class results + : public const_container > +{ +private: + std::size_t m_cases; + std::size_t m_total; + std::size_t m_failed; + +public: + results() + : m_cases (0) + , m_total (0) + , m_failed (0) + { + } + + /** Returns the total number of test cases. */ + std::size_t + cases() const + { + return m_cases; + } + + /** Returns the total number of test conditions. */ + std::size_t + total() const + { + return m_total; + } + + /** Returns the number of failures. */ + std::size_t + failed() const + { + return m_failed; + } + + /** Insert a set of suite results. */ + /** @{ */ + void + insert (suite_results&& r) + { + m_cases += r.size(); + m_total += r.total(); + m_failed += r.failed(); + cont().emplace_back (std::move (r)); + } + + void + insert (suite_results const& r) + { + m_cases += r.size(); + m_total += r.total(); + m_failed += r.failed(); + cont().push_back (r); + } + /** @} */ +}; + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/runner.h b/beast/unit_test/runner.h new file mode 100644 index 00000000..d2b55e75 --- /dev/null +++ b/beast/unit_test/runner.h @@ -0,0 +1,272 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_RUNNER_H_INCLUDED +#define BEAST_UNIT_TEST_RUNNER_H_INCLUDED + +#include "suite_info.h" + +#include "../streams/abstract_ostream.h" + +#include +#include + +namespace beast { +namespace unit_test { + +/** Unit test runner interface. + Derived classes can customize the reporting behavior. This interface is + injected into the unit_test class to receive the results of the tests. +*/ +class runner +{ +private: + // Reroutes log output to the runner + class stream_t : public abstract_ostream + { + private: + runner& m_owner; + + public: + stream_t() = delete; + stream_t& operator= (stream_t const&) = delete; + + stream_t (runner& owner) + : m_owner (owner) + { + } + + void + write (string_type const& s) + { + m_owner.log (s); + } + }; + + stream_t m_stream; + bool m_default; + bool m_failed; + bool m_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) + { + } + + /** Run the specified suite. + @return `true` if any conditions failed. + */ + 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 a sequence of suites. + The expression + `FwdIter::value_type` + must be convertible to `suite_info`. + @return `true` if any conditions failed. + */ + template + bool + run (FwdIter first, FwdIter last) + { + bool failed (false); + for (;first != last; ++first) + failed = run (*first) || failed; + return failed; + } + + /** Conditionally run a sequence of suites. + pred will be called as: + @code + bool pred (suite_info const&); + @endcode + @return `true` if any conditions failed. + */ + template + 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 all suites in a container. + @return `true` if any conditions failed. + */ + template + bool + run_each (SequenceContainer const& c) + { + bool failed (false); + for (auto const& s : c) + failed = run (s) || failed; + return failed; + } + + /** Conditionally run suites in a container. + pred will be called as: + @code + bool pred (suite_info const&); + @endcode + @return `true` if any conditions failed. + */ + template + 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; + } + +private: + // + // Overrides + // + + /** Called when a new suite starts. */ + virtual + void + on_suite_begin (suite_info const&) + { + } + + /** Called when a suite ends. */ + virtual + void + on_suite_end() + { + } + + /** Called when a new case starts. */ + virtual + void + on_case_begin (std::string const&) + { + } + + /** Called when a new case ends. */ + virtual + void + on_case_end() + { + } + + /** Called for each passing condition. */ + virtual + void + on_pass () + { + } + + /** Called for each failing condition. */ + virtual + void + on_fail (std::string const&) + { + } + + /** Called when a test logs output. */ + virtual + void + on_log (std::string const&) + { + } + +private: + friend class suite; + + abstract_ostream& + stream() + { + return m_stream; + } + + // Start a new testcase. + 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); + } + + void + pass() + { + if (m_default) + testcase (""); + on_pass(); + m_cond = true; + } + + void + fail (std::string const& reason) + { + if (m_default) + testcase (""); + on_fail (reason); + m_failed = true; + m_cond = true; + } + + void + log (std::string const& s) + { + if (m_default) + testcase (""); + on_log (s); + } +}; + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/suite.h b/beast/unit_test/suite.h new file mode 100644 index 00000000..1bd157be --- /dev/null +++ b/beast/unit_test/suite.h @@ -0,0 +1,289 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_SUITE_H_INCLUDED +#define BEAST_UNIT_TEST_SUITE_H_INCLUDED + +#include "runner.h" + +#include "../utility/noexcept.h" +#include + +namespace beast { +namespace unit_test { + +/** 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 + translation unit. +*/ +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 + { + char const* + what() const noexcept override + { + return "suite aborted on failed condition"; + } + }; + + // Memberspace + class log_t + { + private: + friend class suite; + runner* m_runner; + + runner* + operator-> () + { + return m_runner; + } + + public: + log_t () + : m_runner (nullptr) + { + } + + template + abstract_ostream::scoped_stream_type + operator<< (T const& t) + { + return m_runner->stream() << t; + } + + /** Returns the raw stream used for output. */ + abstract_ostream& + stream() + { + return m_runner->stream(); + } + }; + + bool m_abort = false; + +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(); + + @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 + */ + typedef abstract_ostream::scoped_stream_type scoped_stream; + + /** Memberspace for logging. */ + log_t log; + + /** 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 + forwarded constructor arguments to the base. + 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); + } + + /** Evaluate a test condition. + The condition is passed as a template argument instead of `bool` so + that implicit conversion is not required. The `reason` argument is + logged if the condition is false. + @return `true` if the test condition indicates success. + */ + template + bool + expect (Condition shouldBeTrue, std::string const& reason = "") + { + if (shouldBeTrue) + pass(); + else + fail (reason); + return shouldBeTrue; + } + + // DEPRECATED + // @return `true` if the test condition indicates success (a false value) + template + bool + unexpected (Condition shouldBeFalse, std::string const& reason = "") + { + if (! shouldBeFalse) + pass(); + else + fail (reason); + return ! shouldBeFalse; + } + + /** Record a successful test condition. */ + void + pass() + { + log->pass(); + } + + /** Record a failure. */ + void + fail (std::string const& reason= "") + { + log->fail (reason); + if (m_abort) + throw abort_exception(); + } + +private: + /** Runs the suite. */ + virtual + void + run() = 0; +}; + +} // unit_test +} // beast + +//------------------------------------------------------------------------------ + +// 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 ( \ + #Class, #Module, #Library, manual); + +//------------------------------------------------------------------------------ + +// Preprocessor directives for controlling unit test definitions. + +// If this is already defined, don't redefine it. This allows +// programs to provide custom behavior for testsuite definitions +// +#ifndef BEAST_DEFINE_TESTSUITE + +/** Enables insertion of test suites into the global container. + The default is to insert all test suite definitions into the global + container. If BEAST_DEFINE_TESTSUITE is user defined, this macro + has no effect. +*/ +#ifndef BEAST_NO_UNIT_TEST_INLINE +#define BEAST_NO_UNIT_TEST_INLINE 0 +#endif + +/** Define a unit test suite. + + Class The type representing the class being tested. + Module Identifies the module. + Library Identifies the library. + + The declaration for the class implementing the test should be the same + as Class ## _test. For example, if Class is aged_ordered_container, the + test class must be declared as: + + @code + + struct aged_ordered_container_test : beast::unit_test::suite + { + //... + }; + + @endcode + + The macro invocation must appear in the same namespace as the test class. +*/ + +#if BEAST_NO_UNIT_TEST_INLINE +#define BEAST_DEFINE_TESTSUITE(Class,Module,Library) + +#else +#include "global_suites.h" +#define BEAST_DEFINE_TESTSUITE(Class,Module,Library) \ + BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,false) +#define BEAST_DEFINE_TESTSUITE_MANUAL(Class,Module,Library) \ + BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,true) + +#endif + +#endif + +//------------------------------------------------------------------------------ + +#endif diff --git a/beast/unit_test/suite_info.h b/beast/unit_test/suite_info.h new file mode 100644 index 00000000..ca86236f --- /dev/null +++ b/beast/unit_test/suite_info.h @@ -0,0 +1,125 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_SUITE_INFO_H_INCLUDED +#define BEAST_UNIT_TEST_SUITE_INFO_H_INCLUDED + +#include +#include +#include + +namespace beast { +namespace unit_test { + +class runner; + +/** Associates a unit test type with metadata. */ +class suite_info +{ +private: + typedef std::function run_type; + + char const* m_name; + char const* m_module; + char const* m_library; + bool m_manual; + 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)) + { + } + + char const* + name() const + { + return m_name; + } + + char const* + module() const + { + return m_module; + } + + char const* + library() const + { + return m_library; + } + + /** Returns `true` if this suite only runs manually. */ + bool + manual() const + { + return m_manual; + } + + /** Return the canonical suite name as a string. */ + std::string + full_name() const + { + return + std::string (m_library) + "." + + std::string (m_module) + "." + + std::string (m_name); + } + + /** Run a new instance of the associated test suite. */ + void + run (runner& r) const + { + m_run (r); + } +}; + +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 +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) + { + Suite test; + return test (r); + }); +} + +} // unit_test +} // beast + +#endif diff --git a/beast/unit_test/suite_list.h b/beast/unit_test/suite_list.h new file mode 100644 index 00000000..3cc534fc --- /dev/null +++ b/beast/unit_test/suite_list.h @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UNIT_TEST_SUITE_LIST_H_INCLUDED +#define BEAST_UNIT_TEST_SUITE_LIST_H_INCLUDED + +#include "suite_info.h" + +#include "../container/const_container.h" + +#include +//#include +#include +#include +#include + +namespace beast { +namespace unit_test { + +/** A container of test suites. */ +class suite_list + : public const_container < + std::set + //std::list + > +{ +private: +#ifndef NDEBUG + std::unordered_set m_names; + std::unordered_set m_classes; +#endif + +public: + /** Insert a suite into the set. + The suite must not already exist. + */ + template + 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 ( + name, module, library, manual))); + } +}; + +} // unit_test +} // beast + +#endif + diff --git a/beast/utility/Utility.cpp b/beast/utility/Utility.cpp index 48175d75..9b42c073 100644 --- a/beast/utility/Utility.cpp +++ b/beast/utility/Utility.cpp @@ -26,10 +26,11 @@ // For Journal and Debug #include "../../modules/beast_core/beast_core.h" -#include "impl/Assert.cpp" #include "impl/Debug.cpp" #include "impl/Journal.cpp" #include "impl/LeakChecked.cpp" #include "impl/StaticObject.cpp" #include "impl/PropertyStream.cpp" + +#include "tests/bassert.test.cpp" #include "tests/empty_base_optimization.test.cpp" diff --git a/beast/utility/impl/Debug.cpp b/beast/utility/impl/Debug.cpp index d3a26e0a..8448e188 100644 --- a/beast/utility/impl/Debug.cpp +++ b/beast/utility/impl/Debug.cpp @@ -17,6 +17,9 @@ */ //============================================================================== +#include "../Debug.h" +#include "../../unit_test/suite.h" + namespace beast { namespace Debug { @@ -299,7 +302,7 @@ String commandLineToString (const String& commandLine) // A simple unit test to determine the diagnostic settings in a build. // -class DebugTests : public UnitTest +class Debug_test : public unit_test::suite { public: static int envDebug () @@ -329,25 +332,34 @@ public: #endif } - void runTest () + void run () { - beginTestCase ("diagnostics"); + log << + "operatingSystemName = '" << + SystemStats::getOperatingSystemName () << "'"; + + log << + "_DEBUG = " << + String::fromNumber (envDebug ()); + + log << + "BEAST_DEBUG = " << + String::fromNumber (beastDebug ()); + + log << + "BEAST_FORCE_DEBUG = " << + String::fromNumber (beastForceDebug ()); + + log << + "sizeof(std::size_t) = " << + String::fromNumber (sizeof(std::size_t)); - logMessage ("operatingSystemName = '" + SystemStats::getOperatingSystemName () + "'"); - logMessage ("_DEBUG = " + String::fromNumber (envDebug ())); - logMessage ("BEAST_DEBUG = " + String::fromNumber (beastDebug ())); - logMessage ("BEAST_FORCE_DEBUG = " + String::fromNumber (beastForceDebug ())); - logMessage ("sizeof(std::size_t) = " + String::fromNumber (sizeof(std::size_t))); bassertfalse; fail (); } - - DebugTests () : UnitTest ("Debug", "beast", runManual) - { - } }; -static DebugTests debugTests; +BEAST_DEFINE_TESTSUITE_MANUAL(Debug,utility,beast); } diff --git a/beast/utility/impl/PropertyStream.cpp b/beast/utility/impl/PropertyStream.cpp index f3b6e750..7ea88bb3 100644 --- a/beast/utility/impl/PropertyStream.cpp +++ b/beast/utility/impl/PropertyStream.cpp @@ -18,6 +18,7 @@ //============================================================================== #include "../PropertyStream.h" +#include "../../unit_test/suite.h" #include #include @@ -606,7 +607,7 @@ void PropertyStream::add (long double value) //------------------------------------------------------------------------------ -class PropertyStreamTests : public UnitTest +class PropertyStream_test : public unit_test::suite { public: typedef PropertyStream::Source Source; @@ -622,8 +623,8 @@ public: } catch (...) { - failException (); - } + fail ("unhandled exception");; + } } void test_peel_leading_slash (std::string s, std::string const& expected, @@ -637,7 +638,7 @@ public: } catch(...) { - failException (); + fail ("unhandled exception");; } } @@ -652,7 +653,7 @@ public: } catch (...) { - failException (); + fail ("unhandled exception");; } } @@ -665,7 +666,7 @@ public: } catch (...) { - failException (); + fail ("unhandled exception");; } } @@ -679,7 +680,7 @@ public: } catch (...) { - failException (); + fail ("unhandled exception");; } } @@ -693,7 +694,7 @@ public: } catch(...) { - failException (); + fail ("unhandled exception");; } } @@ -708,11 +709,11 @@ public: } catch (...) { - failException (); + fail ("unhandled exception");; } } - void runTest() + void run() { Source a ("a"); Source b ("b"); @@ -733,19 +734,19 @@ public: b.add ( e ); d.add ( f ); - beginTestCase ("peel_name"); + testcase ("peel_name"); test_peel_name ("a", "a", ""); test_peel_name ("foo/bar", "foo", "bar"); test_peel_name ("foo/goo/bar", "foo", "goo/bar"); test_peel_name ("", "", ""); - beginTestCase ("peel_leading_slash"); + testcase ("peel_leading_slash"); test_peel_leading_slash ("foo/", "foo/", false); test_peel_leading_slash ("foo", "foo", false); test_peel_leading_slash ("/foo/", "foo/", true); test_peel_leading_slash ("/foo", "foo", true); - beginTestCase ("peel_trailing_slashstar"); + testcase ("peel_trailing_slashstar"); test_peel_trailing_slashstar ("/foo/goo/*", "/foo/goo", true); test_peel_trailing_slashstar ("foo/goo/*", "foo/goo", true); test_peel_trailing_slashstar ("/foo/goo/", "/foo/goo", false); @@ -757,13 +758,13 @@ public: test_peel_trailing_slashstar ("**", "*", true); test_peel_trailing_slashstar ("*/", "*", false); - beginTestCase ("find_one"); + testcase ("find_one"); test_find_one (a, &b, "b"); test_find_one (a, nullptr, "d"); test_find_one (b, &e, "e"); test_find_one (d, &f, "f"); - beginTestCase ("find_path"); + testcase ("find_path"); test_find_path (a, "a", nullptr); test_find_path (a, "e", nullptr); test_find_path (a, "a/b", nullptr); @@ -774,14 +775,14 @@ public: test_find_path (a, "b/e", &e); test_find_path (a, "b/d/f", &f); - beginTestCase ("find_one_deep"); + testcase ("find_one_deep"); test_find_one_deep (a, "z", nullptr); test_find_one_deep (a, "g", &g); test_find_one_deep (a, "b", &b); test_find_one_deep (a, "d", &d); test_find_one_deep (a, "f", &f); - beginTestCase ("find"); + testcase ("find"); test_find (a, "", &a, false); test_find (a, "*", &a, true); test_find (a, "/b", &b, false); @@ -798,14 +799,9 @@ public: test_find (a, "/d*", nullptr, true); test_find (a, "/d/*", nullptr, true); } - - PropertyStreamTests () - : UnitTest ("PropertyStream", "beast") - { - } }; -static PropertyStreamTests propertyStreamTests; +BEAST_DEFINE_TESTSUITE(PropertyStream,utility,beast); } diff --git a/beast/utility/impl/Assert.cpp b/beast/utility/tests/bassert.test.cpp similarity index 78% rename from beast/utility/impl/Assert.cpp rename to beast/utility/tests/bassert.test.cpp index d7503cc2..2da5c702 100644 --- a/beast/utility/impl/Assert.cpp +++ b/beast/utility/tests/bassert.test.cpp @@ -17,21 +17,23 @@ */ //============================================================================== -namespace beast { +#include "../../Config.h" -class BassertUnitTests : public UnitTest +#include "../../unit_test/suite.h" + +namespace beast { + +// This demonstrates what happens when a bassert condition fails +class bassert_test : public unit_test::suite { public: - void runTest () + void run () { - beginTestCase ("bassert"); bassert (false); + pass(); } - - BassertUnitTests () : UnitTest ("bassert", "beast", runManual) { } }; -//------------------------------------------------------------------------------ +BEAST_DEFINE_TESTSUITE_MANUAL(bassert,utility,beast); -static BassertUnitTests bassertUnitTests; -} +} // beast diff --git a/beast/utility/tests/empty_base_optimization.test.cpp b/beast/utility/tests/empty_base_optimization.test.cpp index 54c96741..57c57287 100644 --- a/beast/utility/tests/empty_base_optimization.test.cpp +++ b/beast/utility/tests/empty_base_optimization.test.cpp @@ -23,12 +23,12 @@ #include "../empty_base_optimization.h" -#include "../../../modules/beast_core/beast_core.h" // for UnitTest +#include "../../unit_test/suite.h" namespace beast { -class empty_base_optimization_Tests - : public UnitTest +class empty_base_optimization_test + : public unit_test::suite { public: template @@ -94,20 +94,14 @@ public: } void - runTest () + run () { - beginTestCase ("empty_base_optimization"); expect (test_one()); expect (test_two()); pass (); } - - empty_base_optimization_Tests() - : UnitTest ("empty_base_optimization", "beast") - { - } }; -static empty_base_optimization_Tests empty_base_optimization_tests; +BEAST_DEFINE_TESTSUITE(empty_base_optimization,utility,beast); -} // beast +} // beast diff --git a/modules/beast_asio/beast_asio.cpp b/modules/beast_asio/beast_asio.cpp index 7e21a743..6c95da66 100644 --- a/modules/beast_asio/beast_asio.cpp +++ b/modules/beast_asio/beast_asio.cpp @@ -51,8 +51,6 @@ #include "tests/TestPeerLogicAsyncClient.cpp" #include "tests/TestPeerUnitTests.cpp" -#include "system/BoostUnitTests.cpp" - #include "http/HTTPParser.cpp" #include "http/HTTPRequestParser.cpp" #include "http/HTTPResponseParser.cpp" diff --git a/modules/beast_asio/http/HTTPClientType.cpp b/modules/beast_asio/http/HTTPClientType.cpp index 2cb043cc..dae2052d 100644 --- a/modules/beast_asio/http/HTTPClientType.cpp +++ b/modules/beast_asio/http/HTTPClientType.cpp @@ -19,6 +19,7 @@ #include "../../../beast/asio/wrap_handler.h" #include "../../../beast/asio/placeholders.h" +#include "../../../beast/unit_test/suite.h" namespace beast { namespace asio { @@ -545,7 +546,7 @@ HTTPClientBase* HTTPClientBase::New (Journal journal, //------------------------------------------------------------------------------ -class HTTPClientTests : public UnitTest +class HTTPClient_test : public unit_test::suite { public: typedef boost::system::error_code error_code; @@ -592,35 +593,38 @@ public: //-------------------------------------------------------------------------- - void log (HTTPMessage const& m) + void print (HTTPMessage const& m) { for (std::size_t i = 0; i < m.headers().size(); ++i) { HTTPField const f (m.headers()[i]); - String s; - s = "[ '" + f.name() + - "' , '" + f.value() + "' ]"; - logMessage (s); + std::stringstream ss; + log << + "[ '" << f.name() << + "' , '" << f.value() + "' ]"; } } - void log (HTTPClientBase::error_type error, HTTPClientBase::value_type const& response) + void print (HTTPClientBase::error_type error, + HTTPClientBase::value_type const& response) { if (error != 0) { - logMessage (String ( - "HTTPClient error: '" + error.message() + "'")); + log << + "HTTPClient error: '" + error.message() << "'"; } else if (! response.empty ()) { - logMessage (String ("Status: ") + - String::fromNumber (response->status())); + log << + "Status: " << + String::fromNumber (response->status()).toStdString(); - log (*response); + print (*response); } else { - logMessage ("HTTPClient: no response"); + log << + "HTTPClient: no response"; } } @@ -628,7 +632,7 @@ public: void handle_get (HTTPClientBase::result_type result) { - log (result.first, result.second); + print (result.first, result.second); } void testSync (String const& s, double timeoutSeconds) @@ -639,7 +643,7 @@ public: HTTPClientBase::result_type const& result ( client->get (ParsedURL (s).url ())); - log (result.first, result.second); + print (result.first, result.second); } void testAsync (String const& s, double timeoutSeconds) @@ -649,7 +653,7 @@ public: HTTPClientBase::New (Journal(), timeoutSeconds)); client->async_get (t.get_io_service (), ParsedURL (s).url (), - beast::bind (&HTTPClientTests::handle_get, this, + beast::bind (&HTTPClient_test::handle_get, this, beast::_1)); t.start (); @@ -658,10 +662,8 @@ public: //-------------------------------------------------------------------------- - void runTest () + void run () { - beginTestCase ("HTTPClient::get"); - testSync ( "http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html", 5); @@ -676,13 +678,9 @@ public: pass (); } - - HTTPClientTests () : UnitTest ("HttpClient", "beast", runManual) - { - } }; -static HTTPClientTests httpClientTests; +BEAST_DEFINE_TESTSUITE_MANUAL(HTTPClient,beast_asio,beast); } } diff --git a/modules/beast_asio/system/BoostIncludes.h b/modules/beast_asio/system/BoostIncludes.h index 1a5c45df..609041cb 100644 --- a/modules/beast_asio/system/BoostIncludes.h +++ b/modules/beast_asio/system/BoostIncludes.h @@ -52,33 +52,9 @@ #include #include #include +#include // work-around for broken #include "../../../beast/boost/get_pointer.h" -// Continuation hooks added in 1.54.0 -#ifndef BEAST_ASIO_HAS_CONTINUATION_HOOKS -# if BOOST_VERSION >= 105400 -# define BEAST_ASIO_HAS_CONTINUATION_HOOKS 1 -# else -# define BEAST_ASIO_HAS_CONTINUATION_HOOKS 0 -# endif -#endif -#if BEAST_ASIO_HAS_CONTINUATION_HOOKS -# include -#endif - -//------------------------------------------------------------------------------ - -// Configure some options based on the version of boost -#if BOOST_VERSION >= 105400 -# ifndef BEAST_ASIO_HAS_BUFFEREDHANDSHAKE -# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 1 -# endif -#else -# ifndef BEAST_ASIO_HAS_BUFFEREDHANDSHAKE -# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 0 -# endif -#endif - #endif diff --git a/modules/beast_asio/system/BoostUnitTests.cpp b/modules/beast_asio/system/BoostUnitTests.cpp deleted file mode 100644 index 8995e564..00000000 --- a/modules/beast_asio/system/BoostUnitTests.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -namespace beast { - -/** Test for showing information about the build of boost. -*/ -class BoostUnitTests : public UnitTest -{ -public: - struct BoostVersion - { - explicit BoostVersion (int value) - : vmajor (value / 100000) - , vminor ((value / 100) % 100) - , vpatch (value % 100) - { - } - - String toString () const noexcept - { - return String (vmajor) + "." + - String (vminor).paddedLeft ('0', 2) + "." + - String (vpatch).paddedLeft ('0', 2); - } - - int vmajor; - int vminor; - int vpatch; - }; - - enum - { - minimumVersion = 104700 - }; - - // To prevent constant conditional expression warning - static int getMinimumVersion () - { - return minimumVersion; - } - - void runTest () - { - beginTestCase ("version"); - - BoostVersion version (BOOST_VERSION); - - logMessage (String ("BOOST_VERSION = " + version.toString ())); - logMessage (String ("BOOST_LIB_VERSION = '") + BOOST_LIB_VERSION + "'"); - - if (BOOST_VERSION >= getMinimumVersion ()) - { - pass (); - } - else - { - fail (String ("Boost version is below ") + - BoostVersion (minimumVersion).toString ()); - } - } - - BoostUnitTests () : UnitTest ("boost", "beast") - { - } -}; - -static BoostUnitTests boostUnitTests; - -} diff --git a/modules/beast_asio/tests/PeerTest.cpp b/modules/beast_asio/tests/PeerTest.cpp index 2666a924..54bc467c 100644 --- a/modules/beast_asio/tests/PeerTest.cpp +++ b/modules/beast_asio/tests/PeerTest.cpp @@ -65,11 +65,14 @@ String PeerTest::Result::message () const noexcept return m_message; } -bool PeerTest::Result::report (UnitTest& test, bool reportPassingTests) const +bool PeerTest::Result::report (unit_test::suite& suite, + bool reportPassingTests) const { - bool const success = test.unexpected (failed (), message ()); + bool const success = suite.expect (! failed (), + message ().toStdString()); if (reportPassingTests && success) - test.logMessage (String ("pass ") + message()); + suite.log << + "pass " + message().toStdString(); return success; } @@ -90,14 +93,15 @@ bool PeerTest::Results::operator!= (Results const& other) const noexcept return (client != other.client) || (server != other.server); } -bool PeerTest::Results::report (UnitTest& test, bool beginTestCase) const +bool PeerTest::Results::report (unit_test::suite& suite, + bool beginTestCase) const { if (beginTestCase) - test.beginTestCase (name); + suite.testcase (name.toStdString()); bool success = true; - if (! client.report (test)) + if (! client.report (suite)) success = false; - if (! server.report (test)) + if (! server.report (suite)) success = false; return success; } diff --git a/modules/beast_asio/tests/PeerTest.h b/modules/beast_asio/tests/PeerTest.h index 7f1f5f9f..6020db5d 100644 --- a/modules/beast_asio/tests/PeerTest.h +++ b/modules/beast_asio/tests/PeerTest.h @@ -20,6 +20,8 @@ #ifndef BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED #define BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED +#include "../../../beast/unit_test/suite.h" + namespace beast { namespace asio { @@ -67,14 +69,15 @@ public: bool timedout () const noexcept; /** Provides a descriptive message. - This is suitable to pass to UnitTest::fail. + This is suitable to pass to suite::fail. */ String message () const noexcept; - /** Report the result to a UnitTest object. + /** Report the result to a testsuite. A return value of true indicates success. */ - bool report (UnitTest& test, bool reportPassingTests = false) const; + bool report (unit_test::suite& suite, + bool reportPassingTests = false) const; private: boost::system::error_code m_ec; @@ -97,19 +100,21 @@ public: bool operator== (Results const& other) const noexcept; bool operator!= (Results const& other) const noexcept; - /** Report the results to a UnitTest object. + /** Report the results to a suite object. A return value of true indicates success. @param beginTestCase `true` to call test.beginTestCase for you */ - bool report (UnitTest& test, bool beginTestCase = true) const; + bool report (unit_test::suite& suite, bool beginTestCase = true) const; }; //-------------------------------------------------------------------------- /** Test two peers and return the results. */ - template - static Results run (ClientArg const& clientArg, ServerArg const& serverArg, int timeoutSeconds = defaultTimeoutSeconds) + template + static Results run (ClientArg const& clientArg, ServerArg const& serverArg, + int timeoutSeconds = defaultTimeoutSeconds) { Results results; @@ -199,42 +204,40 @@ public: return results; } - template + template static Results run (Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds) { - return run (arg, arg, timeoutSeconds); + return run ( + arg, arg, timeoutSeconds); } //-------------------------------------------------------------------------- - /** Reports tests of Details for all known asynchronous logic combinations to a UnitTest. - */ - template - static void report_async (UnitTest& test, Arg const& arg, + template + static void report_async (unit_test::suite& suite, Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds, bool beginTestCase = true) { run - (arg, timeoutSeconds).report (test, beginTestCase); + (arg, timeoutSeconds).report (suite, beginTestCase); } - /** Reports tests of Details against all known logic combinations to a UnitTest. - */ - template - static void report (UnitTest& test, Arg const& arg, - int timeoutSeconds = defaultTimeoutSeconds, - bool beginTestCase = true) + template + static + void + report (unit_test::suite& suite, Arg const& arg, + int timeoutSeconds = defaultTimeoutSeconds, bool beginTestCase = true) { run - (arg, timeoutSeconds).report (test, beginTestCase); + (arg, timeoutSeconds).report (suite, beginTestCase); run - (arg, timeoutSeconds).report (test, beginTestCase); + (arg, timeoutSeconds).report (suite, beginTestCase); run - (arg, timeoutSeconds).report (test, beginTestCase); + (arg, timeoutSeconds).report (suite, beginTestCase); - report_async
(test, arg, timeoutSeconds, beginTestCase); + report_async
(suite, arg, timeoutSeconds, beginTestCase); } }; diff --git a/modules/beast_asio/tests/TestPeerUnitTests.cpp b/modules/beast_asio/tests/TestPeerUnitTests.cpp index fa600a82..22dfc772 100644 --- a/modules/beast_asio/tests/TestPeerUnitTests.cpp +++ b/modules/beast_asio/tests/TestPeerUnitTests.cpp @@ -17,11 +17,13 @@ */ //============================================================================== +#include "../../../beast/unit_test/suite.h" + namespace beast { namespace asio { -/** UnitTest for the TestPeer family of objects. */ -class TestPeerUnitTests : public UnitTest +/** Test suite for the TestPeer family of objects. */ +class TestPeer_test : public unit_test::suite { public: @@ -31,7 +33,7 @@ public: PeerTest::report
(*this, arg, timeoutSeconds); } - void runTest () + void run () { typedef boost::asio::ip::tcp protocol; testDetails (protocol::v4 ()); @@ -44,13 +46,9 @@ public: { timeoutSeconds = 10 }; - - TestPeerUnitTests () : UnitTest ("TestPeer", "beast") - { - } }; -static TestPeerUnitTests testPeerUnitTests; +BEAST_DEFINE_TESTSUITE(TestPeer,beast_asio,beast); } } diff --git a/modules/beast_core/beast_core.cpp b/modules/beast_core/beast_core.cpp index 87a46701..07f0e1de 100644 --- a/modules/beast_core/beast_core.cpp +++ b/modules/beast_core/beast_core.cpp @@ -128,7 +128,6 @@ #include "diagnostic/FatalError.cpp" #include "diagnostic/SemanticVersion.cpp" -#include "diagnostic/UnitTest.cpp" #include "diagnostic/UnitTestUtilities.cpp" #include "files/DirectoryIterator.cpp" @@ -145,7 +144,6 @@ #include "memory/MemoryBlock.cpp" -#include "misc/Main.cpp" #include "misc/Result.cpp" #include "streams/FileInputSource.cpp" diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h index 5a23a33a..26776e88 100644 --- a/modules/beast_core/beast_core.h +++ b/modules/beast_core/beast_core.h @@ -166,7 +166,6 @@ class FileOutputStream; #include "files/TemporaryFile.h" #include "logging/Logger.h" #include "memory/SharedSingleton.h" -#include "misc/Main.h" #include "misc/WindowsRegistry.h" #include "streams/MemoryOutputStream.h" @@ -177,7 +176,6 @@ class FileOutputStream; #include "threads/HighResolutionTimer.h" #include "threads/InterProcessLock.h" #include "threads/Process.h" -#include "diagnostic/UnitTest.h" #include "xml/XmlDocument.h" #include "xml/XmlElement.h" #include "diagnostic/UnitTestUtilities.h" diff --git a/modules/beast_core/diagnostic/FatalError.cpp b/modules/beast_core/diagnostic/FatalError.cpp index 295c44ce..4585f623 100644 --- a/modules/beast_core/diagnostic/FatalError.cpp +++ b/modules/beast_core/diagnostic/FatalError.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { // // FatalError::Reporter @@ -112,26 +113,16 @@ FatalError::FatalError (char const* message, char const* fileName, int lineNumbe //------------------------------------------------------------------------------ -// Yes even this class can have a unit test. It's manually triggered though. -// -class FatalErrorTests : public UnitTest +class FatalError_test : public unit_test::suite { public: - FatalErrorTests () : UnitTest ("FatalError", "beast", runManual) + void run () { - } - - void runTest () - { - beginTestCase ("raise"); - - // We don't really expect the program to run after this - // but the unit test is here so you can manually test it. int shouldBeZero (1); check_invariant (shouldBeZero == 0); } }; -static FatalErrorTests fatalErrorTests; +BEAST_DEFINE_TESTSUITE_MANUAL(FatalError,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/diagnostic/SemanticVersion.cpp b/modules/beast_core/diagnostic/SemanticVersion.cpp index 56ffd366..732b74c7 100644 --- a/modules/beast_core/diagnostic/SemanticVersion.cpp +++ b/modules/beast_core/diagnostic/SemanticVersion.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { SemanticVersion::SemanticVersion () : majorVersion (0) @@ -288,13 +289,9 @@ bool SemanticVersion::chopIdentifiers (StringArray* value, bool allowLeadingZero //------------------------------------------------------------------------------ -class SemanticVersionTests : public UnitTest +class SemanticVersion_test: public unit_test::suite { public: - SemanticVersionTests () : UnitTest ("SemanticVersion", "beast") - { - } - void checkPass (String const& input, bool shouldPass = true) { SemanticVersion v; @@ -377,7 +374,7 @@ public: void testParse () { - beginTestCase ("parse"); + testcase ("parse"); check ("0.0.0"); check ("1.2.3"); @@ -511,7 +508,7 @@ public: checkLess ("0.9.9", "1.0.0"); } - void runTest () + void run () { testParse (); testValues (); @@ -519,6 +516,6 @@ public: } }; -static SemanticVersionTests semanticVersionTests; +BEAST_DEFINE_TESTSUITE(SemanticVersion,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/diagnostic/UnitTest.cpp b/modules/beast_core/diagnostic/UnitTest.cpp deleted file mode 100644 index c14a5c16..00000000 --- a/modules/beast_core/diagnostic/UnitTest.cpp +++ /dev/null @@ -1,484 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Portions of this file are from JUCE. - Copyright (c) 2013 - Raw Material Software Ltd. - Please visit http://www.juce.com - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -namespace beast -{ - -UnitTest::UnitTest (String const& className, - String const& packageName, - When when) - : m_className (className.removeCharacters (" ")) - , m_packageName (packageName.removeCharacters (" ")) - , m_when (when) - , m_runner (nullptr) -{ - getAllTests().add (this); -} - -UnitTest::~UnitTest() -{ - getAllTests().removeFirstMatchingValue (this); -} - -String UnitTest::getTestName() const noexcept -{ - String s; - s << m_packageName << "." << m_className; - return s; -} - -String const& UnitTest::getClassName() const noexcept -{ - return m_className; -} - -String const& UnitTest::getPackageName() const noexcept -{ - return m_packageName; -} - -Journal UnitTest::journal () const -{ - bassert (m_runner != nullptr); - return m_runner->journal(); -} - -UnitTest::TestList& UnitTest::getAllTests() -{ - static TestList s_tests; - - return s_tests; -} - -void UnitTest::initialise() -{ -} - -void UnitTest::shutdown() -{ -} - -ScopedPointer & UnitTest::run ( - UnitTests* const runner) -{ - bassert (runner != nullptr); - m_runner = runner; - m_random = m_runner->m_random; - - m_suite = new Suite (m_className, m_packageName); - - initialise(); - -#if 0 - try - { - runTest(); - } - catch (...) - { - failException (); - } -#else - runTest (); -#endif - - shutdown(); - - finishCase (); - - m_suite->secondsElapsed = RelativeTime ( - Time::getCurrentTime () - m_suite->whenStarted).inSeconds (); - - return m_suite; -} - -void UnitTest::logMessage (String const& message) -{ - m_runner->logMessage (message); -} - -void UnitTest::logReport (StringArray const& report) -{ - m_runner->logReport (report); -} - -void UnitTest::beginTestCase (String const& name) -{ - finishCase (); - - String s; - s << getTestName () << " : " << name; - logMessage (s); - - m_case = new Case (name, m_className); -} - -bool UnitTest::expect_bool (bool trueCondition, String const& failureMessage) -{ - if (trueCondition) - { - pass (); - } - else - { - fail (failureMessage); - } - - return trueCondition; -} - -bool UnitTest::unexpected_bool (bool falseCondition, String const& failureMessage) -{ - return expect (! falseCondition, failureMessage); -} - -void UnitTest::pass () -{ - // If this goes off it means you forgot to call beginTestCase()! - bassert (m_case != nullptr); - - m_case->items.add (Item (true)); -} - -void UnitTest::fail (String const& failureMessage) -{ - // If this goes off it means you forgot to call beginTestCase()! - bassert (m_case != nullptr); - - Item item (false, failureMessage); - - m_case->failures++; - int const caseNumber = m_case->items.add (Item (false, failureMessage)); - - String s; - s << "#" << String (caseNumber) << " failed: " << failureMessage; - logMessage (s); - - m_runner->onFailure (); -} - -void UnitTest::failException () -{ - Item item (false, "An exception was thrown"); - - if (m_case != nullptr) - { - m_case->failures++; - } - else - { - // This hack gives us a test case, to handle the condition where an - // exception was thrown before beginTestCase() was called. - // - beginTestCase ("Exception outside test case"); - } - - int const caseNumber = m_case->items.add (item); - - String s; - s << "#" << String (caseNumber) << " threw an exception "; - logMessage (s); - - m_runner->onFailure (); -} - -Random& UnitTest::random() -{ - // This method's only valid while the test is being run! - bassert (m_runner != nullptr); - - return m_random; -} - -//------------------------------------------------------------------------------ - -void UnitTest::finishCase () -{ - if (m_case != nullptr) - { - // If this goes off it means you forgot to - // report any passing test case items! - // - bassert (m_case->items.size () > 0); - - m_case->secondsElapsed = RelativeTime ( - Time::getCurrentTime () - m_case->whenStarted).inSeconds (); - - m_suite->tests += m_case->items.size (); - m_suite->failures += m_case->failures; - - m_suite->cases.add (m_case.release ()); - } -} - -//============================================================================== - -UnitTests::JournalSink::JournalSink (UnitTests& tests) - : m_tests (tests) -{ -} - -void UnitTests::JournalSink::write (Journal::Severity, std::string const& text) -{ - m_tests.logMessage (text); -} - -//============================================================================== - -UnitTests::UnitTests() - : m_assertOnFailure (false) - , m_sink (*this) -{ -} - -UnitTests::~UnitTests() -{ -} - -void UnitTests::setAssertOnFailure (bool shouldAssert) noexcept -{ - m_assertOnFailure = shouldAssert; -} - -UnitTests::Results const& UnitTests::getResults () const noexcept -{ - return *m_results; -} - -bool UnitTests::anyTestsFailed () const noexcept -{ - return m_results->failures > 0; -} - -UnitTests::TestList UnitTests::selectTests ( - String const& match, TestList const& tests) const noexcept -{ - TestList list; - list.ensureStorageAllocated (tests.size ()); - - int const indexOfDot = match.indexOfChar ('.'); - String const package = (indexOfDot == -1) ? match : match.substring (0, indexOfDot); - String const testname = (indexOfDot == -1) ? "" - : match.substring (indexOfDot + 1, match.length () + 1); - - if (package != String::empty) - { - if (testname != String::empty) - { - // "package.testname" : First test which matches - for (int i = 0; i < tests.size(); ++i) - { - UnitTest* const test = tests [i]; - if (package.equalsIgnoreCase (test->getPackageName ()) && - testname.equalsIgnoreCase (test->getClassName ())) - { - list.add (test); - break; - } - } - } - else - { - // Get all tests in the package - list = selectPackage (package, tests); - - // If no trailing slash on package, try tests - if (list.size () == 0 && indexOfDot == -1) - { - // Try "package" as a testname - list = selectTest (package, tests); - } - } - } - else if (testname != String::empty) - { - list = selectTest (testname, tests); - } - else - { - // All non manual tests - for (int i = 0; i < tests.size(); ++i) - { - UnitTest* const test = tests [i]; - if (test->getWhen () != UnitTest::runManual) - list.add (test); - } - } - - return list; -} - -UnitTests::TestList UnitTests::selectPackage ( - String const& package, TestList const& tests) const noexcept -{ - TestList list; - list.ensureStorageAllocated (tests.size ()); - for (int i = 0; i < tests.size(); ++i) - { - UnitTest* const test = tests [i]; - if (package.equalsIgnoreCase (test->getPackageName ()) && - test->getWhen () != UnitTest::runManual) - list.add (test); - } - return list; -} - -UnitTests::TestList UnitTests::selectTest ( - String const& testname, TestList const& tests) const noexcept -{ - TestList list; - for (int i = 0; i < tests.size(); ++i) - { - UnitTest* const test = tests [i]; - if (testname.equalsIgnoreCase (test->getClassName ())) - { - list.add (test); - break; - } - } - return list; -} - -UnitTests::TestList UnitTests::selectStartupTests (TestList const& tests) const noexcept -{ - TestList list; - for (int i = 0; i < tests.size(); ++i) - { - UnitTest* const test = tests [i]; - if (test->getWhen () == UnitTest::runStartup) - list.add (test); - } - return list; -} - -void UnitTests::runSelectedTests (String const& match, TestList const& tests, int64 randomSeed) -{ - runTests (selectTests (match, tests), randomSeed); -} - -void UnitTests::runTests (TestList const& tests, int64 randomSeed) -{ - if (randomSeed == 0) - randomSeed = Random().nextInt (0x7fffffff); - m_random = Random (randomSeed); - - m_results = new Results; - for (int i = 0; i < tests.size (); ++i) - { - if (shouldAbortTests()) - break; - runTest (*tests [i]); - } - m_results->secondsElapsed = RelativeTime ( - Time::getCurrentTime () - m_results->whenStarted).inSeconds (); -} - -void UnitTests::onFailure () -{ - // A failure occurred and the setting to assert on failures is turned on. - bassert (! m_assertOnFailure); -} - -bool UnitTests::shouldAbortTests() -{ - return false; -} - -void UnitTests::logMessage (const String& message) -{ - Logger::writeToLog (message); -} - -void UnitTests::logReport (StringArray const& report) -{ - for (int i = 0; i < report.size (); ++i) - logMessage (report [i]); -} - -void UnitTests::runTest (UnitTest& test) -{ -#if 0 - try - { -#endif - ScopedPointer suite (test.run (this).release ()); - - m_results->cases += suite->cases.size (); - m_results->tests += suite->tests; - m_results->failures += suite->failures; - - m_results->suites.add (suite.release ()); -#if 0 - } - catch (...) - { - // Should never get here. - Throw (std::runtime_error ("unhandled exception during unit tests")); - } -#endif -} - -//------------------------------------------------------------------------------ - -/** A UnitTest that prints the list of available unit tests. - Not an actual test (it always passes) but if you run it manually it - will print a list of the names of all available unit tests in the program. -*/ -class UnitTestsPrinter : public UnitTest -{ -public: - UnitTestsPrinter () : UnitTest ("print", "print", runManual) - { - } - - void runTest () - { - beginTestCase ("List available unit tests"); - - TestList const& list (UnitTest::getAllTests ()); - - for (int i = 0; i < list.size (); ++i) - { - UnitTest const& test (*list [i]); - - String s; - switch (test.getWhen ()) - { - default: - case UnitTest::runNormal: s << " "; break; - case UnitTest::runManual: s << "[manual] "; break; - case UnitTest::runStartup: s << "[FORCED] "; break; - }; - - s << test.getTestName (); - - logMessage (s); - } - - pass (); - } -}; - -static UnitTestsPrinter unitTestsPrinter; - -} // namespace beast diff --git a/modules/beast_core/diagnostic/UnitTest.h b/modules/beast_core/diagnostic/UnitTest.h deleted file mode 100644 index d28bf7a6..00000000 --- a/modules/beast_core/diagnostic/UnitTest.h +++ /dev/null @@ -1,555 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Portions of this file are from JUCE. - Copyright (c) 2013 - Raw Material Software Ltd. - Please visit http://www.juce.com - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_UNITTEST_H_INCLUDED -#define BEAST_UNITTEST_H_INCLUDED - -namespace beast -{ - -class UnitTests; - -/** This is a base class for classes that perform a unit test. - - To write a test using this class, your code should look something like this: - - @code - - class MyTest : public UnitTest - { - public: - MyTest() : UnitTest ("Foobar testing", "packageName") { } - - void runTest() - { - beginTestCase ("Part 1"); - - expect (myFoobar.doesSomething()); - expect (myFoobar.doesSomethingElse()); - - beginTestCase ("Part 2"); - - expect (myOtherFoobar.doesSomething()); - expect (myOtherFoobar.doesSomethingElse()); - - //... - } - }; - - // This makes the unit test available in the global list - // It doesn't have to be static. - // - static MyTest myTest; - - @endcode - - To run one or more unit tests, use the UnitTests class. - - @see UnitTests -*/ -class BEAST_API UnitTest : public Uncopyable -{ -public: - /** When the test should be run. */ - enum When - { - /** Test will be run when @ref runAllTests is called. - @see runAllTests - */ - runNormal, - - /** Test will excluded from @ref runAllTests. - The test can be manually run from @ref runTestsByName. - @see runAllTests, runTestsByName - */ - runManual, - - /** Test will be additionlly forced to run on every launch. - If any failures occur, FatalError is called. The tests will - also be run from @ref runAllTests or @ref runTestsByName if - explicitly invoked. - - @see FatalError - */ - runStartup - }; - - /** Describes a single test item. - - An item created for each call to the test functions, such as @ref expect - or @expectEquals. - */ - struct Item - { - explicit Item (bool passed_, String failureMessage_ = "") - : passed (passed_) - , failureMessage (failureMessage_) - { - } - - bool passed; - String failureMessage; - }; - - /** Describes a test case. - A test case represents a group of Item objects. - */ - struct Case - { - explicit Case (String const& name_, String const& className_) - : name (name_) - , className (className_) - , whenStarted (Time::getCurrentTime ()) - , secondsElapsed (0) - , failures (0) - { - } - - String name; - String className; - - Time whenStarted; - double secondsElapsed; - - int failures; - - Array items; - }; - - /** Contains the results of a test. - - One of these objects is instantiated each time UnitTest::beginTestCase() is called, and - it contains details of the number of subsequent UnitTest::expect() calls that are - made. - */ - struct Suite - { - String className; - String packageName; - Time whenStarted; - double secondsElapsed; - int tests; - int failures; - OwnedArray cases; - - //---- - - Suite (String const& className_, String const& packageName_) - : className (className_) - , packageName (packageName_) - , whenStarted (Time::getCurrentTime ()) // hack for now - , secondsElapsed (0) - , tests (0) - , failures (0) - { - } - - // for convenience - String getSuiteName () const noexcept - { - String s; - s << packageName << "::" << className; - return s; - } - }; - - /** The type of a list of tests. */ - typedef Array TestList; - - //-------------------------------------------------------------------------- - - /** Creates a test with the given name, group, and run option. - - The group is used when you want to run all tests in a particular group - instead of all tests in general. The run option allows you to write some - tests that are only available manually. For examplem, a performance unit - test that takes a long time which you might not want to run every time - you run all tests. - */ - /* - suiteName: A name - className: The name of the class that the unit test exercises - packageName: A real or pseudo "namespace" describing the general area of - functionality to which the specified class belongs. - Examples: "network", "core", "ui" - A package name can appear in multiple testsuite instances. - */ - explicit UnitTest (String const& name, - String const& group = "", - When when = runNormal); - - /** Destructor. */ - virtual ~UnitTest(); - - /** Returns the fully qualified test name in the form . */ - String getTestName() const noexcept; - - /** Returns the class name of the test. */ - const String& getClassName() const noexcept; - - /** Returns the package name of the test. */ - String const& getPackageName () const noexcept; - - /** Returns the run option of the test. */ - When getWhen () const noexcept { return m_when; } - - /** Returns a Journal that logs to the UnitTests. */ - Journal journal () const; - - /** Runs the test, using the specified UnitTests. - You shouldn't need to call this method directly - use - UnitTests::runTests() instead. - */ - ScopedPointer & run (UnitTests* runner); - - /** Returns the set of all UnitTest objects that currently exist. */ - static TestList& getAllTests(); - - //-------------------------------------------------------------------------- - - /** You can optionally implement this method to set up your test. - This method will be called before runTest(). - */ - virtual void initialise(); - - /** You can optionally implement this method to clear up after your test has been run. - This method will be called after runTest() has returned. - */ - virtual void shutdown(); - - /** Implement this method in your subclass to actually run your tests. - - The content of your implementation should call beginTestCase() and expect() - to perform the tests. - */ - virtual void runTest() = 0; - - /** Tells the system that a new subsection of tests is beginning. - This should be called from your runTest() method, and may be called - as many times as you like, to demarcate different sets of tests. - */ - void beginTestCase (String const& name); - - // beginTestCase () - - /** Checks that the result of a test is true, and logs this result. - - In your runTest() method, you should call this method for each condition that - you want to check, e.g. - - @code - void runTest() - { - beginTestCase ("basic tests"); - expect (x + y == 2); - expect (getThing() == someThing); - ...etc... - } - @endcode - - If Suite is true, a pass is logged; if it's false, a failure is logged. - If the failure message is specified, it will be written to the log if the test fails. - - Requirements: - Condition must be explicitly convertible to bool - */ - template - bool expect (Condition trueCondition, String const& failureMessage = String::empty) - { - return expect_bool (!!trueCondition, failureMessage); - } - - bool expect_bool (bool trueCondition, String const& failureMessage); - - /** Checks that the result of a test is false, and logs this result. - - This is basically the opposite of expect(). - - @see expect - - Requirements: - Condition must be explicitly convertible to bool - */ - template - bool unexpected (Condition falseCondition, String const& failureMessage = String::empty) - { - return unexpected_bool (!!falseCondition, failureMessage); - } - - bool unexpected_bool (bool falseCondition, String const& failureMessage); - - /** Compares two values, and if they don't match, prints out a message containing the - expected and actual result values. - */ - template - bool expectEquals (ActualType actual, ExpectedType expected, String failureMessage = String::empty) - { - const bool result = (actual == expected); - - if (! result) - { - if (failureMessage.isNotEmpty()) - failureMessage << " -- "; - - failureMessage << "Expected value: " << expected << ", Actual value: " << actual; - } - - return expect (result, failureMessage); - } - - /** Causes the test item to pass. */ - void pass (); - - /** Causes the test item to fail. */ - void fail (String const& failureMessage = String::empty); - - /** Records an exception in the test item. */ - void failException (); - - //============================================================================== - /** Writes a message to the test log. - This can only be called during your runTest() method. - */ - void logMessage (const String& message); - - void logReport (StringArray const& report); - - /** Returns a shared RNG that all unit tests should use. */ - Random& random(); - -private: - void finishCase (); - -private: - //============================================================================== - String const m_className; - String const m_packageName; - When const m_when; - UnitTests* m_runner; - ScopedPointer m_suite; - ScopedPointer m_case; - Random m_random; -}; - -//============================================================================== -/** - Runs a set of unit tests. - - You can instantiate one of these objects and use it to invoke tests on a set of - UnitTest objects. - - By using a subclass of UnitTests, you can intercept logging messages and - perform custom behaviour when each test completes. - - @see UnitTest -*/ -class BEAST_API UnitTests : public Uncopyable -{ -public: - typedef UnitTest::TestList TestList; - - struct Results - { - Results () - : whenStarted (Time::getCurrentTime ()) - , cases (0) - , tests (0) - , failures (0) - { - } - - Time whenStarted; - double secondsElapsed; - int cases; - int tests; - int failures; - - OwnedArray suites; - }; - - /** */ - UnitTests(); - - /** Destructor. */ - virtual ~UnitTests(); - - /** Sets a flag to indicate whether an assertion should be triggered if a test fails. - This is true by default. - */ - void setAssertOnFailure (bool shouldAssert) noexcept; - - /** Retrieve the information on all the suites that were run. - This is overwritten every time new tests are run. - */ - Results const& getResults () const noexcept; - - /** Returns `true` if any test failed. */ - bool anyTestsFailed () const noexcept; - - //-------------------------------------------------------------------------- - - /** Selects zero or more tests from specified packages or test names. - - The name can be in these formats: - "" - - "." - "." - "." - - "" - An empty string will match all tests objects which are not - marked to be run manually. - - - Selects all tests which belong to that package, excluding those - which must be run manually. If no package with that name exists, - then this will select the first test from any package which matches - the name. If the test is a manual test, it will be selected. - - "." - Selects all tests which belong to that package, excluding those - which must be run manually. If no package with that name exists, - then no tests will be selected. - - "." - Selects only the first test that matches the given testname and - package, regardless of the manual run setting. If no test with a - matching package and test name is found, then no test is selected. - - "." - Selects the first test which matches the testname, even if it - is a manual test. - - Some examples of names: - - "beast" All unit tests in beast - "beast.File" Just the File beast unit test - ".Random" The first test with the name Random - - @note Matching is not case-sensitive. - - @param match The string used to match tests - @param tests An optional parameter containing a list of tests to match. - */ - TestList selectTests (String const& match = "", - TestList const& tests = UnitTest::getAllTests ()) const noexcept; - - /** Selects all tests which match the specified package. - - Tests marked to be run manually are not included. - - @note Matching is not case-sensitive. - - @param match The string used to match tests - @param tests An optional parameter containing a list of tests to match. - */ - TestList selectPackage (String const& package, - TestList const& tests = UnitTest::getAllTests ()) const noexcept; - - /** Selects the first test whose name matches, from any package. - - This can include tests marked to be run manually. - - @note Matching is not case-sensitive. - - @param match The name of the test to match. - @param tests An optional parameter containing a list of tests to match. - */ - TestList selectTest (String const& testname, - TestList const& tests = UnitTest::getAllTests ()) const noexcept; - - /** Selects the startup tests. - A test marked as runStartup will be forced to run on launch. - Typically these are lightweight tests that ensure the system - environment will not cause the program to exhibit undefined behavior. - - @param tests An optional parameter containing a list of tests to match. - */ - TestList selectStartupTests (TestList const& tests = UnitTest::getAllTests ()) const noexcept; - - /** Run a list of matching tests. - This first calls selectTests and then runTeests on the resulting list. - @param match The string used for matching. - @param tests An optional parameter containing a list of tests to match. - */ - void runSelectedTests (String const& match = "", - TestList const& tests = UnitTest::getAllTests (), - int64 randomSeed = 0); - - /** Runs the specified list of tests. - @note The tests are run regardless of the run settings. - @param tests The list of tests to run. - */ - void runTests (TestList const& tests, int64 randomSeed = 0); - - Journal journal () - { - return Journal (m_sink); - } - -protected: - friend class UnitTest; - - /** Called on a failure. */ - void onFailure (); - - /** This can be overridden to let the runner know that it should abort the tests - as soon as possible, e.g. because the thread needs to stop. - */ - virtual bool shouldAbortTests (); - - /** Logs a message about the current test progress. - By default this just writes the message to the Logger class, but you could override - this to do something else with the data. - */ - virtual void logMessage (String const& message); - - /** Logs a report about the current test progress. - This calls logMessage for each String. - */ - virtual void logReport (StringArray const& report); - -private: - void runTest (UnitTest& test); - -private: - class JournalSink : public Journal::Sink, public Uncopyable - { - public: - explicit JournalSink (UnitTests& tests); - void write (Journal::Severity severity, std::string const& text); - - private: - UnitTests& m_tests; - }; - - bool m_assertOnFailure; - ScopedPointer m_results; - Random m_random; - JournalSink m_sink; -}; - -} // namespace beast - -#endif diff --git a/modules/beast_core/diagnostic/UnitTestUtilities.cpp b/modules/beast_core/diagnostic/UnitTestUtilities.cpp index 7875d0da..f40a382f 100644 --- a/modules/beast_core/diagnostic/UnitTestUtilities.cpp +++ b/modules/beast_core/diagnostic/UnitTestUtilities.cpp @@ -17,188 +17,8 @@ */ //============================================================================== -namespace beast -{ +namespace beast { +namespace UnitTestUtilities { -namespace UnitTestUtilities -{ - -JUnitXMLFormatter::JUnitXMLFormatter (UnitTests const& tests) - : m_tests (tests) - , m_currentTime (timeToString (Time::getCurrentTime ())) - , m_hostName (SystemStats::getComputerName ()) -{ -} - -// This is the closest thing to documentation on JUnit XML I could find: -// -// http://junitpdfreport.sourceforge.net/managedcontent/PdfTranslation -// -String JUnitXMLFormatter::createDocumentString () -{ - UnitTests::Results const& results (m_tests.getResults ()); - - ScopedPointer testsuites (new XmlElement ("testsuites")); - testsuites->setAttribute ("tests", String (results.tests)); - if (results.failures != 0) - testsuites->setAttribute ("failures", String (results.failures)); - testsuites->setAttribute ("time", secondsToString (results.secondsElapsed)); - - for (int i = 0; i < results.suites.size (); ++i) - { - UnitTest::Suite const& suite (*results.suites [i]); - - XmlElement* testsuite (new XmlElement ("testsuite"));; - testsuite->setAttribute ("name", suite.className); - testsuite->setAttribute ("tests", String (suite.tests)); - if (suite.failures != 0) - testsuite->setAttribute ("failures", String (suite.failures)); - testsuite->setAttribute ("time", secondsToString (suite.secondsElapsed)); - testsuite->setAttribute ("timestamp", timeToString (suite.whenStarted)); - testsuite->setAttribute ("hostname", m_hostName); - testsuite->setAttribute ("package", suite.packageName); - - testsuites->addChildElement (testsuite); - - for (int i = 0; i < suite.cases.size (); ++i) - { - UnitTest::Case const& testCase (*suite.cases [i]); - - XmlElement* testcase (new XmlElement ("testcase")); - testcase->setAttribute ("name", testCase.name); - testcase->setAttribute ("time", secondsToString (testCase.secondsElapsed)); - testcase->setAttribute ("classname", suite.className); - - testsuite->addChildElement (testcase); - - for (int i = 0; i < testCase.items.size (); ++i) - { - UnitTest::Item const& item (testCase.items.getUnchecked (i)); - - if (!item.passed) - { - XmlElement* failure (new XmlElement ("failure")); - - String s; - s << "#" << String (i+1) << " " << item.failureMessage; - failure->setAttribute ("message", s); - - testcase->addChildElement (failure); - } - } - } - } - - return testsuites->createDocument ( - //"https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-4.xsd", - "", - false, - true, - "UTF-8", - 999); -}; - -String JUnitXMLFormatter::timeToString (Time const& time) -{ - return time.toString (true, true, false, true); -} - -String JUnitXMLFormatter::secondsToString (double seconds) -{ - if (seconds < .01) - return String (seconds, 4); - else if (seconds < 1) - return String (seconds, 2); - else if (seconds < 10) - return String (seconds, 1); - else - return String (int (seconds)); -} - -//------------------------------------------------------------------------------ - -/** A unit test that always passes. - This can be useful to diagnose continuous integration systems. -*/ -class PassUnitTest : public UnitTest -{ -public: - PassUnitTest () : UnitTest ("Pass", "beast", runManual) - { - } - - void runTest () - { - beginTestCase ("pass"); - - pass (); - } -}; - -static PassUnitTest passUnitTest; - -//------------------------------------------------------------------------------ - -/** A unit test that always fails. - This can be useful to diagnose continuous integration systems. -*/ -class FailUnitTest : public UnitTest -{ -public: - FailUnitTest () : UnitTest ("Fail", "beast", runManual) - { - } - - void runTest () - { - beginTestCase ("fail"); - - fail ("Intentional failure"); - } -}; - -static FailUnitTest failUnitTest; - -} - -//------------------------------------------------------------------------------ - -class UnitTestUtilitiesTests : public UnitTest -{ -public: - UnitTestUtilitiesTests () : UnitTest ("UnitTestUtilities", "beast") - { - } - - void testPayload () - { - using namespace UnitTestUtilities; - - int const maxBufferSize = 4000; - int const minimumBytes = 1; - int const numberOfItems = 100; - int64 const seedValue = 50; - - beginTestCase ("Payload"); - - Payload p1 (maxBufferSize); - Payload p2 (maxBufferSize); - - for (int i = 0; i < numberOfItems; ++i) - { - p1.repeatableRandomFill (minimumBytes, maxBufferSize, seedValue); - p2.repeatableRandomFill (minimumBytes, maxBufferSize, seedValue); - - expect (p1 == p2, "Should be equal"); - } - } - - void runTest () - { - testPayload (); - } -}; - -static UnitTestUtilitiesTests unitTestUtilitiesTests; - -} // namespace beast +} // UnitTestUtilities +} // beast diff --git a/modules/beast_core/diagnostic/UnitTestUtilities.h b/modules/beast_core/diagnostic/UnitTestUtilities.h index c42b4316..1f226dce 100644 --- a/modules/beast_core/diagnostic/UnitTestUtilities.h +++ b/modules/beast_core/diagnostic/UnitTestUtilities.h @@ -20,11 +20,8 @@ #ifndef BEAST_UNITTESTUTILITIES_H_INCLUDED #define BEAST_UNITTESTUTILITIES_H_INCLUDED -namespace beast -{ - -namespace UnitTestUtilities -{ +namespace beast { +namespace UnitTestUtilities { /** Fairly shuffle an array pseudo-randomly. */ @@ -102,39 +99,7 @@ public: HeapBlock data; }; -//------------------------------------------------------------------------------ - -/** Format unit test results in JUnit XML format. - - The output can be used directly with the Jenkins CI server with - the appropriate JUnit plugin. - - JUnit FAQ: http://junit.sourceforge.net/doc/faq/faq.htm - - Jenkins Home: http://jenkins-ci.org/ - - @see UnitTest, UnitTests -*/ - -class JUnitXMLFormatter : public Uncopyable -{ -public: - JUnitXMLFormatter (UnitTests const& tests); - - String createDocumentString (); - -private: - static String timeToString (Time const& time); - static String secondsToString (double seconds); - -private: - UnitTests const& m_tests; - String const m_currentTime; - String const m_hostName; -}; - -} - -} // namespace beast +} // UnitTestUtilities +} // beast #endif diff --git a/modules/beast_core/files/File.cpp b/modules/beast_core/files/File.cpp index 35b0c163..d06beba7 100644 --- a/modules/beast_core/files/File.cpp +++ b/modules/beast_core/files/File.cpp @@ -21,8 +21,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { // We need to make a shared singleton or else there are // issues with the leak detector and order of detruction. @@ -904,14 +905,19 @@ File File::createTempFile (const String& fileNameEnding) //============================================================================== -class FileTests : public UnitTest +class File_test : public unit_test::suite { public: - FileTests() : UnitTest ("File", "beast") {} - - void runTest() + template + bool + expectEquals (T1 const& t1, T2 const& t2) { - beginTestCase ("Reading"); + return expect (t1 == t2); + } + + void run() + { + testcase ("Reading"); const File home (File::getSpecialLocation (File::userHomeDirectory)); const File temp (File::getSpecialLocation (File::tempDirectory)); @@ -950,7 +956,7 @@ public: expect (numRootsExisting > 0); } - beginTestCase ("Writing"); + testcase ("Writing"); File demoFolder (temp.getChildFile ("Beast UnitTests Temp Folder.folder")); expect (demoFolder.deleteRecursively()); @@ -991,7 +997,7 @@ public: expect (tempFile.exists()); expect (tempFile.getSize() == 10); expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000); - expectEquals (tempFile.loadFileAsString(), String ("0123456789")); + expect (tempFile.loadFileAsString() == String ("0123456789")); expect (! demoFolder.containsSubDirectories()); expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName()); @@ -1036,7 +1042,7 @@ public: expect (tempFile.getSize() == 10); } - beginTestCase ("More writing"); + testcase ("More writing"); expect (tempFile.appendData ("abcdefghij", 10)); expect (tempFile.getSize() == 20); @@ -1058,6 +1064,6 @@ public: } }; -static FileTests fileTests; +BEAST_DEFINE_TESTSUITE (File,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/files/RandomAccessFile.cpp b/modules/beast_core/files/RandomAccessFile.cpp index a20270ca..2376079c 100644 --- a/modules/beast_core/files/RandomAccessFile.cpp +++ b/modules/beast_core/files/RandomAccessFile.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { RandomAccessFile::RandomAccessFile () noexcept : fileHandle (nullptr) @@ -101,13 +102,9 @@ Result RandomAccessFile::flush () //------------------------------------------------------------------------------ -class RandomAccessFileTests : public UnitTest +class RandomAccessFile_test : public unit_test::suite { public: - RandomAccessFileTests () : UnitTest ("RandomAccessFile", "beast") - { - } - enum { maxPayload = 8192 @@ -221,7 +218,9 @@ public: int const seedValue = 50; - beginTestCase (String ("numRecords=") + String (numRecords)); + std::stringstream ss; + ss << numRecords << " records"; + testcase (ss.str()); // Calculate the path File const path (File::createTempFile ("RandomAccessFile")); @@ -264,14 +263,12 @@ public: } } - void runTest () + void run () { testFile (10000); } - -private: }; -static RandomAccessFileTests randomAccessFileTests; +BEAST_DEFINE_TESTSUITE(RandomAccessFile,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/maths/Random.cpp b/modules/beast_core/maths/Random.cpp index 2cea7649..67c9b9fb 100644 --- a/modules/beast_core/maths/Random.cpp +++ b/modules/beast_core/maths/Random.cpp @@ -21,8 +21,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { Random::Random (const int64 seedValue) noexcept : seed (seedValue) @@ -122,15 +123,11 @@ void Random::fillBitsRandomly (void* const buffer, size_t bytes) //============================================================================== -class RandomTests : public UnitTest +class Random_test : public unit_test::suite { public: - RandomTests() : UnitTest ("Random", "beast") {} - - void runTest() + void run() { - beginTestCase ("Random"); - for (int j = 10; --j >= 0;) { Random r; @@ -153,6 +150,6 @@ public: } }; -static RandomTests randomTests; +BEAST_DEFINE_TESTSUITE(Random,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/misc/Main.cpp b/modules/beast_core/misc/Main.cpp deleted file mode 100644 index 1f04b0ec..00000000 --- a/modules/beast_core/misc/Main.cpp +++ /dev/null @@ -1,131 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -namespace beast -{ - -Main* Main::s_instance; - -Main::Main () -{ - // If this happens it means there are two instances of Main! - check_precondition (s_instance == nullptr); - - s_instance = this; - -} - -Main::~Main () -{ - s_instance = nullptr; -} - -Main& Main::getInstance () -{ - bassert (s_instance != nullptr); - - return *s_instance; -} - -int Main::runStartupUnitTests () -{ - int exitCode = EXIT_SUCCESS; - - struct StartupUnitTests : UnitTests - { - void logMessage (String const&) - { - // Intentionally do nothing, we don't want - // to see the extra output for startup tests. - } - - void log (String const& message) - { -#if BEAST_MSVC - if (beast_isRunningUnderDebugger ()) - Logger::outputDebugString (message); -#endif - - std::cerr << message.toStdString () << std::endl; - } - - void reportCase (String const& suiteName, UnitTest::Case const& testcase) - { - String s; - s << suiteName << " (" << testcase.name << ") produced " << - String (testcase.failures) << - ((testcase.failures == 1) ? " failure." : " failures."); - log (s); - } - - void reportSuite (UnitTest::Suite const& suite) - { - if (suite.failures > 0) - { - String const suiteName = suite.getSuiteName (); - - for (int i = 0; i < suite.cases.size (); ++i) - { - UnitTest::Case const& testcase (*suite.cases [i]); - - if (testcase.failures > 0) - reportCase (suiteName, testcase); - } - } - } - - void reportSuites (UnitTests::Results const& results) - { - for (int i = 0; i < results.suites.size (); ++i) - reportSuite (*results.suites [i]); - } - - void reportResults () - { - reportSuites (getResults ()); - } - }; - - StartupUnitTests tests; - - tests.runTests (tests.selectStartupTests ()); - - if (tests.anyTestsFailed ()) - { - tests.reportResults (); - - tests.log ("Terminating with an error due to failed startup tests."); - - exitCode = EXIT_FAILURE; - } - - return exitCode; -} - -int Main::runFromMain (int argc, char const* const* argv) -{ - int exitCode (runStartupUnitTests ()); - - if (exitCode == EXIT_SUCCESS) - exitCode = run (argc, argv); - - return exitCode; -} - -} // namespace beast diff --git a/modules/beast_core/misc/Main.h b/modules/beast_core/misc/Main.h deleted file mode 100644 index 25158476..00000000 --- a/modules/beast_core/misc/Main.h +++ /dev/null @@ -1,84 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_CORE_MAIN_H_INCLUDED -#define BEAST_CORE_MAIN_H_INCLUDED - -namespace beast -{ - -/** Represents a command line program's entry point - To use this, derive your class from @ref Main and implement the - function run (); -*/ -class Main : public Uncopyable -{ -public: - Main (); - - virtual ~Main (); - - /** Run the program. - - You should call this from your @ref main function. Don't put - anything else in there. Instead, do it in your class derived - from Main. For example: - - @code - - struct MyProgram : Main - { - int run (int argc, char const* const* argv) - { - std::cout << "Hello, world!" << std::endl; - return 0; - } - }; - - int main (int argc, char const* const* argv) - { - MyProgram program; - - return program.runFromMain (argc, argv); - } - - @endcode - */ - int runFromMain (int argc, char const* const* argv); - - /** Retrieve the instance of the program. */ - static Main& getInstance (); - -protected: - /** Entry point for running the program. - Subclasses provide the implementation. - */ - virtual int run (int argc, char const* const* argv) = 0; - -private: - int runStartupUnitTests (); - -private: - static Main* s_instance; -}; - -} // namespace beast - -#endif - diff --git a/modules/beast_core/text/LexicalCast.cpp b/modules/beast_core/text/LexicalCast.cpp index a074d771..cc5d1d70 100644 --- a/modules/beast_core/text/LexicalCast.cpp +++ b/modules/beast_core/text/LexicalCast.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { unsigned char const LexicalCastUtilities::s_digitTable [256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF - 0x07 @@ -57,13 +58,9 @@ unsigned char const LexicalCastUtilities::s_digitTable [256] = { //------------------------------------------------------------------------------ -class LexicalCastTests : public UnitTest +class LexicalCast_test : public unit_test::suite { public: - LexicalCastTests () : UnitTest ("LexicalCast", "beast") - { - } - template static IntType nextRandomInt (Random& r) { @@ -74,7 +71,7 @@ public: void testInteger (IntType in) { String s; - IntType out; + IntType out (in+1); expect (lexicalCastChecked (s, in)); expect (lexicalCastChecked (out, s)); @@ -85,9 +82,10 @@ public: void testIntegers (Random& r) { { - String s; - s << "random " << typeid (IntType).name (); - beginTestCase (s); + std::stringstream ss; + ss << + "random " << typeid (IntType).name (); + testcase (ss.str()); for (int i = 0; i < 1000; ++i) { @@ -97,16 +95,17 @@ public: } { - String s; - s << "numeric_limits <" << typeid (IntType).name () << ">"; - beginTestCase (s); + std::stringstream ss; + ss << + "numeric_limits <" << typeid (IntType).name () << ">"; + testcase (ss.str()); testInteger (std::numeric_limits ::min ()); testInteger (std::numeric_limits ::max ()); } } - void runTest () + void run() { int64 const seedValue = 50; @@ -123,6 +122,6 @@ public: } }; -static LexicalCastTests lexicalCastTests; +BEAST_DEFINE_TESTSUITE(LexicalCast,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/thread/Workers.cpp b/modules/beast_core/thread/Workers.cpp index 2edc3202..2c72f9be 100644 --- a/modules/beast_core/thread/Workers.cpp +++ b/modules/beast_core/thread/Workers.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace beast -{ +#include "../../../beast/unit_test/suite.h" + +namespace beast { Workers::Workers (Callback& callback, String const& threadNames, int numberOfThreads) : m_callback (callback) @@ -222,12 +223,9 @@ void Workers::Worker::run () //------------------------------------------------------------------------------ -class WorkersTests : public UnitTest +class Workers_test : public unit_test::suite { public: - WorkersTests () : UnitTest ("Workers", "beast") - { - } struct TestCallback : Workers::Callback { @@ -247,11 +245,19 @@ public: Atomic count; }; + template + bool + expectEquals (T1 const& t1, T2 const& t2) + { + return expect (t1 == t2); + } + void testThreads (int const threadCount) { - String s; - s << "threadCount = " << String (threadCount); - beginTestCase (s); + std::stringstream ss; + ss << + "threadCount = " << threadCount; + testcase (ss.str()); TestCallback cb (threadCount); @@ -277,7 +283,7 @@ public: expectEquals (count, 0); } - void runTest () + void run () { testThreads (0); testThreads (1); @@ -288,6 +294,6 @@ public: } }; -static WorkersTests workersTests; +BEAST_DEFINE_TESTSUITE(Workers,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_core/thread/impl/TrackedMutex.cpp b/modules/beast_core/thread/impl/TrackedMutex.cpp index 50247655..59245d94 100644 --- a/modules/beast_core/thread/impl/TrackedMutex.cpp +++ b/modules/beast_core/thread/impl/TrackedMutex.cpp @@ -17,11 +17,8 @@ */ //============================================================================== -namespace beast -{ - -namespace detail -{ +namespace beast { +namespace detail { // Example: // @@ -74,7 +71,7 @@ TrackedMutexBasics::Lists& TrackedMutexBasics::getLists () //------------------------------------------------------------------------------ -} // namespace detail +} // detail //============================================================================== @@ -478,88 +475,4 @@ String TrackedMutex::makeSourceLocation (char const* fileName, int lineNumber) n return sourceLocation; } -//============================================================================== - -namespace detail -{ - -class TrackedMutexUnitTests : public UnitTest -{ -public: - typedef TrackedMutexType Mutex; - - struct LockingThread : public Thread - { - Mutex& m_m1; - Mutex& m_m2; - WaitableEvent m_start; - - explicit LockingThread (String name, Mutex& m1, Mutex& m2) - : Thread (name) - , m_m1 (m1) - , m_m2 (m2) - { - startThread (); - } - - void waitForStart () - { - m_start.wait (); - } - - void run () - { - Mutex::ScopedLockType l2 (m_m2, __FILE__, __LINE__); - { - Mutex::ScopedLockType l1 (m_m1, __FILE__, __LINE__); - m_start.signal (); - { - Mutex::ScopedUnlockType ul1 (m_m1, __FILE__, __LINE__); - this->wait (); - } - } - } - }; - - //-------------------------------------------------------------------------- - - void report (String name) - { - beginTestCase (name); - StringArray report; - TrackedMutex::generateGlobalBlockedReport (report); - logReport (report); - pass (); - } - - void runTest () - { - Mutex m1 ("M1", __FILE__, __LINE__); - Mutex m2 ("M2", __FILE__, __LINE__); - - { - Mutex::ScopedLockType l1 (m1, __FILE__, __LINE__); - LockingThread t1 ("T1", m1, m2); - { - Mutex::ScopedUnlockType ul1 (m1, __FILE__, __LINE__); - t1.waitForStart (); - } - report ("#1"); - { - t1.notify (); - Mutex::ScopedUnlockType ul1 (m1, __FILE__, __LINE__); - t1.waitForThreadToExit (); - } - } - } - - TrackedMutexUnitTests () : UnitTest ("TrackedMutex", "beast", runManual) - { - } -}; - -static TrackedMutexUnitTests trackedMutexUnitTests; - -} // namespace detail - -} // namespace beast +} // beast diff --git a/modules/beast_core/threads/ChildProcess.cpp b/modules/beast_core/threads/ChildProcess.cpp index a7a68fe7..46f465e1 100644 --- a/modules/beast_core/threads/ChildProcess.cpp +++ b/modules/beast_core/threads/ChildProcess.cpp @@ -61,13 +61,11 @@ String ChildProcess::readAllProcessOutput() //============================================================================== -class ChildProcessTests : public UnitTest +class ChildProcess_test : public unit_test::suite { public: - void runTest() + void run() { - beginTestCase ("Child Processes"); - #if BEAST_WINDOWS || BEAST_MAC || BEAST_LINUX ChildProcess p; @@ -87,17 +85,13 @@ public: //expect (output.isNotEmpty()); #endif } - - // VFALCO NOTE I had to disable this test because it was leaving - // behind a zombie process and making other unit tests fail. - // It doesnt happen with a debugger attached, or if the - // unit test is run individually. - // - ChildProcessTests() : UnitTest ("ChildProcess", "beast", runManual) - { - } }; -static ChildProcessTests childProcessTests; +// VFALCO NOTE I had to disable this test because it was leaving +// behind a zombie process and making other unit tests fail. +// It doesnt happen with a debugger attached, or if the +// unit test is run individually. +// +BEAST_DEFINE_TESTSUITE_MANUAL(ChildProcess,beast_core,beast); -} // namespace beast +} // beast diff --git a/modules/beast_vflib/beast_vflib.cpp b/modules/beast_vflib/beast_vflib.cpp deleted file mode 100644 index 355f19d5..00000000 --- a/modules/beast_vflib/beast_vflib.cpp +++ /dev/null @@ -1,28 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include "beast_vflib.h" - -#include "threads/ThreadWithServiceQueue.cpp" - -/** Unit tests for header only classes -*/ - -static beast::detail::CallQueueTests callQueueTests; -static beast::detail::ManualServiceQueueTests manualServiceQueueTests; diff --git a/modules/beast_vflib/beast_vflib.h b/modules/beast_vflib/beast_vflib.h deleted file mode 100644 index 50e2d76a..00000000 --- a/modules/beast_vflib/beast_vflib.h +++ /dev/null @@ -1,29 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#ifndef BEAST_VFLIB_H_INCLUDED -#define BEAST_VFLIB_H_INCLUDED - -#include "functor/BindHelper.h" -#include "threads/CallQueue.h" -#include "threads/ThreadWithServiceQueue.h" -#include "threads/ManualServiceQueue.h" -#include "threads/GuiServiceQueue.h" - -#endif diff --git a/modules/beast_vflib/functor/BindHelper.h b/modules/beast_vflib/functor/BindHelper.h deleted file mode 100644 index b148fd08..00000000 --- a/modules/beast_vflib/functor/BindHelper.h +++ /dev/null @@ -1,115 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#ifndef BEAST_VFLIB_BINDHELPER_H_INCLUDED -#define BEAST_VFLIB_BINDHELPER_H_INCLUDED - -namespace beast { - -/** Calls bind() for you. - The UnaryFunction will be called with this signature: - @code - template - void operator() (Functor const& f); - @endcode - Where Functor is the result of the bind. - */ -template -class BindHelper -{ -private: - // Gets called with the bind - UnaryFunction m_f; - -public: -#if BEAST_VARIADIC_MAX >= 1 - template - explicit BindHelper (Arg& arg) - : m_f (arg) - { } - - template - explicit BindHelper (Arg const& arg) - : m_f (arg) - { } - - template - void operator() (F const& f) const - { m_f (f); } -#endif - -#if BEAST_VARIADIC_MAX >= 2 - template - void operator() (F const& f, P1 const& p1) const - { m_f (bind (f, p1)); } -#endif - -#if BEAST_VARIADIC_MAX >= 3 - template - void operator() (F const& f, P1 const& p1, P2 const& p2) const - { m_f (bind (f, p1, p2)); } -#endif - -#if BEAST_VARIADIC_MAX >= 4 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3) const - { m_f (bind (f, p1, p2, p3)); } -#endif - -#if BEAST_VARIADIC_MAX >= 5 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const - { m_f (bind (f, p1, p2, p3, p4)); } -#endif - -#if BEAST_VARIADIC_MAX >= 6 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5) const - { m_f (bind (f, p1, p2, p3, p4, p5)); } -#endif - -#if BEAST_VARIADIC_MAX >= 7 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6) const - { m_f (bind (f, p1, p2, p3, p4, p5, p6)); } -#endif - -#if BEAST_VARIADIC_MAX >= 8 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7) const - { m_f (bind (f, p1, p2, p3, p4, p5, p6, p7)); } -#endif - -#if BEAST_VARIADIC_MAX >= 9 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8) const - { m_f (bind (f, p1, p2, p3, p4, p5, p6, p7, p8)); } -#endif - -#if BEAST_VARIADIC_MAX >= 10 - template - void operator() (F const& f, P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8, P9 const& p9) const - { m_f (bind (f, p1, p2, p3, p4, p5, p6, p7, p8, p9)); } -#endif -}; - -} - -#endif diff --git a/modules/beast_vflib/threads/CallQueue.h b/modules/beast_vflib/threads/CallQueue.h deleted file mode 100644 index 352977de..00000000 --- a/modules/beast_vflib/threads/CallQueue.h +++ /dev/null @@ -1,382 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#ifndef BEAST_VFLIB_CALLQUEUE_H_INCLUDED -#define BEAST_VFLIB_CALLQUEUE_H_INCLUDED - -#include "beast/Threads.h" -#include "../functor/BindHelper.h" - -namespace beast { - -template > -class CallQueueType -: public ServiceQueueType -{ -public: - explicit CallQueueType (const String& name, - int expectedConcurrency = 1, - Allocator alloc = Allocator()) - : ServiceQueueType(expectedConcurrency, alloc) - , m_name (name) - , queue(*this) - , call(*this) - { - } - - ~CallQueueType () - { - // Someone forget to close the queue. - bassert (m_closed.isSignaled ()); - - // Can't destroy queue with unprocessed calls. - bassert (ServiceQueueBase::empty ()); - } - - void enqueue (ServiceQueueBase::Item* item) - { - // If this goes off someone added calls - // after the queue has been closed. - bassert (!m_closed.isSignaled ()); - - ServiceQueueType ::enqueue (item); - } - - /** Close the queue. - - Functors may not be added after this routine is called. This is used for - diagnostics, to track down spurious calls during application shutdown - or exit. Derived classes may call this if the appropriate time is known. - - The queue is synchronized after it is closed. - Can still have pending calls, just can't put new ones in. - */ - virtual void close () - { - m_closed.signal (); - - ServiceQueueType ::stop (); - } - - struct BindHelperPost - { - CallQueueType& m_queue; - explicit BindHelperPost (CallQueueType& queue) - : m_queue (queue) - { } - template - void operator() (F const& f) const - { m_queue.post ( F (f) ); } - }; - - struct BindHelperDispatch - { - CallQueueType& m_queue; - explicit BindHelperDispatch (CallQueueType& queue) - : m_queue (queue) - { } - template - void operator() (F const& f) const - { m_queue.dispatch ( F (f) ); } - }; - - BindHelper const queue; - BindHelper const call; - -private: - String m_name; - AtomicFlag m_closed; -}; - -typedef CallQueueType > CallQueue; - -namespace detail -{ - -//------------------------------------------------------------------------------ - -class CallQueueTests -: public UnitTest -{ -public: - struct CallTracker - { - CallQueueTests *unitTest; - int c0, c1, c2, c3, c4, c5, c6, c7, c8; - int q0, q1, q2, q3, q4, q5, q6, q7, q8; - - CallTracker(CallQueueTests *parent) - : unitTest(parent) - , c0(0), c1(0), c2(0), c3(0), c4(0), c5(0), c6(0), c7(0), c8(0) - , q0(0), q1(0), q2(0), q3(0), q4(0), q5(0), q6(0), q7(0), q8(0) - { - } - - void doQ0() { q0++; } - - void doQ1(const String& p1) - { - unitTest->expect(p1 == "p1"); - q1++; - } - - void doQ2(const String& p1, const String& p2) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - q2++; - } - - void doQ3(const String& p1, const String& p2, const String& p3) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - q3++; - } - - void doQ4(const String& p1, const String& p2, const String& p3, const String& p4) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - q4++; - } - - void doQ5(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - q5++; - } - - void doQ6(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - q6++; - } - - void doQ7(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - unitTest->expect(p7 == "p7"); - q7++; - } - - void doQ8(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7, const String& p8) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - unitTest->expect(p7 == "p7"); - unitTest->expect(p8 == "p8"); - q8++; - } - - void doC0() { c0++; } - - void doC1(const String& p1) - { - unitTest->expect(p1 == "p1"); - c1++; - } - - void doC2(const String& p1, const String& p2) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - c2++; - } - - void doC3(const String& p1, const String& p2, const String& p3) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - c3++; - } - - void doC4(const String& p1, const String& p2, const String& p3, const String& p4) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - c4++; - } - - void doC5(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - c5++; - } - - void doC6(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - c6++; - } - - void doC7(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - unitTest->expect(p7 == "p7"); - c7++; - } - - void doC8(const String& p1, const String& p2, const String& p3, const String& p4, const String& p5, const String& p6, const String& p7, const String& p8) - { - unitTest->expect(p1 == "p1"); - unitTest->expect(p2 == "p2"); - unitTest->expect(p3 == "p3"); - unitTest->expect(p4 == "p4"); - unitTest->expect(p5 == "p5"); - unitTest->expect(p6 == "p6"); - unitTest->expect(p7 == "p7"); - unitTest->expect(p8 == "p8"); - c8++; - } - }; - - CallTracker m_callTracker; - - void testArities () - { - beginTestCase("Arities"); - - int calls = 0; - -#if BEAST_VARIADIC_MAX >= 2 - m_queue.queue(&CallTracker::doQ0, &m_callTracker); calls++; - m_queue.queue(&CallTracker::doC0, &m_callTracker); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 3 - m_queue.queue(&CallTracker::doQ1, &m_callTracker, "p1"); calls++; - m_queue.queue(&CallTracker::doC1, &m_callTracker, "p1"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 4 - m_queue.queue(&CallTracker::doQ2, &m_callTracker, "p1", "p2"); calls++; - m_queue.queue(&CallTracker::doC2, &m_callTracker, "p1", "p2"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 5 - m_queue.queue(&CallTracker::doQ3, &m_callTracker, "p1", "p2", "p3"); calls++; - m_queue.queue(&CallTracker::doC3, &m_callTracker, "p1", "p2", "p3"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 6 - m_queue.queue(&CallTracker::doQ4, &m_callTracker, "p1", "p2", "p3", "p4"); calls++; - m_queue.queue(&CallTracker::doC4, &m_callTracker, "p1", "p2", "p3", "p4"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 7 - m_queue.queue(&CallTracker::doQ5, &m_callTracker, "p1", "p2", "p3", "p4", "p5"); calls++; - m_queue.queue(&CallTracker::doC5, &m_callTracker, "p1", "p2", "p3", "p4", "p5"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 8 - m_queue.queue(&CallTracker::doQ6, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6"); calls++; - m_queue.queue(&CallTracker::doC6, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 9 - m_queue.queue(&CallTracker::doQ7, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7"); calls++; - m_queue.queue(&CallTracker::doC7, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7"); calls++; -#endif - -#if BEAST_VARIADIC_MAX >= 10 - m_queue.queue(&CallTracker::doQ8, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"); calls++; - m_queue.queue(&CallTracker::doC8, &m_callTracker, "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"); calls++; -#endif - - std::size_t performedCalls = m_queue.poll(); - - m_queue.close(); - - expect (performedCalls == calls); - - expect (m_callTracker.c0 == 1); - expect (m_callTracker.c1 == 1); - expect (m_callTracker.c2 == 1); - expect (m_callTracker.c3 == 1); - expect (m_callTracker.c4 == 1); - expect (m_callTracker.c5 == 1); - - expect (m_callTracker.q0 == 1); - expect (m_callTracker.q1 == 1); - expect (m_callTracker.q2 == 1); - expect (m_callTracker.q3 == 1); - expect (m_callTracker.q4 == 1); - expect (m_callTracker.q5 == 1); - } - - void runTest() - { - testArities(); - } - - CallQueueTests () - : UnitTest ("CallQueue", "beast") - , m_queue("CallQueue Test Queue") - , m_callTracker(this) - { - } - - CallQueue m_queue; -}; - -} - -} - -#endif diff --git a/modules/beast_vflib/threads/ManualServiceQueue.h b/modules/beast_vflib/threads/ManualServiceQueue.h deleted file mode 100644 index 3ab220e7..00000000 --- a/modules/beast_vflib/threads/ManualServiceQueue.h +++ /dev/null @@ -1,165 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#ifndef BEAST_VFLIB_MANUALSERVICEQUEUE_H_INCLUDED -#define BEAST_VFLIB_MANUALSERVICEQUEUE_H_INCLUDED - -#include "CallQueue.h" - -namespace beast { - -class ManualServiceQueue -: public CallQueue -{ -public: - explicit ManualServiceQueue (const String& name) - : CallQueue(name) - { - } - - /** Calls all functors in the queue. Returns if there are no - more functors available to run - */ - bool synchronize () - { - if(poll() > 0) - return true; - - return false; - } -}; - -//------------------------------------------------------------------------------ - -namespace detail -{ - -//------------------------------------------------------------------------------ - -class ManualServiceQueueTests -: public UnitTest -{ -public: - struct CallTracker - { - ManualServiceQueueTests *unitTest; - int c0, c1; - int q0, q1; - - CallTracker(ManualServiceQueueTests *parent) - : unitTest(parent) - , c0(0), c1(0) - , q0(0), q1(0) - { - } - - void doQ0() { q0++; } - - void doQ1(const String& p1) - { - unitTest->expect(p1 == "p1"); - q1++; - } - - void doC0() { c0++; } - - void doC1(const String& p1) - { - unitTest->expect(p1 == "p1"); - c1++; - } - }; - - void performEmptyQueue() - { - beginTestCase("Empty queue"); - - ManualServiceQueue queue("ManualServiceQueueTests"); - - bool doneSomething = queue.synchronize(); - expect(!doneSomething); - - queue.close(); - } - - void performCalls() - { - beginTestCase("Calls"); - - Random r; - r.setSeedRandomly(); - - ManualServiceQueue queue("ManualServiceQueueTests"); - - static int const batches = 1000; - - for(std::size_t i=0; i 0) - { - for(std::size_t y=0; y - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#include "ThreadWithServiceQueue.h" - -namespace beast { - -ThreadWithServiceQueue::ThreadWithServiceQueue (const String& name) -: CallQueue(name) -, m_thread(name, this) -, m_entryPoints(nullptr) -, m_calledStart(false) -, m_calledStop(false) -{ -} - -ThreadWithServiceQueue::~ThreadWithServiceQueue () -{ - stop(true); -} - -void ThreadWithServiceQueue::start (EntryPoints* const entryPoints) -{ - // start() MUST be called. - bassert (!m_calledStart); - m_calledStart = true; - - m_entryPoints = entryPoints; - - m_thread.startThread (); -} - -void ThreadWithServiceQueue::stop (bool const wait) -{ - // start() MUST be called. - bassert (m_calledStart); - - if (!m_calledStop) - { - m_calledStop = true; - - m_thread.signalThreadShouldExit(); - - // something could slip in here - - close (); - } - - if (wait) - m_thread.waitForThreadToExit (); -} - -void ThreadWithServiceQueue::runThread () -{ - m_entryPoints->threadInit (); - - while (! m_thread.threadShouldExit ()) - run (); - - // Perform the remaining calls in the queue - - reset (); - poll (); - - m_entryPoints->threadExit(); -} - -//------------------------------------------------------------------------------ - -namespace detail -{ - -//------------------------------------------------------------------------------ - -class ThreadWithServiceQueueTests -: public UnitTest -{ -public: - - struct ThreadWithServiceQueueRunner - : public ThreadWithServiceQueue::EntryPoints - { - ThreadWithServiceQueue m_worker; - int cCallCount, c1CallCount; - int qCallCount, q1CallCount; - int initCalled, exitCalled; - - ThreadWithServiceQueueRunner() - : m_worker("ThreadWithServiceQueueRunner") - , cCallCount(0) - , c1CallCount(0) - , qCallCount(0) - , q1CallCount(0) - , initCalled(0) - , exitCalled(0) - { - } - - void start() - { - m_worker.start(this); - } - - void stop() - { - m_worker.stop(true); - } - - void c() - { - m_worker.call(&ThreadWithServiceQueueRunner::cImpl, this); - } - - void cImpl() - { - cCallCount++; - } - - void c1(int p1) - { - m_worker.call(&ThreadWithServiceQueueRunner::c1Impl, this, p1); - } - - void c1Impl(int p1) - { - c1CallCount++; - } - - void q() - { - m_worker.queue(&ThreadWithServiceQueueRunner::qImpl, this); - } - - void qImpl() - { - qCallCount++; - } - - void q1(int p1) - { - m_worker.queue(&ThreadWithServiceQueueRunner::q1Impl, this, p1); - } - - void q1Impl(int p1) - { - q1CallCount++; - } - - void threadInit () - { - initCalled++; - } - - void threadExit () - { - exitCalled++; - } - }; - - static int const calls = 1000; - - void performCalls() - { - Random r; - r.setSeedRandomly(); - - ThreadWithServiceQueueRunner runner; - - runner.start(); - - for(std::size_t i=0; i - Copyright Patrick Dehne (www.sonicweb-radio.de) - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -//============================================================================== - -#ifndef BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED -#define BEAST_VFLIB_THREADWITHSERVICEQUEUE_H_INCLUDED - -#include "CallQueue.h" - -namespace beast { - -class ThreadWithServiceQueue -: public CallQueue -{ -public: - /** Entry points for a ThreadWithCallQueue. - */ - class EntryPoints - { - public: - virtual ~EntryPoints () { } - - virtual void threadInit () { } - - virtual void threadExit () { } - }; - - explicit ThreadWithServiceQueue (const String& name); - - ~ThreadWithServiceQueue(); - - void start (EntryPoints* const entryPoints); - - void stop (bool const wait); - - /** Calls all functors in the queue. Blocks if there are no - functors available to run until more functors become - available or the queue is stopped - - */ - bool synchronize (); - - /** Helper class to work around ThreadWithServiceQueue and Thread both - having a run member - */ - class Worker - : public Thread - { - public: - Worker(const String& name, ThreadWithServiceQueue *parent) - : Thread(name) - , m_parent(parent) - { - } - - void run() - { - m_parent->runThread(); - } - - private: - ThreadWithServiceQueue *m_parent; - }; - - void runThread (); - -private: - EntryPoints* m_entryPoints; - bool m_calledStart; - bool m_calledStop; - Worker m_thread; -}; - -} - -#endif