[haiku-commits] r34827 - in haiku/trunk/src/tests/system/kernel: . unit unit/lock

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 30 Dec 2009 20:38:41 +0100 (CET)

Author: bonefish
Date: 2009-12-30 20:38:41 +0100 (Wed, 30 Dec 2009)
New Revision: 34827
Changeset: http://dev.haiku-os.org/changeset/34827/haiku

Added:
   haiku/trunk/src/tests/system/kernel/unit/
   haiku/trunk/src/tests/system/kernel/unit/Jamfile
   haiku/trunk/src/tests/system/kernel/unit/Test.cpp
   haiku/trunk/src/tests/system/kernel/unit/Test.h
   haiku/trunk/src/tests/system/kernel/unit/TestContext.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestContext.h
   haiku/trunk/src/tests/system/kernel/unit/TestError.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestError.h
   haiku/trunk/src/tests/system/kernel/unit/TestManager.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestManager.h
   haiku/trunk/src/tests/system/kernel/unit/TestOutput.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestOutput.h
   haiku/trunk/src/tests/system/kernel/unit/TestSuite.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestSuite.h
   haiku/trunk/src/tests/system/kernel/unit/TestThread.h
   haiku/trunk/src/tests/system/kernel/unit/TestVisitor.cpp
   haiku/trunk/src/tests/system/kernel/unit/TestVisitor.h
   haiku/trunk/src/tests/system/kernel/unit/kernel_unit_tests.cpp
   haiku/trunk/src/tests/system/kernel/unit/lock/
   haiku/trunk/src/tests/system/kernel/unit/lock/Jamfile
   haiku/trunk/src/tests/system/kernel/unit/lock/LockTestSuite.cpp
   haiku/trunk/src/tests/system/kernel/unit/lock/LockTestSuite.h
   haiku/trunk/src/tests/system/kernel/unit/lock/RWLockTests.cpp
   haiku/trunk/src/tests/system/kernel/unit/lock/RWLockTests.h
Modified:
   haiku/trunk/src/tests/system/kernel/Jamfile
Log:
* Added a framework for unit tests in the kernel. The beast is implemented as
  a driver which publishes a device as "/dev/kernel_unit_tests". Commands
  can be issued by writing to the device (e.g.
  "echo help > /dev/kernel_unit_tests"), output is written to serial port/
  syslog.
* Added a few tests for rw_lock.


Modified: haiku/trunk/src/tests/system/kernel/Jamfile
===================================================================
--- haiku/trunk/src/tests/system/kernel/Jamfile 2009-12-30 15:17:09 UTC (rev 
34826)
+++ haiku/trunk/src/tests/system/kernel/Jamfile 2009-12-30 19:38:41 UTC (rev 
34827)
@@ -85,4 +85,5 @@
 SubInclude HAIKU_TOP src tests system kernel scheduler ;
 SubInclude HAIKU_TOP src tests system kernel slab ;
 SubInclude HAIKU_TOP src tests system kernel swap ;
+SubInclude HAIKU_TOP src tests system kernel unit ;
 SubInclude HAIKU_TOP src tests system kernel util ;

