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)
This commit is contained in:
Matthias Koefferlein 2017-08-20 23:57:03 +02:00
parent a7e4c7aadc
commit 4d06a7617c
3 changed files with 163 additions and 217 deletions

View File

@ -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";

View File

@ -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 <class X, class Y>
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 <class X>
inline bool equals (X *a, int b)
{
return a == (X *) size_t (b);
}
/**
* @brief A specialization of comparison of double vs "anything"
*/
template <class Y>
inline bool equals (double a, const Y &b)
{
return equals (a, double (b));
}
/**
* @brief A specialization of comparison of "anything" vs. double
*/
template <class X>
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 <class T1, class T2>
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 <ut::TestBase *> m_tests;
};
/**
* @brief A generic compare operator
*/
template <class X, class Y>
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 <class X>
inline bool equals (X *a, int b)
{
return a == (X *) size_t (b);
}
/**
* @brief A specialization of comparison of double vs "anything"
*/
template <class Y>
inline bool equals (double a, const Y &b)
{
return equals (a, double (b));
}
/**
* @brief A specialization of comparison of "anything" vs. double
*/
template <class X>
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__); \

View File

@ -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