[geos-commits] r2621 - trunk/tests/unit/tut
svn_geos at osgeo.org
svn_geos at osgeo.org
Fri Aug 21 05:43:09 EDT 2009
Author: mloskot
Date: 2009-08-21 05:43:09 -0400 (Fri, 21 Aug 2009)
New Revision: 2621
Added:
trunk/tests/unit/tut/tut_console_reporter.hpp
Modified:
trunk/tests/unit/tut/tut.hpp
trunk/tests/unit/tut/tut_assert.hpp
trunk/tests/unit/tut/tut_exception.hpp
trunk/tests/unit/tut/tut_posix.hpp
trunk/tests/unit/tut/tut_reporter.hpp
trunk/tests/unit/tut/tut_restartable.hpp
trunk/tests/unit/tut/tut_result.hpp
trunk/tests/unit/tut/tut_runner.hpp
Log:
Updated C++ TUT Framework to latest revision (147) of its SVN trunk
Modified: trunk/tests/unit/tut/tut.hpp
===================================================================
--- trunk/tests/unit/tut/tut.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -11,6 +11,10 @@
#include <algorithm>
#include <typeinfo>
+#if defined(linux)
+#define TUT_USE_POSIX
+#endif
+
#include "tut_exception.hpp"
#include "tut_result.hpp"
#include "tut_posix.hpp"
@@ -58,6 +62,16 @@
return current_test_name_;
}
+ void set_test_id(int current_test_id)
+ {
+ current_test_id_ = current_test_id;
+ }
+
+ int get_test_id() const
+ {
+ return current_test_id_;
+ }
+
/**
* Default do-nothing test.
*/
@@ -77,6 +91,7 @@
bool called_method_was_a_dummy_test_;
private:
+ int current_test_id_;
std::string current_test_name_;
};
@@ -124,6 +139,14 @@
tests tests_;
tests_iterator current_test_;
+ enum seh_result
+ {
+ SEH_OK,
+ SEH_CTOR,
+ SEH_TEST,
+ SEH_DUMMY
+ };
+
/**
* Exception-in-destructor-safe smart-pointer class.
*/
@@ -287,85 +310,81 @@
/**
* Runs next test.
*/
- test_result run_next()
+ bool run_next(test_result &tr)
{
if (current_test_ == tests_.end())
{
- throw no_more_tests();
+ return false;
}
// find next user-specialized test
safe_holder<object> obj;
while (current_test_ != tests_.end())
{
- try
- {
- tests_iterator current_test = current_test_++;
+ tests_iterator current_test = current_test_++;
- test_result tr = run_test_(current_test, obj);
-
- return tr;
- }
- catch (const no_such_test&)
+ if(run_test_(current_test, obj, tr) && tr.result != test_result::dummy)
{
- continue;
+ return true;
}
}
- throw no_more_tests();
+ return false;
}
/**
* Runs one test by position.
*/
- test_result run_test(int n)
+ bool run_test(int n, test_result &tr)
{
- // beyond tests is special case to discover upper limit
- if (tests_.rbegin() == tests_.rend())
+ if (tests_.rbegin() == tests_.rend() ||
+ tests_.rbegin()->first < n)
{
- throw beyond_last_test();
+ return false;
}
- if (tests_.rbegin()->first < n)
- {
- throw beyond_last_test();
- }
-
// withing scope; check if given test exists
tests_iterator ti = tests_.find(n);
if (ti == tests_.end())
{
- throw no_such_test();
+ return false;
}
safe_holder<object> obj;
- test_result tr = run_test_(ti, obj);
-
- return tr;
+ return run_test_(ti, obj, tr);
}
-
/**
* VC allows only one exception handling type per function,
* so I have to split the method.
*/
- test_result run_test_(const tests_iterator& ti, safe_holder<object>& obj)
+ bool run_test_(const tests_iterator& ti, safe_holder<object>& obj, test_result &tr)
{
std::string current_test_name;
- test_result tr(name_, ti->first, current_test_name, test_result::ok);
+ tr = test_result(name_, ti->first, current_test_name, test_result::ok);
try
{
- if (run_test_seh_(ti->second, obj, current_test_name) == false)
- {
- throw seh("seh");
+ switch (run_test_seh_(ti->second, obj, current_test_name, ti->first))
+ {
+ case SEH_CTOR:
+ throw bad_ctor("seh");
+ break;
+
+ case SEH_TEST:
+ throw seh("seh");
+ break;
+
+ case SEH_DUMMY:
+ tr.result = test_result::dummy;
+ break;
+
+ case SEH_OK:
+ // ok
+ break;
}
}
- catch (const no_such_test&)
- {
- throw;
- }
catch (const rethrown& ex)
{
tr = ex.tr;
@@ -401,14 +420,14 @@
tr.name = current_test_name;
}
- return tr;
+ return true;
}
/**
* Runs one under SEH if platform supports it.
*/
- bool run_test_seh_(testmethod tm, safe_holder<object>& obj,
- std::string& current_test_name)
+ seh_result run_test_seh_(testmethod tm, safe_holder<object>& obj,
+ std::string& current_test_name, int current_test_id)
{
#if defined(TUT_USE_SEH)
__try
@@ -426,21 +445,21 @@
__try
{
#endif
+ obj.get()->set_test_id(current_test_id);
(obj.get()->*tm)();
#if defined(TUT_USE_SEH)
}
__except(handle_seh_(::GetExceptionCode()))
{
- // throw seh("SEH");
current_test_name = obj->get_test_name();
- return false;
+ return SEH_TEST;
}
#endif
if (obj->called_method_was_a_dummy_test_)
{
// do not call obj.release(); reuse object
- throw no_such_test();
+ return SEH_DUMMY;
}
current_test_name = obj->get_test_name();
@@ -450,10 +469,10 @@
}
__except(handle_seh_(::GetExceptionCode()))
{
- return false;
+ return SEH_CTOR;
}
#endif
- return true;
+ return SEH_OK;
}
void reset_holder_(safe_holder<object>& obj)
Modified: trunk/tests/unit/tut/tut_assert.hpp
===================================================================
--- trunk/tests/unit/tut/tut_assert.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_assert.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -2,6 +2,8 @@
#define TUT_ASSERT_H_GUARD
#include "tut_exception.hpp"
+#include <limits>
+#include <iomanip>
#if defined(TUT_USE_POSIX)
#include <errno.h>
@@ -11,6 +13,24 @@
namespace tut
{
+ namespace detail
+ {
+ template<typename M>
+ std::ostream &msg_prefix(std::ostream &str, const M &msg)
+ {
+ std::stringstream ss;
+ ss << msg;
+
+ if(!ss.str().empty())
+ {
+ str << ss.rdbuf() << ": ";
+ }
+
+ return str;
+ }
+ }
+
+
namespace
{
@@ -40,8 +60,8 @@
* Tests provided condition.
* Throws if false.
*/
-template <typename T>
-void ensure(const T msg, bool cond)
+template <typename M>
+void ensure(const M& msg, bool cond)
{
if (!cond)
{
@@ -53,8 +73,8 @@
* Tests provided condition.
* Throws if true.
*/
-template <typename T>
-void ensure_not(const T msg, bool cond)
+template <typename M>
+void ensure_not(const M& msg, bool cond)
{
ensure(msg, !cond);
}
@@ -66,29 +86,47 @@
* NB: both T and Q must have operator << defined somewhere, or
* client code will not compile at all!
*/
-template <class T, class Q>
-void ensure_equals(const char* msg, const Q& actual, const T& expected)
+template <typename M, typename LHS, typename RHS>
+void ensure_equals(const M& msg, const LHS& actual, const RHS& expected)
{
if (expected != actual)
{
std::stringstream ss;
- ss << (msg ? msg : "")
- << (msg ? ":" : "")
- << " expected '"
- << expected
- << "' actual '"
- << actual
- << '\'';
- throw failure(ss.str().c_str());
+ detail::msg_prefix(ss,msg)
+ << "expected '"
+ << expected
+ << "' actual '"
+ << actual
+ << '\'';
+ throw failure(ss.str());
}
}
-template <class T, class Q>
-void ensure_equals(const Q& actual, const T& expected)
+template <typename LHS, typename RHS>
+void ensure_equals(const LHS& actual, const RHS& expected)
{
- ensure_equals<>(0, actual, expected);
+ ensure_equals("Values are not equal", actual, expected);
}
+template<typename M>
+void ensure_equals(const M& msg, const double& actual, const double& expected,
+ const double& epsilon = std::numeric_limits<double>::epsilon())
+{
+ const double diff = actual - expected;
+
+ if ( !((diff <= epsilon) && (diff >= -epsilon )) )
+ {
+ std::stringstream ss;
+ detail::msg_prefix(ss,msg)
+ << std::scientific
+ << std::showpoint
+ << std::setprecision(16)
+ << "expected " << expected
+ << " actual " << actual
+ << " with precision " << epsilon;
+ throw failure(ss.str());
+ }
+}
/**
* Tests two objects for being at most in given distance one from another.
* Borders are excluded.
@@ -97,16 +135,16 @@
* NB: T must have operator << defined somewhere, or
* client code will not compile at all! Also, T shall have
* operators + and -, and be comparable.
+ *
+ * TODO: domains are wrong, T - T might not yield T, but Q
*/
-template <class T>
-void ensure_distance(const char* msg, const T& actual, const T& expected,
- const T& distance)
+template <typename M, class T>
+void ensure_distance(const M& msg, const T& actual, const T& expected, const T& distance)
{
if (expected-distance >= actual || expected+distance <= actual)
{
std::stringstream ss;
- ss << (msg ? msg : "")
- << (msg? ":" : "")
+ detail::msg_prefix(ss,msg)
<< " expected ("
<< expected-distance
<< " - "
@@ -114,27 +152,27 @@
<< ") actual '"
<< actual
<< '\'';
- throw failure(ss.str().c_str());
+ throw failure(ss.str());
}
}
template <class T>
void ensure_distance(const T& actual, const T& expected, const T& distance)
{
- ensure_distance<>(0, actual, expected, distance);
+ ensure_distance<>("Distance is wrong", actual, expected, distance);
}
-void ensure_errno(const char *msg, bool cond)
+template<typename M>
+void ensure_errno(const M& msg, bool cond)
{
if(!cond)
{
#if defined(TUT_USE_POSIX)
char e[512];
std::stringstream ss;
- ss << (msg ? msg : "")
- << (msg? ": " : "")
- << strerror_r(errno, e, sizeof(e));
- throw failure(ss.str().c_str());
+ detail::msg_prefix(ss,msg)
+ << strerror_r(errno, e, sizeof(e));
+ throw failure(ss.str());
#else
throw failure(msg);
#endif
@@ -149,7 +187,8 @@
throw failure(msg);
}
-void fail(const std::string &msg)
+template<typename M>
+void fail(const M& msg)
{
throw failure(msg);
}
Added: trunk/tests/unit/tut/tut_console_reporter.hpp
===================================================================
--- trunk/tests/unit/tut/tut_console_reporter.hpp (rev 0)
+++ trunk/tests/unit/tut/tut_console_reporter.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -0,0 +1,241 @@
+#ifndef TUT_CONSOLE_REPORTER
+#define TUT_CONSOLE_REPORTER
+
+#include <tut/tut.hpp>
+#include <cassert>
+
+/**
+ * Template Unit Tests Framework for C++.
+ * http://tut.dozen.ru
+ *
+ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
+ */
+namespace
+{
+
+std::ostream& operator<<(std::ostream& os, const tut::test_result& tr)
+{
+ switch(tr.result)
+ {
+ case tut::test_result::ok:
+ os << '.';
+ break;
+ case tut::test_result::fail:
+ os << '[' << tr.test << "=F]";
+ break;
+ case tut::test_result::ex_ctor:
+ os << '[' << tr.test << "=C]";
+ break;
+ case tut::test_result::ex:
+ os << '[' << tr.test << "=X]";
+ break;
+ case tut::test_result::warn:
+ os << '[' << tr.test << "=W]";
+ break;
+ case tut::test_result::term:
+ os << '[' << tr.test << "=T]";
+ break;
+ case tut::test_result::rethrown:
+ os << '[' << tr.test << "=P]";
+ break;
+ case tut::test_result::dummy:
+ assert(!"Should never be called");
+ }
+
+ return os;
+}
+
+} // end of namespace
+
+namespace tut
+{
+
+/**
+ * Default TUT callback handler.
+ */
+class console_reporter : public tut::callback
+{
+ std::string current_group;
+ typedef std::vector<tut::test_result> not_passed_list;
+ not_passed_list not_passed;
+ std::ostream& os;
+
+public:
+
+ int ok_count;
+ int exceptions_count;
+ int failures_count;
+ int terminations_count;
+ int warnings_count;
+
+ console_reporter()
+ : os(std::cout)
+ {
+ init();
+ }
+
+ console_reporter(std::ostream& out)
+ : os(out)
+ {
+ init();
+ }
+
+ void run_started()
+ {
+ init();
+ }
+
+ void test_completed(const tut::test_result& tr)
+ {
+ if (tr.group != current_group)
+ {
+ os << std::endl << tr.group << ": " << std::flush;
+ current_group = tr.group;
+ }
+
+ os << tr << std::flush;
+
+ // update global statistics
+ switch (tr.result) {
+ case test_result::ok:
+ ok_count++;
+ break;
+ case test_result::fail:
+ case test_result::rethrown:
+ failures_count++;
+ break;
+ case test_result::ex:
+ case test_result::ex_ctor:
+ exceptions_count++;
+ break;
+ case test_result::warn:
+ warnings_count++;
+ break;
+ case test_result::term:
+ terminations_count++;
+ break;
+ case tut::test_result::dummy:
+ assert(!"Should never be called");
+ } // switch
+
+ if (tr.result != tut::test_result::ok)
+ {
+ not_passed.push_back(tr);
+ }
+ }
+
+ void run_completed()
+ {
+ os << std::endl;
+
+ if (not_passed.size() > 0)
+ {
+ not_passed_list::const_iterator i = not_passed.begin();
+ while (i != not_passed.end())
+ {
+ tut::test_result tr = *i;
+
+ os << std::endl;
+
+ os << "---> " << "group: " << tr.group
+ << ", test: test<" << tr.test << ">"
+ << (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string())
+ << std::endl;
+
+#if defined(TUT_USE_POSIX)
+ if(tr.pid != getpid())
+ {
+ os << " child pid: " << tr.pid << std::endl;
+ }
+#endif
+ os << " problem: ";
+ switch(tr.result)
+ {
+ case test_result::rethrown:
+ os << "assertion failed in child" << std::endl;
+ break;
+ case test_result::fail:
+ os << "assertion failed" << std::endl;
+ break;
+ case test_result::ex:
+ case test_result::ex_ctor:
+ os << "unexpected exception" << std::endl;
+ if( tr.exception_typeid != "" )
+ {
+ os << " exception typeid: "
+ << tr.exception_typeid << std::endl;
+ }
+ break;
+ case test_result::term:
+ os << "would be terminated" << std::endl;
+ break;
+ case test_result::warn:
+ os << "test passed, but cleanup code (destructor) raised"
+ " an exception" << std::endl;
+ break;
+ default:
+ break;
+ }
+
+ if (!tr.message.empty())
+ {
+ if (tr.result == test_result::fail)
+ {
+ os << " failed assertion: \"" << tr.message << "\""
+ << std::endl;
+ }
+ else
+ {
+ os << " message: \"" << tr.message << "\""
+ << std::endl;
+ }
+ }
+
+ ++i;
+ }
+ }
+
+ os << std::endl;
+
+ os << "tests summary:";
+ if (terminations_count > 0)
+ {
+ os << " terminations:" << terminations_count;
+ }
+ if (exceptions_count > 0)
+ {
+ os << " exceptions:" << exceptions_count;
+ }
+ if (failures_count > 0)
+ {
+ os << " failures:" << failures_count;
+ }
+ if (warnings_count > 0)
+ {
+ os << " warnings:" << warnings_count;
+ }
+ os << " ok:" << ok_count;
+ os << std::endl;
+ }
+
+ bool all_ok() const
+ {
+ return not_passed.empty();
+ }
+
+private:
+
+ void init()
+ {
+ ok_count = 0;
+ exceptions_count = 0;
+ failures_count = 0;
+ terminations_count = 0;
+ warnings_count = 0;
+ not_passed.clear();
+ }
+};
+
+}
+
+#endif
Modified: trunk/tests/unit/tut/tut_exception.hpp
===================================================================
--- trunk/tests/unit/tut/tut_exception.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_exception.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -37,38 +37,6 @@
};
/**
- * Exception to be throwed when attempted to execute
- * missed test by number.
- */
-struct no_such_test : public tut_error
-{
- no_such_test()
- : tut_error("no such test")
- {
- }
-
- ~no_such_test() throw()
- {
- }
-};
-
-/**
- * No such test and passed test number is higher than
- * any test number in current group. Used in one-by-one
- * test running when upper bound is not known.
- */
-struct beyond_last_test : public no_such_test
-{
- beyond_last_test()
- {
- }
-
- ~beyond_last_test() throw()
- {
- }
-};
-
-/**
* Group not found exception.
*/
struct no_such_group : public tut_error
@@ -85,21 +53,6 @@
/**
* Internal exception to be throwed when
- * no more tests left in group or journal.
- */
-struct no_more_tests
-{
- no_more_tests()
- {
- }
-
- ~no_more_tests() throw()
- {
- }
-};
-
-/**
- * Internal exception to be throwed when
* test constructor has failed.
*/
struct bad_ctor : public tut_error
Modified: trunk/tests/unit/tut/tut_posix.hpp
===================================================================
--- trunk/tests/unit/tut/tut_posix.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_posix.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -65,11 +65,19 @@
pid_t fork()
{
test_object<T> *self = dynamic_cast< tut::test_object<T>* >(this);
- ensure("trying to call 'fork' in ctor of test object", self != NULL);
+ ensure("trying to call 'tut_fork' in ctor of test object", self != NULL);
return self->fork_();
}
+ pid_t waitpid(pid_t pid, int *status, int flags = 0)
+ {
+ test_object<T> *self = dynamic_cast< tut::test_object<T>* >(this);
+ ensure("trying to call 'tut_waitpid' in ctor of test object", self != NULL);
+
+ return self->waitpid_(pid, status, flags);
+ }
+
void ensure_child_exit(pid_t pid, int exit_status = 0)
{
test_object<T> *self = dynamic_cast< tut::test_object<T>* >(this);
@@ -188,7 +196,7 @@
else
{
// in child, shutdown reporter
- tut::runner.get().set_callback(NULL);
+ tut::runner.get().clear_callbacks();
// close reading side
close(fds[0]);
@@ -248,13 +256,13 @@
return;
}
else
- {
- std::stringstream ss;
+ {
+ std::stringstream ss;
char e[1024];
ss << "child " << pid << " could not be killed with SIGKILL, " << strerror_r(errno, e, sizeof(e)) << std::endl;
- fail(ss.str());
+ fail(ss.str());
+ }
}
- }
ensure_equals("wait after SIGKILL", waitpid_(pid, &status), pid);
ensure_child_signal_(status, SIGKILL);
@@ -290,8 +298,20 @@
return tr;
}
+ struct fdclose
+ {
+ fdclose(int fd): fd_(fd) { }
+ ~fdclose()
+ {
+ close(fd_);
+ }
+ private:
+ int fd_;
+ };
+
pid_t waitpid_(pid_t pid, int *status, int flags = 0)
{
+
ensure("trying to wait for unknown pid", pids_.count(pid) > 0);
pid_t p = ::waitpid(pid, status, flags);
@@ -309,6 +329,8 @@
FD_ZERO(&fdset);
int pipe = pids_[pid];
+ fdclose guard(pipe);
+
FD_SET(pipe, &fdset);
int result = select(pipe+1, &fdset, NULL, NULL, &tv);
@@ -417,7 +439,7 @@
return pids;
}
-
+
pid_map pids_;
int pipe_;
};
Modified: trunk/tests/unit/tut/tut_reporter.hpp
===================================================================
--- trunk/tests/unit/tut/tut_reporter.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_reporter.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -1,243 +1,11 @@
#ifndef TUT_REPORTER
#define TUT_REPORTER
-#include <tut/tut.hpp>
+#include <tut/tut_console_reporter.hpp>
-/**
- * Template Unit Tests Framework for C++.
- * http://tut.dozen.ru
- *
- * @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
- */
-namespace
-{
-
-std::ostream& operator<<(std::ostream& os, const tut::test_result& tr)
-{
- switch(tr.result)
- {
- case tut::test_result::ok:
- os << '.';
- break;
- case tut::test_result::fail:
- os << '[' << tr.test << "=F]";
- break;
- case tut::test_result::ex_ctor:
- os << '[' << tr.test << "=C]";
- break;
- case tut::test_result::ex:
- os << '[' << tr.test << "=X]";
- break;
- case tut::test_result::warn:
- os << '[' << tr.test << "=W]";
- break;
- case tut::test_result::term:
- os << '[' << tr.test << "=T]";
- break;
- case tut::test_result::rethrown:
- os << '[' << tr.test << "=P]";
- break;
- }
-
- return os;
-}
-
-} // end of namespace
-
namespace tut
{
-
-/**
- * Default TUT callback handler.
- */
-class reporter : public tut::callback
-{
- std::string current_group;
- typedef std::vector<tut::test_result> not_passed_list;
- not_passed_list not_passed;
- std::ostream& os;
-
-public:
-
- int ok_count;
- int exceptions_count;
- int failures_count;
- int terminations_count;
- int warnings_count;
-
- reporter()
- : os(std::cout)
- {
- init();
- }
-
- reporter(std::ostream& out)
- : os(out)
- {
- init();
- }
-
- void run_started()
- {
- init();
- }
-
- void test_completed(const tut::test_result& tr)
- {
- if (tr.group != current_group)
- {
- os << std::endl << tr.group << ": " << std::flush;
- current_group = tr.group;
- }
-
- os << tr << std::flush;
- if (tr.result == tut::test_result::ok)
- {
- ok_count++;
- }
- else if (tr.result == tut::test_result::ex)
- {
- exceptions_count++;
- }
- else if (tr.result == tut::test_result::ex_ctor)
- {
- exceptions_count++;
- }
- else if (tr.result == tut::test_result::fail)
- {
- failures_count++;
- }
- else if (tr.result == tut::test_result::rethrown)
- {
- failures_count++;
- }
- else if (tr.result == tut::test_result::warn)
- {
- warnings_count++;
- }
- else
- {
- terminations_count++;
- }
-
- if (tr.result != tut::test_result::ok)
- {
- not_passed.push_back(tr);
- }
- }
-
- void run_completed()
- {
- os << std::endl;
-
- if (not_passed.size() > 0)
- {
- not_passed_list::const_iterator i = not_passed.begin();
- while (i != not_passed.end())
- {
- tut::test_result tr = *i;
-
- os << std::endl;
-
- os << "---> " << "group: " << tr.group
- << ", test: test<" << tr.test << ">"
- << (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string())
- << std::endl;
-
-#if defined(TUT_USE_POSIX)
- if(tr.pid != getpid())
- {
- os << " child pid: " << tr.pid << std::endl;
- }
-#endif
- os << " problem: ";
- switch(tr.result)
- {
- case test_result::rethrown:
- os << "assertion failed in child" << std::endl;
- break;
- case test_result::fail:
- os << "assertion failed" << std::endl;
- break;
- case test_result::ex:
- case test_result::ex_ctor:
- os << "unexpected exception" << std::endl;
- if( tr.exception_typeid != "" )
- {
- os << " exception typeid: "
- << tr.exception_typeid << std::endl;
- }
- break;
- case test_result::term:
- os << "would be terminated" << std::endl;
- break;
- case test_result::warn:
- os << "test passed, but cleanup code (destructor) raised"
- " an exception" << std::endl;
- break;
- default:
- break;
- }
-
- if (!tr.message.empty())
- {
- if (tr.result == test_result::fail)
- {
- os << " failed assertion: \"" << tr.message << "\""
- << std::endl;
- }
- else
- {
- os << " message: \"" << tr.message << "\""
- << std::endl;
- }
- }
-
- ++i;
- }
- }
-
- os << std::endl;
-
- os << "tests summary:";
- if (terminations_count > 0)
- {
- os << " terminations:" << terminations_count;
- }
- if (exceptions_count > 0)
- {
- os << " exceptions:" << exceptions_count;
- }
- if (failures_count > 0)
- {
- os << " failures:" << failures_count;
- }
- if (warnings_count > 0)
- {
- os << " warnings:" << warnings_count;
- }
- os << " ok:" << ok_count;
- os << std::endl;
- }
-
- bool all_ok() const
- {
- return not_passed.empty();
- }
-
-private:
-
- void init()
- {
- ok_count = 0;
- exceptions_count = 0;
- failures_count = 0;
- terminations_count = 0;
- warnings_count = 0;
- not_passed.clear();
- }
-};
-
+ typedef console_reporter reporter;
}
#endif
Modified: trunk/tests/unit/tut/tut_restartable.hpp
===================================================================
--- trunk/tests/unit/tut/tut_restartable.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_restartable.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -7,11 +7,10 @@
#include <stdexcept>
/**
- * Template Unit Tests Framework for C++.
- * http://tut.dozen.ru
+ * Optional restartable wrapper for test_runner.
*
- * Optional restartable wrapper for test_runner. Allows to restart test runs
- * finished due to abnormal test application termination (such as segmentation
+ * Allows to restart test runs finished due to abnormal
+ * test application termination (such as segmentation
* fault or math error).
*
* @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
@@ -19,10 +18,10 @@
namespace tut
{
-
+
namespace util
{
-
+
/**
* Escapes non-alphabetical characters in string.
*/
@@ -124,12 +123,12 @@
/**
* deserialization for test_result
*/
-void deserialize(std::istream& is, tut::test_result& tr)
+bool deserialize(std::istream& is, tut::test_result& tr)
{
std::getline(is,tr.group);
if (is.eof())
{
- throw tut::no_more_tests();
+ return false;
}
tr.group = unescape(tr.group);
@@ -170,6 +169,7 @@
{
throw std::logic_error("malformed test result");
}
+ return true;
}
};
@@ -179,7 +179,7 @@
class restartable_wrapper
{
test_runner& runner_;
- callback* callback_;
+ callbacks callbacks_;
std::string dir_;
std::string log_; // log file: last test being executed
@@ -191,8 +191,7 @@
* @param dir Directory where to search/put log and journal files
*/
restartable_wrapper(const std::string& dir = ".")
- : runner_(runner.get()),
- callback_(0),
+ : runner_(runner.get()),
dir_(dir)
{
// dozen: it works, but it would be better to use system path separator
@@ -213,17 +212,30 @@
*/
void set_callback(callback* cb)
{
- callback_ = cb;
+ callbacks_.clear();
+ callbacks_.insert(cb);
}
- /**
- * Returns callback object.
- */
- callback& get_callback() const
+ void insert_callback(callback* cb)
{
- return runner_.get_callback();
+ callbacks_.insert(cb);
}
+ void erase_callback(callback* cb)
+ {
+ callbacks_.erase(cb);
+ }
+
+ void set_callbacks(const callbacks& cb)
+ {
+ callbacks_ = cb;
+ }
+
+ const callbacks& get_callbacks() const
+ {
+ return runner_.get_callbacks();
+ }
+
/**
* Returns list of known test groups.
*/
@@ -270,17 +282,17 @@
try
{
- tut::test_result tr = runner_.run_test(*gni,test);
+ tut::test_result tr;
+ if( !runner_.run_test(*gni,test, tr) )
+ {
+ break;
+ }
register_test_(tr);
}
catch (const tut::beyond_last_test&)
{
break;
}
- catch(const tut::no_such_test&)
- {
- // it's ok
- }
++test;
}
@@ -301,27 +313,22 @@
*/
void invoke_callback_() const
{
- runner_.set_callback(callback_);
- runner_.get_callback().run_started();
+ runner_.set_callbacks(callbacks_);
+ runner_.cb_run_started_();
std::string current_group;
std::ifstream ijournal(jrn_.c_str());
while (ijournal.good())
{
- // read next test result
- try
+ tut::test_result tr;
+ if( !util::deserialize(ijournal,tr) )
{
- tut::test_result tr;
- util::deserialize(ijournal,tr);
- runner_.get_callback().test_completed(tr);
- }
- catch (const no_more_tests&)
- {
break;
}
+ runner_.cb_test_completed_(tr);
}
- runner_.get_callback().run_completed();
+ runner_.cb_run_completed_();
}
/**
Modified: trunk/tests/unit/tut/tut_result.hpp
===================================================================
--- trunk/tests/unit/tut/tut_result.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_result.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -60,7 +60,8 @@
warn,
term,
ex_ctor,
- rethrown
+ rethrown,
+ dummy
};
result_type result;
Modified: trunk/tests/unit/tut/tut_runner.hpp
===================================================================
--- trunk/tests/unit/tut/tut_runner.hpp 2009-08-15 13:26:16 UTC (rev 2620)
+++ trunk/tests/unit/tut/tut_runner.hpp 2009-08-21 09:43:09 UTC (rev 2621)
@@ -3,6 +3,7 @@
#include <string>
#include <vector>
+#include <set>
#include "tut_exception.hpp"
namespace tut
@@ -20,10 +21,10 @@
// execute tests iteratively
virtual void rewind() = 0;
- virtual test_result run_next() = 0;
+ virtual bool run_next(test_result &) = 0;
// execute one test
- virtual test_result run_test(int n) = 0;
+ virtual bool run_test(int n, test_result &tr) = 0;
};
@@ -37,6 +38,13 @@
struct callback
{
/**
+ * Default constructor.
+ */
+ callback()
+ {
+ }
+
+ /**
* Virtual destructor is a must for subclassed types.
*/
virtual ~callback()
@@ -80,12 +88,16 @@
virtual void run_completed()
{
}
+private:
+ callback(const callback &);
+ void operator=(const callback&);
};
/**
* Typedef for runner::list_groups()
*/
typedef std::vector<std::string> groupnames;
+typedef std::set<callback*> callbacks;
/**
* Test runner.
@@ -99,7 +111,6 @@
* Constructor
*/
test_runner()
- : callback_(&default_callback_)
{
}
@@ -125,22 +136,46 @@
groups_.insert( std::make_pair(name, gr) );
}
+ void set_callback(callback *cb)
+ {
+ clear_callbacks();
+ insert_callback(cb);
+ }
+
/**
* Stores callback object.
*/
- void set_callback(callback* cb)
+ void insert_callback(callback* cb)
{
- callback_ = cb == 0 ? &default_callback_ : cb;
+ if(cb != NULL)
+ {
+ callbacks_.insert(cb);
+ }
}
+ void erase_callback(callback* cb)
+ {
+ callbacks_.erase(cb);
+ }
+
+ void clear_callbacks()
+ {
+ callbacks_.clear();
+ }
+
/**
- * Returns callback object.
+ * Returns callback list.
*/
- callback& get_callback() const
+ const callbacks &get_callbacks() const
{
- return *callback_;
+ return callbacks_;
}
+ void set_callbacks(const callbacks &cb)
+ {
+ callbacks_ = cb;
+ }
+
/**
* Returns list of known test groups.
*/
@@ -163,26 +198,20 @@
*/
void run_tests() const
{
- callback_->run_started();
+ cb_run_started_();
const_iterator i = groups_.begin();
const_iterator e = groups_.end();
while (i != e)
{
- callback_->group_started(i->first);
- try
- {
- run_all_tests_in_group_(i);
- }
- catch (const no_more_tests&)
- {
- callback_->group_completed(i->first);
- }
+ cb_group_started_(i->first);
+ run_all_tests_in_group_(i);
+ cb_group_completed_(i->first);
++i;
}
- callback_->run_completed();
+ cb_run_completed_();
}
/**
@@ -190,64 +219,48 @@
*/
void run_tests(const std::string& group_name) const
{
- callback_->run_started();
+ cb_run_started_();
const_iterator i = groups_.find(group_name);
if (i == groups_.end())
{
- callback_->run_completed();
+ cb_run_completed_();
throw no_such_group(group_name);
}
- callback_->group_started(group_name);
- try
- {
- run_all_tests_in_group_(i);
- }
- catch (const no_more_tests&)
- {
- // ok
- }
-
- callback_->group_completed(group_name);
- callback_->run_completed();
+ cb_group_started_(group_name);
+ run_all_tests_in_group_(i);
+ cb_group_completed_(group_name);
+ cb_run_completed_();
}
/**
* Runs one test in specified group.
*/
- test_result run_test(const std::string& group_name, int n) const
+ bool run_test(const std::string& group_name, int n, test_result &tr) const
{
- callback_->run_started();
+ cb_run_started_();
const_iterator i = groups_.find(group_name);
if (i == groups_.end())
{
- callback_->run_completed();
+ cb_run_completed_();
throw no_such_group(group_name);
}
- callback_->group_started(group_name);
- try
+ cb_group_started_(group_name);
+
+ bool t = i->second->run_test(n, tr);
+
+ if(t && tr.result != test_result::dummy)
{
- test_result tr = i->second->run_test(n);
- callback_->test_completed(tr);
- callback_->group_completed(group_name);
- callback_->run_completed();
- return tr;
+ cb_test_completed_(tr);
}
- catch (const beyond_last_test&)
- {
- callback_->group_completed(group_name);
- callback_->run_completed();
- throw;
- }
- catch (const no_such_test&)
- {
- callback_->group_completed(group_name);
- callback_->run_completed();
- throw;
- }
+
+ cb_group_completed_(group_name);
+ cb_run_completed_();
+
+ return t;
}
protected:
@@ -257,23 +270,67 @@
typedef groups::const_iterator const_iterator;
groups groups_;
- callback default_callback_;
- callback* callback_;
+ callbacks callbacks_;
-
private:
+ friend class restartable_wrapper;
+ void cb_run_started_() const
+ {
+ for(callbacks::const_iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
+ {
+ (*i)->run_started();
+ }
+ }
+
+ void cb_run_completed_() const
+ {
+ for(callbacks::const_iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
+ {
+ (*i)->run_completed();
+ }
+ }
+
+ void cb_group_started_(const std::string &group_name) const
+ {
+ for(callbacks::const_iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
+ {
+ (*i)->group_started(group_name);
+ }
+ }
+
+ void cb_group_completed_(const std::string &group_name) const
+ {
+ for(callbacks::const_iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
+ {
+ (*i)->group_completed(group_name);
+ }
+ }
+
+ void cb_test_completed_(const test_result &tr) const
+ {
+ for(callbacks::const_iterator i = callbacks_.begin(); i != callbacks_.end(); ++i)
+ {
+ (*i)->test_completed(tr);
+ }
+ }
+
void run_all_tests_in_group_(const_iterator i) const
{
i->second->rewind();
- for ( ;; )
+
+ test_result tr;
+ while(i->second->run_next(tr))
{
- test_result tr = i->second->run_next();
- callback_->test_completed(tr);
+ if(tr.result != test_result::dummy)
+ {
+ cb_test_completed_(tr);
+ }
if (tr.result == test_result::ex_ctor)
{
- throw no_more_tests();
+ // test object ctor failed, skip whole group
+ break;
}
}
}
More information about the geos-commits
mailing list