From 4d06a7617cc17c124de6439a039309d48691651c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 20 Aug 2017 23:57:03 +0200 Subject: [PATCH] Some ut enhancements * CaptureChannel becomes a main feature and is easier to use now. * EXPECT_EQ/NE no longer does a double evaluation of the arguments on fail (to print the result that wasn't matching) --- src/buddies/unit_tests/bdStrmcmpTests.cc | 162 +++----------------- src/ut/utHead.h | 186 ++++++++++++++--------- src/ut/utMain.cc | 32 +++- 3 files changed, 163 insertions(+), 217 deletions(-) diff --git a/src/buddies/unit_tests/bdStrmcmpTests.cc b/src/buddies/unit_tests/bdStrmcmpTests.cc index 9616fff81..a8f7d3e35 100644 --- a/src/buddies/unit_tests/bdStrmcmpTests.cc +++ b/src/buddies/unit_tests/bdStrmcmpTests.cc @@ -29,50 +29,10 @@ BD_PUBLIC int strmcmp (int argc, char *argv[]); -class CaptureChannel : public tl::Channel -{ -public: - CaptureChannel () - { - // .. nothing yet .. - } - - std::string captured_text () const - { - return m_text.str (); - } - - void clear () - { - m_text.str (std::string ()); - } - -protected: - virtual void puts (const char *s) - { - m_text << s; - } - - virtual void endl () - { - m_text << "\n"; - } - - virtual void end () { } - virtual void begin () { } - -private: - std::ostringstream m_text; -}; - TEST(1) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; tl::info << "Self test"; EXPECT_EQ (cap.captured_text (), "Self test\n"); @@ -94,11 +54,7 @@ TEST(1) TEST(2A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -127,11 +83,7 @@ TEST(2A) TEST(2B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -148,11 +100,7 @@ TEST(2B) TEST(2C) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -176,11 +124,7 @@ TEST(2C) TEST(2D) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -201,11 +145,7 @@ TEST(2D) TEST(2E) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -220,11 +160,7 @@ TEST(2E) TEST(2F) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -247,11 +183,7 @@ TEST(2F) TEST(3A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -275,11 +207,7 @@ TEST(3A) TEST(3B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -294,11 +222,7 @@ TEST(3B) TEST(4A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -325,11 +249,7 @@ TEST(4A) TEST(4B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -344,11 +264,7 @@ TEST(4B) TEST(5A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -368,11 +284,7 @@ TEST(5A) TEST(5B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -387,11 +299,7 @@ TEST(5B) TEST(6A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -415,11 +323,7 @@ TEST(6A) TEST(6B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -434,11 +338,7 @@ TEST(6B) TEST(7A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -458,11 +358,7 @@ TEST(7A) TEST(7B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -477,11 +373,7 @@ TEST(7B) TEST(8A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -513,11 +405,7 @@ TEST(8A) TEST(8B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -536,11 +424,7 @@ TEST(8B) TEST(9A) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; @@ -560,11 +444,7 @@ TEST(9A) TEST(9B) { - CaptureChannel cap; - - tl::warn.add (&cap, false); - tl::info.add (&cap, false); - tl::error.add (&cap, false); + ut::CaptureChannel cap; std::string input_a = ut::testsrc (); input_a += "/testdata/bd/strmcmp_in.gds"; diff --git a/src/ut/utHead.h b/src/ut/utHead.h index b68cecc47..a9c06c198 100644 --- a/src/ut/utHead.h +++ b/src/ut/utHead.h @@ -132,6 +132,102 @@ struct Exception { } }; +/** + * @brief A utility class to capture the warning, error and info channels + * + * Instantiate this class inside a test. Then run the test and finally + * obtain the collected output with CaptureChannel::captured_text(). + */ +class UT_PUBLIC CaptureChannel : public tl::Channel +{ +public: + CaptureChannel (); + + std::string captured_text () const + { + return m_text.str (); + } + + void clear () + { + m_text.str (std::string ()); + } + +protected: + virtual void puts (const char *s); + virtual void endl (); + virtual void end (); + virtual void begin (); + +private: + std::ostringstream m_text; +}; + +/** + * @brief A generic compare operator + */ +template +inline bool equals (const X &a, const Y &b) +{ + return a == b; +} + +/** + * @brief A specialization of the compare operator for doubles + */ +UT_PUBLIC bool equals (double a, double b); + +/** + * @brief Specialization of comparison of pointers vs. integers (specifically "0") + */ +template +inline bool equals (X *a, int b) +{ + return a == (X *) size_t (b); +} + +/** + * @brief A specialization of comparison of double vs "anything" + */ +template +inline bool equals (double a, const Y &b) +{ + return equals (a, double (b)); +} + +/** + * @brief A specialization of comparison of "anything" vs. double + */ +template +inline bool equals (const X &a, double b) +{ + return equals (double (a), b); +} + +/** + * @brief A specialization of the compare operator for const char * + */ +inline bool equals (const char *a, const char *b) +{ + return equals (std::string (a), std::string (b)); +} + +/** + * @brief A specialization of the compare operator for std::string vs. const char * + */ +inline bool equals (const std::string &a, const char *b) +{ + return equals (a, std::string (b)); +} + +/** + * @brief A specialization of the compare operator for std::string vs. const char * + */ +inline bool equals (const char *a, const std::string &b) +{ + return equals (std::string (a), b); +} + /** * @brief The base class for tests */ @@ -348,6 +444,19 @@ struct UT_PUBLIC TestBase diff (file, line, msg, std::string (subject), std::string (ref)); } + /** + * @brief Main entry point for the compare feature (EXPECT_EQ and EXPECT_NE) + */ + template + void eq_helper (bool eq, const T1 &a, const T2 &b, const char *what_expr, const char *equals_expr, const char *file, int line) + { + if (ut::equals (a, b) != eq) { + std::ostringstream sstr; + sstr << what_expr << " does not equal " << equals_expr; + diff (file, line, sstr.str (), a, b); + } + } + private: virtual void execute (ut::TestBase *_this) throw (tl::Exception) = 0; @@ -391,71 +500,6 @@ private: std::vector m_tests; }; -/** - * @brief A generic compare operator - */ -template -inline bool equals (const X &a, const Y &b) -{ - return a == b; -} - -/** - * @brief A specialization of the compare operator for doubles - */ -UT_PUBLIC bool equals (double a, double b); - -/** - * @brief Specialization of comparison of pointers vs. integers (specifically "0") - */ -template -inline bool equals (X *a, int b) -{ - return a == (X *) size_t (b); -} - -/** - * @brief A specialization of comparison of double vs "anything" - */ -template -inline bool equals (double a, const Y &b) -{ - return equals (a, double (b)); -} - -/** - * @brief A specialization of comparison of "anything" vs. double - */ -template -inline bool equals (const X &a, double b) -{ - return equals (double (a), b); -} - -/** - * @brief A specialization of the compare operator for const char * - */ -inline bool equals (const char *a, const char *b) -{ - return equals (std::string (a), std::string (b)); -} - -/** - * @brief A specialization of the compare operator for std::string vs. const char * - */ -inline bool equals (const std::string &a, const char *b) -{ - return equals (a, std::string (b)); -} - -/** - * @brief A specialization of the compare operator for std::string vs. const char * - */ -inline bool equals (const char *a, const std::string &b) -{ - return equals (std::string (a), b); -} - } // namespace ut #define TEST(NAME) \ @@ -472,19 +516,11 @@ struct TestImpl##NAME \ #define EXPECT_EQ(WHAT,EQUALS) \ _this->checkpoint (__FILE__, __LINE__); \ - if (! ut::equals ((WHAT), (EQUALS))) { \ - std::ostringstream sstr; \ - sstr << #WHAT << " does not equal " << #EQUALS; \ - _this->diff (__FILE__, __LINE__, sstr.str (), (WHAT), (EQUALS)); \ - } + _this->eq_helper (true, (WHAT), (EQUALS), #WHAT, #EQUALS, __FILE__, __LINE__); #define EXPECT_NE(WHAT,EQUALS) \ _this->checkpoint (__FILE__, __LINE__); \ - if (ut::equals ((WHAT), (EQUALS))) { \ - std::ostringstream sstr; \ - sstr << #WHAT << " equals " << #EQUALS; \ - _this->raise (__FILE__, __LINE__, sstr.str ()); \ - } + _this->eq_helper (false, (WHAT), (EQUALS), #WHAT, #EQUALS, __FILE__, __LINE__); #define EXPECT(WHAT) \ _this->checkpoint (__FILE__, __LINE__); \ diff --git a/src/ut/utMain.cc b/src/ut/utMain.cc index b5ea53945..e9eaeb286 100644 --- a/src/ut/utMain.cc +++ b/src/ut/utMain.cc @@ -139,6 +139,36 @@ void print_error (const std::string &s) tl::error << "ERROR: " << s; } +// ------------------------------------------------ +// CaptureChannel implementation + +CaptureChannel::CaptureChannel () +{ + tl::info.add (this, false); + tl::error.add (this, false); + tl::warn.add (this, false); +} + +void CaptureChannel::puts (const char *s) +{ + m_text << s; +} + +void CaptureChannel::endl () +{ + m_text << "\n"; +} + +void CaptureChannel::end () +{ + // .. nothing yet .. +} + +void CaptureChannel::begin () +{ + // .. nothing yet .. +} + // ------------------------------------------------ // tl::Channel implementations for redirecting the log output @@ -842,7 +872,7 @@ main_cont (int argc, char **argv) if (ut_file.exists () && ut_file.isReadable ()) { std::string pp = tl::to_string (ut_file.absoluteFilePath ()); - tl::log << "Loading plugin unit tests " << pp; + tl::log << "Loading unit tests " << pp; // NOTE: since we are using a different suffix ("*.ut"), we can't use QLibrary. #ifdef _WIN32