1/* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5#ifndef TEST_CONTEXT_H 6#define TEST_CONTEXT_H 7 8 9#include <stdarg.h> 10#include <stdio.h> 11 12#include <KernelExport.h> 13 14#include "TestOutput.h" 15 16 17class Test; 18class TestContext; 19class TestError; 20 21 22struct TestOptions { 23 bool panicOnFailure; 24 bool quitAfterFailure; 25 26 public: 27 TestOptions(); 28}; 29 30 31struct GlobalTestContext { 32 GlobalTestContext(TestOutput& output, 33 TestOptions& options); 34 ~GlobalTestContext(); 35 36 static GlobalTestContext* Current(); 37 38 TestOutput& Output() const { return fOutput; } 39 TestOptions& Options() const { return fOptions; } 40 41 TestContext* CurrentContext() const 42 { return fCurrentContext; } 43 void SetCurrentContext(TestContext* context); 44 45 int32 TotalTests() const { return fTotalTests; } 46 int32 FailedTests() const { return fFailedTests; } 47 48 void TestDone(bool success); 49 50 thread_id SpawnThread(thread_func function, 51 const char* name, int32 priority, 52 void* arg); 53 54private: 55 struct ThreadEntry { 56 ThreadEntry* globalNext; 57 ThreadEntry* contextNext; 58 GlobalTestContext* context; 59 thread_id thread; 60 61 ThreadEntry(GlobalTestContext* context) 62 : 63 globalNext(NULL), 64 contextNext(NULL), 65 context(context), 66 thread(find_thread(NULL)) 67 { 68 } 69 }; 70 71 struct ThreadCookie; 72 73private: 74 static void _SetCurrent(ThreadEntry* entry); 75 static void _UnsetCurrent(ThreadEntry* entry); 76 static status_t _ThreadEntry(void* data); 77 78private: 79 static ThreadEntry* sGlobalThreads; 80 ThreadEntry* fThreads; 81 ThreadEntry fThreadEntry; 82 TestOutput& fOutput; 83 TestOptions& fOptions; 84 TestContext* fCurrentContext; 85 int32 fTotalTests; 86 int32 fFailedTests; 87}; 88 89 90class TestContext { 91public: 92 TestContext(GlobalTestContext* globalContext); 93 TestContext(TestContext& parent, Test* test); 94 ~TestContext(); 95 96 static TestContext* Current(); 97 98 GlobalTestContext* GlobalContext() const { return fGlobalContext; } 99 TestContext* Parent() const { return fParent; } 100 int32 Level() const { return fLevel; } 101 TestOutput& Output() const 102 { return fGlobalContext->Output(); } 103 TestOptions& Options() const 104 { return fGlobalContext->Options(); } 105 106 inline int PrintArgs(const char* format, va_list args); 107 inline int Print(const char* format,...); 108 109 void ErrorArgs(const char* format, va_list args); 110 inline void Error(const char* format,...); 111 112 inline void AssertFailed(const char* file, int line, 113 const char* function, 114 const char* condition); 115 inline void AssertFailed(const char* file, int line, 116 const char* function, 117 const char* condition, 118 const char* format,...); 119 120 void TestDone(bool success); 121 122private: 123 GlobalTestContext* fGlobalContext; 124 TestContext* fParent; 125 Test* fTest; 126 TestError* fErrors; 127 int32 fLevel; 128}; 129 130 131/*static*/ inline TestContext* 132TestContext::Current() 133{ 134 return GlobalTestContext::Current()->CurrentContext(); 135} 136 137 138int 139TestContext::PrintArgs(const char* format, va_list args) 140{ 141 return Output().PrintArgs(format, args); 142} 143 144 145int 146TestContext::Print(const char* format,...) 147{ 148 va_list args; 149 va_start(args, format); 150 int result = Output().PrintArgs(format, args); 151 va_end(args); 152 153 return result; 154} 155 156 157void 158TestContext::Error(const char* format,...) 159{ 160 va_list args; 161 va_start(args, format); 162 ErrorArgs(format, args); 163 va_end(args); 164} 165 166 167void 168TestContext::AssertFailed(const char* file, int line, const char* function, 169 const char* condition) 170{ 171 Error("ASSERT FAILED at %s:%d %s: %s\n", file, line, function, condition); 172} 173 174 175void 176TestContext::AssertFailed(const char* file, int line, const char* function, 177 const char* condition, const char* format,...) 178{ 179 char buffer[256]; 180 181 va_list args; 182 va_start(args, format); 183 vsnprintf(buffer, sizeof(buffer), format, args); 184 va_end(args); 185 186 Error("ASSERT FAILED at %s:%d %s: %s; %s\n", file, line, function, 187 condition, buffer); 188} 189 190 191#endif // TEST_CONTEXT_H 192