Added: haiku/trunk/src/tests/system/kernel/unit/Jamfile
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/Jamfile                            
(rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/Jamfile    2009-12-30 19:38:41 UTC 
(rev 34827)
@@ -0,0 +1,23 @@
+SubDir HAIKU_TOP src tests system kernel unit ;
+
+UsePrivateKernelHeaders ;
+
+
+KernelAddon kernel_unit_tests :
+       kernel_unit_tests.cpp
+       Test.cpp
+       TestContext.cpp
+       TestError.cpp
+       TestManager.cpp
+       TestOutput.cpp
+       TestSuite.cpp
+       TestVisitor.cpp
+
+       :
+       <nogrist>kernel_unit_tests_lock.o
+
+       $(TARGET_STATIC_LIBSUPC++)
+;
+
+
+HaikuSubInclude lock ;

Added: haiku/trunk/src/tests/system/kernel/unit/Test.cpp
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/Test.cpp                           
(rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/Test.cpp   2009-12-30 19:38:41 UTC 
(rev 34827)
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "Test.h"
+
+#include "TestVisitor.h"
+
+
+// #pragma mark - Test
+
+
+Test::Test(const char* name)
+       :
+       fName(name),
+       fSuite(NULL)
+{
+}
+
+
+Test::~Test()
+{
+}
+
+
+void
+Test::SetSuite(TestSuite* suite)
+{
+       fSuite = suite;
+}
+
+
+bool
+Test::IsLeafTest() const
+{
+       return true;
+}
+
+
+status_t
+Test::Setup(TestContext& context)
+{
+       return B_OK;
+}
+
+
+bool
+Test::Run(TestContext& context, const char* name)
+{
+// TODO: Report error!
+       return false;
+}
+
+
+void
+Test::Cleanup(TestContext& context, bool setupOK)
+{
+}
+
+
+Test*
+Test::Visit(TestVisitor& visitor)
+{
+       return visitor.VisitTest(this) ? this : NULL;
+}
+
+
+// #pragma mark - StandardTestDelegate
+
+
+StandardTestDelegate::StandardTestDelegate()
+{
+}
+
+
+StandardTestDelegate::~StandardTestDelegate()
+{
+}
+
+
+status_t
+StandardTestDelegate::Setup(TestContext& context)
+{
+       return B_OK;
+}
+
+
+void
+StandardTestDelegate::Cleanup(TestContext& context, bool setupOK)
+{
+}

Added: haiku/trunk/src/tests/system/kernel/unit/Test.h
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/Test.h                             
(rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/Test.h     2009-12-30 19:38:41 UTC 
(rev 34827)
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef TEST_H
+#define TEST_H
+
+
+#include "TestContext.h"
+
+
+class TestSuite;
+class TestVisitor;
+
+
+class Test {
+public:
+                                                               Test(const 
char* name);
+       virtual                                         ~Test();
+
+                       const char*                     Name() const    { 
return fName; }
+
+                       TestSuite*                      Suite() const   { 
return fSuite; }
+                       void                            SetSuite(TestSuite* 
suite);
+
+       virtual bool                            IsLeafTest() const;
+       virtual status_t                        Setup(TestContext& context);
+       virtual bool                            Run(TestContext& context) = 0;
+       virtual bool                            Run(TestContext& context, const 
char* name);
+       virtual void                            Cleanup(TestContext& context, 
bool setupOK);
+
+       virtual Test*                           Visit(TestVisitor& visitor);
+
+private:
+                       const char*                     fName;
+                       TestSuite*                      fSuite;
+};
+
+
+class StandardTestDelegate {
+public:
+                                                               
StandardTestDelegate();
+       virtual                                         ~StandardTestDelegate();
+
+       virtual status_t                        Setup(TestContext& context);
+       virtual void                            Cleanup(TestContext& context, 
bool setupOK);
+};
+
+
+template<typename TestClass>
+class StandardTest : public Test {
+public:
+                                                               
StandardTest(const char* name,
+                                                                       
TestClass* object,
+                                                                       bool 
(TestClass::*method)(TestContext&));
+       virtual                                         ~StandardTest();
+
+       virtual status_t                        Setup(TestContext& context);
+       virtual bool                            Run(TestContext& context);
+       virtual void                            Cleanup(TestContext& context, 
bool setupOK);
+
+private:
+                       TestClass*                      fObject;
+                       bool                            
(TestClass::*fMethod)(TestContext&);
+};
+
+
+template<typename TestClass>
+StandardTest<TestClass>::StandardTest(const char* name, TestClass* object,
+       bool (TestClass::*method)(TestContext&))
+       :
+       Test(name),
+       fObject(object),
+       fMethod(method)
+{
+}
+
+
+template<typename TestClass>
+StandardTest<TestClass>::~StandardTest()
+{
+       delete fObject;
+}
+
+
+template<typename TestClass>
+status_t
+StandardTest<TestClass>::Setup(TestContext& context)
+{
+       return fObject->Setup(context);
+}
+
+
+template<typename TestClass>
+bool
+StandardTest<TestClass>::Run(TestContext& context)
+{
+       return (fObject->*fMethod)(context);
+}
+
+
+template<typename TestClass>
+void
+StandardTest<TestClass>::Cleanup(TestContext& context, bool setupOK)
+{
+       fObject->Cleanup(context, setupOK);
+}
+
+
+#define TEST_ASSERT(condition)                                                 
                                \
+       do {                                                                    
                                                        \
+               if (!(condition)) {                                             
                                                \
+                       TestContext::Current()->AssertFailed(__FILE__, 
__LINE__,        \
+                               __PRETTY_FUNCTION__, #condition);               
                                \
+                       return false;                                           
                                                \
+               }                                                               
                                                                \
+       } while (false)
+
+#define TEST_ASSERT_PRINT(condition, format...)                                
                        \
+       do {                                                                    
                                                        \
+               if (!(condition)) {                                             
                                                \
+                       TestContext::Current()->AssertFailed(__FILE__, 
__LINE__,        \
+                               __PRETTY_FUNCTION__, #condition, format);       
                        \
+                       return false;                                           
                                                \
+               }                                                               
                                                                \
+       } while (false)
+
+#define TEST_PROPAGATE(result)                                                 
                                \
+       do {                                                                    
                                                        \
+               if (!(result))                                                  
                                                \
+                       return false;                                           
                                                \
+       } while (false)
+
+
+#endif // TEST_H

Added: haiku/trunk/src/tests/system/kernel/unit/TestContext.cpp
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestContext.cpp                    
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestContext.cpp    2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "TestContext.h"
+
+#include <util/AutoLock.h>
+
+#include "Test.h"
+#include "TestError.h"
+
+
+static spinlock sLock = B_SPINLOCK_INITIALIZER;
+
+
+// #pragma mark - TestOptions
+
+
+TestOptions::TestOptions()
+       :
+       panicOnFailure(false),
+       quitAfterFailure(false)
+{
+}
+
+
+// #pragma mark - GlobalTestContext
+
+
+struct GlobalTestContext::ThreadCookie {
+       GlobalTestContext*      context;
+       thread_func                     function;
+       void*                           arg;
+
+       ThreadCookie(GlobalTestContext* context, thread_func function, void* 
arg)
+               :
+               context(context),
+               function(function),
+               arg(arg)
+       {
+       }
+};
+
+
+/*static*/ GlobalTestContext::ThreadEntry* GlobalTestContext::sGlobalThreads
+       = NULL;
+
+
+GlobalTestContext::GlobalTestContext(TestOutput& output, TestOptions& options)
+       :
+       fThreads(NULL),
+       fThreadEntry(this),
+       fOutput(output),
+       fOptions(options),
+       fCurrentContext(NULL),
+       fTotalTests(0),
+       fFailedTests(0)
+{
+       _SetCurrent(&fThreadEntry);
+}
+
+
+GlobalTestContext::~GlobalTestContext()
+{
+       InterruptsSpinLocker locker(sLock);
+
+       // remove all of our entries from the global list
+       ThreadEntry** entry = &sGlobalThreads;
+       while (*entry != NULL) {
+               if ((*entry)->context == this)
+                       *entry = (*entry)->globalNext;
+               else
+                       entry = &(*entry)->globalNext;
+       }
+}
+
+
+/*static*/ GlobalTestContext*
+GlobalTestContext::Current()
+{
+       thread_id thread = find_thread(NULL);
+
+       InterruptsSpinLocker locker(sLock);
+
+       ThreadEntry* entry = sGlobalThreads;
+       while (entry != NULL) {
+               if (entry->thread == thread)
+                       return entry->context;
+               entry = entry->globalNext;
+       }
+
+       return NULL;
+}
+
+
+void
+GlobalTestContext::SetCurrentContext(TestContext* context)
+{
+       fCurrentContext = context;
+}
+
+
+void
+GlobalTestContext::TestDone(bool success)
+{
+       fTotalTests++;
+       if (!success)
+               fFailedTests++;
+}
+
+
+thread_id
+GlobalTestContext::SpawnThread(thread_func function, const char* name,
+       int32 priority, void* arg)
+{
+       ThreadCookie* cookie = new(std::nothrow) ThreadCookie(this, function, 
arg);
+       if (cookie == NULL)
+               return B_NO_MEMORY;
+
+       thread_id thread = spawn_kernel_thread(_ThreadEntry, name, priority,
+               cookie);
+       if (thread < 0) {
+               delete cookie;
+               return thread;
+       }
+
+       return thread;
+}
+
+
+/*static*/ void
+GlobalTestContext::_SetCurrent(ThreadEntry* entry)
+{
+       InterruptsSpinLocker locker(sLock);
+
+       entry->contextNext = entry->context->fThreads;
+       entry->context->fThreads = entry;
+
+       entry->globalNext = sGlobalThreads;
+       sGlobalThreads = entry;
+}
+
+
+/*static*/ void
+GlobalTestContext::_UnsetCurrent(ThreadEntry* entryToRemove)
+{
+       InterruptsSpinLocker locker(sLock);
+
+       // remove from the global list
+       ThreadEntry** entry = &sGlobalThreads;
+       while (*entry != NULL) {
+               if (*entry == entryToRemove) {
+                       *entry = (*entry)->globalNext;
+                       break;
+               }
+
+               entry = &(*entry)->globalNext;
+       }
+
+       // remove from the context's list
+       entry = &entryToRemove->context->fThreads;
+       while (*entry != NULL) {
+               if (*entry == entryToRemove) {
+                       *entry = (*entry)->contextNext;
+                       break;
+               }
+
+               entry = &(*entry)->contextNext;
+       }
+}
+
+
+/*static*/ status_t
+GlobalTestContext::_ThreadEntry(void* data)
+{
+       ThreadCookie* cookie = (ThreadCookie*)data;
+
+       ThreadEntry entry(cookie->context);
+       _SetCurrent(&entry);
+
+       thread_func function = cookie->function;
+       void* arg = cookie->arg;
+       delete cookie;
+
+       status_t result = function(arg);
+
+       _UnsetCurrent(&entry);
+
+       return result;
+}
+
+
+// #pragma mark - TestContext
+
+
+TestContext::TestContext(GlobalTestContext* globalContext)
+       :
+       fGlobalContext(globalContext),
+       fParent(NULL),
+       fTest(NULL),
+       fErrors(NULL),
+       fLevel(0)
+{
+       fGlobalContext->SetCurrentContext(this);
+}
+
+
+TestContext::TestContext(TestContext& parent, Test* test)
+       :
+       fGlobalContext(parent.GlobalContext()),
+       fParent(&parent),
+       fTest(test),
+       fErrors(NULL),
+       fLevel(parent.Level() + 1)
+{
+       fGlobalContext->SetCurrentContext(this);
+
+       if (fTest != NULL) {
+               if (fTest->IsLeafTest())
+                       Print("%*s%s...", fLevel * 2, "", test->Name());
+               else
+                       Print("%*s%s:\n", fLevel * 2, "", test->Name());
+       }
+}
+
+
+TestContext::~TestContext()
+{
+       fGlobalContext->SetCurrentContext(fParent);
+
+       while (fErrors != NULL) {
+               TestError* error = fErrors;
+               fErrors = error->ListLink();
+               delete error;
+       }
+}
+
+
+void
+TestContext::TestDone(bool success)
+{
+       if (fTest != NULL && fTest->IsLeafTest()) {
+               if (success) {
+                       Print(" ok\n");
+               } else {
+                       Print(" FAILED\n");
+                       TestError* error = fErrors;
+                       while (error != NULL) {
+                               Print("%s", error->Message());
+                               error = error->ListLink();
+                       }
+               }
+
+               fGlobalContext->TestDone(success);
+       }
+}
+
+
+void
+TestContext::ErrorArgs(const char* format, va_list args)
+{
+       int size = vsnprintf(NULL, 0, format, args) + 1;
+       char* buffer = (char*)malloc(size);
+       if (buffer == NULL)
+               return;
+
+       vsnprintf(buffer, size, format, args);
+
+       TestError* error = new(std::nothrow) TestError(fTest, buffer);
+       if (error == NULL) {
+               free(buffer);
+               return;
+       }
+
+       InterruptsSpinLocker locker(sLock);
+       error->ListLink() = fErrors;
+       fErrors = error;
+
+       if (Options().panicOnFailure)
+               panic("Test check failed: %s", error->Message());
+}

Added: haiku/trunk/src/tests/system/kernel/unit/TestContext.h
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestContext.h                      
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestContext.h      2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef TEST_CONTEXT_H
+#define TEST_CONTEXT_H
+
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <KernelExport.h>
+
+#include "TestOutput.h"
+
+
+class Test;
+class TestContext;
+class TestError;
+
+
+struct TestOptions {
+                       bool                            panicOnFailure;
+                       bool                            quitAfterFailure;
+
+       public:
+                                                               TestOptions();
+};
+
+
+struct GlobalTestContext {
+                                                               
GlobalTestContext(TestOutput& output,
+                                                                       
TestOptions& options);
+                                                               
~GlobalTestContext();
+
+       static  GlobalTestContext*      Current();
+
+                       TestOutput&                     Output() const  { 
return fOutput; }
+                       TestOptions&            Options() const { return 
fOptions; }
+
+                       TestContext*            CurrentContext() const
+                                                                       { 
return fCurrentContext; }
+                       void                            
SetCurrentContext(TestContext* context);
+
+                       int32                           TotalTests() const      
{ return fTotalTests; }
+                       int32                           FailedTests() const     
{ return fFailedTests; }
+
+                       void                            TestDone(bool success);
+
+                       thread_id                       SpawnThread(thread_func 
function,
+                                                                       const 
char* name, int32 priority,
+                                                                       void* 
arg);
+
+private:
+                       struct ThreadEntry {
+                               ThreadEntry*            globalNext;
+                               ThreadEntry*            contextNext;
+                               GlobalTestContext*      context;
+                               thread_id                       thread;
+
+                               ThreadEntry(GlobalTestContext* context)
+                                       :
+                                       globalNext(NULL),
+                                       contextNext(NULL),
+                                       context(context),
+                                       thread(find_thread(NULL))
+                               {
+                               }
+                       };
+
+                       struct ThreadCookie;
+
+private:
+       static  void                            _SetCurrent(ThreadEntry* entry);
+       static  void                            _UnsetCurrent(ThreadEntry* 
entry);
+       static  status_t                        _ThreadEntry(void* data);
+
+private:
+       static  ThreadEntry*            sGlobalThreads;
+                       ThreadEntry*            fThreads;
+                       ThreadEntry                     fThreadEntry;
+                       TestOutput&                     fOutput;
+                       TestOptions&            fOptions;
+                       TestContext*            fCurrentContext;
+                       int32                           fTotalTests;
+                       int32                           fFailedTests;
+};
+
+
+class TestContext {
+public:
+                                                               
TestContext(GlobalTestContext* globalContext);
+                                                               
TestContext(TestContext& parent, Test* test);
+                                                               ~TestContext();
+
+       static  TestContext*            Current();
+
+                       GlobalTestContext*      GlobalContext() const { return 
fGlobalContext; }
+                       TestContext*            Parent() const  { return 
fParent; }
+                       int32                           Level() const   { 
return fLevel; }
+                       TestOutput&                     Output() const
+                                                                       { 
return fGlobalContext->Output(); }
+                       TestOptions&            Options() const
+                                                                       { 
return fGlobalContext->Options(); }
+
+       inline  int                                     PrintArgs(const char* 
format, va_list args);
+       inline  int                                     Print(const char* 
format,...);
+
+                       void                            ErrorArgs(const char* 
format, va_list args);
+       inline  void                            Error(const char* format,...);
+
+       inline  void                            AssertFailed(const char* file, 
int line,
+                                                                       const 
char* function,
+                                                                       const 
char* condition);
+       inline  void                            AssertFailed(const char* file, 
int line,
+                                                                       const 
char* function,
+                                                                       const 
char* condition,
+                                                                       const 
char* format,...);
+
+                       void                            TestDone(bool success);
+
+private:
+                       GlobalTestContext*      fGlobalContext;
+                       TestContext*            fParent;
+                       Test*                           fTest;
+                       TestError*                      fErrors;
+                       int32                           fLevel;
+};
+
+
+/*static*/ inline TestContext*
+TestContext::Current()
+{
+       return GlobalTestContext::Current()->CurrentContext();
+}
+
+
+int
+TestContext::PrintArgs(const char* format, va_list args)
+{
+       return Output().PrintArgs(format, args);
+}
+
+
+int
+TestContext::Print(const char* format,...)
+{
+       va_list args;
+       va_start(args, format);
+       int result = Output().PrintArgs(format, args);
+       va_end(args);
+
+       return result;
+}
+
+
+void
+TestContext::Error(const char* format,...)
+{
+       va_list args;
+       va_start(args, format);
+       ErrorArgs(format, args);
+       va_end(args);
+}
+
+
+void
+TestContext::AssertFailed(const char* file, int line, const char* function,
+       const char* condition)
+{
+       Error("ASSERT FAILED at %s:%d %s: %s\n", file, line, function, 
condition);
+}
+
+
+void
+TestContext::AssertFailed(const char* file, int line, const char* function,
+       const char* condition, const char* format,...)
+{
+       char buffer[256];
+
+       va_list args;
+       va_start(args, format);
+       vsnprintf(buffer, sizeof(buffer), format, args);
+       va_end(args);
+
+       Error("ASSERT FAILED at %s:%d %s: %s; %s\n", file, line, function,
+               condition, buffer);
+}
+
+
+#endif // TEST_CONTEXT_H

Added: haiku/trunk/src/tests/system/kernel/unit/TestError.cpp
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestError.cpp                      
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestError.cpp      2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "TestError.h"
+
+#include <stdlib.h>
+
+
+TestError::TestError(Test* test, char* message)
+       :
+       fTest(test),
+       fMessage(message)
+{
+}
+
+
+TestError::~TestError()
+{
+       free(fMessage);
+}

Added: haiku/trunk/src/tests/system/kernel/unit/TestError.h
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestError.h                        
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestError.h        2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef TEST_ERROR_H
+#define TEST_ERROR_H
+
+
+#include <SupportDefs.h>
+
+
+class Test;
+
+
+class TestError {
+public:
+                                                               TestError(Test* 
test, char* message);
+                                                               ~TestError();
+
+                       Test*                           GetTest() const { 
return fTest; }
+                       const char*                     Message() const { 
return fMessage; }
+
+                       TestError*&                     ListLink()      { 
return fNext; }
+
+private:
+                       TestError*                      fNext;
+                       Test*                           fTest;
+                       char*                           fMessage;
+};
+
+
+#endif // TEST_ERROR_H

Added: haiku/trunk/src/tests/system/kernel/unit/TestManager.cpp
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestManager.cpp                    
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestManager.cpp    2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "TestManager.h"
+
+#include <string.h>
+
+#include "TestOutput.h"
+#include "TestVisitor.h"
+
+
+TestManager::TestManager()
+       :
+       TestSuite("all")
+{
+}
+
+
+TestManager::~TestManager()
+{
+}
+
+
+void
+TestManager::ListTests(TestOutput& output)
+{
+       struct Visitor : TestVisitor {
+               Visitor(TestOutput& output)
+                       :
+                       fOutput(output),
+                       fLevel(0)
+               {
+               }
+
+               virtual bool VisitTest(Test* test)
+               {
+                       fOutput.Print("%*s%s\n", fLevel * 2, "", test->Name());
+                       return false;
+               }
+
+               virtual bool VisitTestSuitePre(TestSuite* suite)
+               {
+                       if (fLevel > 0)
+                               VisitTest(suite);
+                       fLevel++;
+                       return false;
+               }
+
+               virtual bool VisitTestSuitePost(TestSuite* suite)
+               {
+                       fLevel--;
+                       return false;
+               }
+
+       private:
+               TestOutput&     fOutput;
+               int                     fLevel;
+       } visitor(output);
+
+       output.Print("Available tests:\n");
+       Visit(visitor);
+}
+
+
+void
+TestManager::RunTests(GlobalTestContext& globalContext,
+       const char* const* tests, int testCount)
+{
+       TestContext context(&globalContext);
+
+       context.Print("Running tests:\n");
+
+       if (testCount == 0 || (testCount == 1 && strcmp(tests[0], "all") == 0)) 
{
+               Run(context);
+       } else {
+               for (int i = 0; i < testCount; i++) {
+                       bool result = Run(context, tests[i]);
+                       if (!result && context.Options().quitAfterFailure)
+                               break;
+               }
+       }
+
+       context.Print("run tests: %ld, failed tests: %ld\n",
+               globalContext.TotalTests(), globalContext.FailedTests());
+}

Added: haiku/trunk/src/tests/system/kernel/unit/TestManager.h
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestManager.h                      
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestManager.h      2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef TEST_MANAGER_H
+#define TEST_MANAGER_H
+
+
+#include "TestSuite.h"
+
+
+class GlobalTestContext;
+class TestOutput;
+
+
+class TestManager : public TestSuite {
+public:
+                                                               TestManager();
+                                                               ~TestManager();
+
+                       void                            ListTests(TestOutput& 
output);
+                       void                            
RunTests(GlobalTestContext& globalContext,
+                                                                       const 
char* const* tests, int testCount);
+};
+
+
+#endif // TEST_MANAGER_H

Added: haiku/trunk/src/tests/system/kernel/unit/TestOutput.cpp
===================================================================
--- haiku/trunk/src/tests/system/kernel/unit/TestOutput.cpp                     
        (rev 0)
+++ haiku/trunk/src/tests/system/kernel/unit/TestOutput.cpp     2009-12-30 
19:38:41 UTC (rev 34827)
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "TestOutput.h"
+
+#include <stdio.h>
+
+#include <util/AutoLock.h>
+
+
+// #pragma mark - TestOutput
+
+
+TestOutput::TestOutput()
+{
+}
+
+
+TestOutput::~TestOutput()
+{
+}
+
+
+// #pragma mark - DebugTestOutput
+
+
+DebugTestOutput::DebugTestOutput()
+{
+       B_INITIALIZE_SPINLOCK(&fLock);
+}
+
+

[... truncated: 1113 lines follow ...]

Other related posts: