Big CppUnit update
+ Initial threaded test support + Integrated CppUnitShell code into TestShell git-svn-id: file:///srv/svn/repos/haiku/trunk/current@75 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
#ifndef _beos_thread_manager_h_
|
||||
#define _beos_thread_manager_h_
|
||||
|
||||
#include <cppunit/Exception.h>
|
||||
#include <cppunit/TestResult.h>
|
||||
#include <kernel/OS.h>
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
|
||||
//class ThreadedTestCase;
|
||||
class CppUnit::TestResult;
|
||||
|
||||
// Pointer to a function that takes no parameters and
|
||||
// returns no result. All threads must be implemented
|
||||
// in a function of this type.
|
||||
|
||||
// Helper class to handle thread management
|
||||
template <class TestClass, class ExpectedException>
|
||||
class BThreadManager {
|
||||
public:
|
||||
typedef void (TestClass::*ThreadMethod)();
|
||||
|
||||
BThreadManager(std::string threadName, TestClass *object, ThreadMethod method);
|
||||
~BThreadManager();
|
||||
|
||||
status_t LaunchThread(CppUnit::TestResult *result);
|
||||
|
||||
// Thread management methods
|
||||
int32 Stop();
|
||||
int32 WaitForThread();
|
||||
bool IsRunning();
|
||||
|
||||
std::string getName() const { return fName; }
|
||||
|
||||
protected:
|
||||
std::string fName;
|
||||
TestClass *fObject;
|
||||
ThreadMethod fMethod;
|
||||
thread_id fID;
|
||||
CppUnit::TestResult *fTestResult;
|
||||
|
||||
static long EntryFunction(BThreadManager<TestClass, ExpectedException>* manager);
|
||||
void Run();
|
||||
|
||||
};
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
BThreadManager<TestClass, ExpectedException>::BThreadManager(
|
||||
std::string threadName,
|
||||
TestClass *object,
|
||||
ThreadMethod method
|
||||
)
|
||||
: fName(threadName)
|
||||
, fObject(object)
|
||||
, fMethod(method)
|
||||
, fID(0)
|
||||
, fTestResult(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
BThreadManager<TestClass, ExpectedException>::~BThreadManager() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
int32
|
||||
BThreadManager<TestClass, ExpectedException>::WaitForThread() {
|
||||
int32 result = 0;
|
||||
if (find_thread(NULL) != fID)
|
||||
wait_for_thread(fID, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
int32
|
||||
BThreadManager<TestClass, ExpectedException>::Stop() {
|
||||
int32 result = 0;
|
||||
if (find_thread(NULL) != fID) {
|
||||
while (IsRunning()) {
|
||||
kill(fID, SIGINT);
|
||||
snooze(1000000);
|
||||
}
|
||||
result = WaitForThread();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
bool
|
||||
BThreadManager<TestClass, ExpectedException>::IsRunning(void) {
|
||||
if (fID != 0) {
|
||||
thread_info info;
|
||||
if (get_thread_info(fID, &info) == B_OK)
|
||||
return true;
|
||||
else
|
||||
fID = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
status_t
|
||||
BThreadManager<TestClass, ExpectedException>::LaunchThread(CppUnit::TestResult *result) {
|
||||
if (IsRunning())
|
||||
return B_ALREADY_RUNNING;
|
||||
|
||||
fTestResult = result;
|
||||
fID = spawn_thread((thread_entry)(BThreadManager::EntryFunction),
|
||||
fName.c_str(), B_NORMAL_PRIORITY, this);
|
||||
|
||||
status_t err;
|
||||
if (fID == B_NO_MORE_THREADS || fID == B_NO_MEMORY) {
|
||||
err = fID;
|
||||
fID = 0;
|
||||
} else {
|
||||
err = resume_thread(fID);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
long
|
||||
BThreadManager<TestClass, ExpectedException>::EntryFunction(BThreadManager<TestClass, ExpectedException> *manager) {
|
||||
manager->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class TestClass, class ExpectedException>
|
||||
void
|
||||
BThreadManager<TestClass, ExpectedException>::Run(void) {
|
||||
// These outer try/catch blocks handle unexpected exceptions.
|
||||
// Said exceptions are caught and noted in the TestResult
|
||||
// class, but not allowed to escape and disrupt the other
|
||||
// threads that are assumingly running concurrently.
|
||||
try {
|
||||
|
||||
// Our parent ThreadedTestCaller should check fObject to be non-NULL,
|
||||
// but we'll do it here too just to be sure.
|
||||
if (!fObject)
|
||||
throw CppUnit::Exception("BThreadManager::Run() -- NULL fObject pointer");
|
||||
|
||||
// Before running, we need to add this thread's name to
|
||||
// the object's id->(name,subtestnum) map.
|
||||
fObject->InitThreadInfo(fID, fName);
|
||||
|
||||
// This inner try/catch block is for expected exceptions.
|
||||
// If we get through it without an exception, we have to
|
||||
// raise a different exception that makes note of the fact
|
||||
// that the exception we were expecting didn't arrive. If
|
||||
// no exception is expected, then nothing is done (see
|
||||
// "cppunit/TestCaller.h" for detail on the classes used
|
||||
// to handle this behaviour).
|
||||
try {
|
||||
(fObject->*fMethod)();
|
||||
} catch ( ExpectedException & ) {
|
||||
return;
|
||||
}
|
||||
CppUnit::ExpectedExceptionTraits<ExpectedException>::expectedException();
|
||||
|
||||
} catch ( CppUnit::Exception &e ) {
|
||||
// Add on the thread name, then note the exception
|
||||
CppUnit::Exception *threadException = new CppUnit::Exception(
|
||||
std::string(e.what()) + " (thread: " + fName + ")",
|
||||
e.sourceLine()
|
||||
);
|
||||
fTestResult->addFailure( fObject, threadException );
|
||||
}
|
||||
catch ( std::exception &e ) {
|
||||
// Add on the thread name, then note the exception
|
||||
CppUnit::Exception *threadException = new CppUnit::Exception(
|
||||
std::string(e.what()) + " (thread: " + fName + ")"
|
||||
);
|
||||
fTestResult->addError( fObject, threadException );
|
||||
}
|
||||
catch (...) {
|
||||
// Add on the thread name, then note the exception
|
||||
CppUnit::Exception *threadException = new CppUnit::Exception(
|
||||
"caught unknown exception (thread: " + fName + ")"
|
||||
);
|
||||
fTestResult->addError( fObject, threadException );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user