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 17 class Test; 18 class TestContext; 19 class TestError; 20 21 22 struct TestOptions { 23 bool panicOnFailure; 24 bool quitAfterFailure; 25 26 public: 27 TestOptions(); 28 }; 29 30 31 struct 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 54 private: 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 73 private: 74 static void _SetCurrent(ThreadEntry* entry); 75 static void _UnsetCurrent(ThreadEntry* entry); 76 static status_t _ThreadEntry(void* data); 77 78 private: 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 90 class TestContext { 91 public: 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 122 private: 123 GlobalTestContext* fGlobalContext; 124 TestContext* fParent; 125 Test* fTest; 126 TestError* fErrors; 127 int32 fLevel; 128 }; 129 130 131 /*static*/ inline TestContext* 132 TestContext::Current() 133 { 134 return GlobalTestContext::Current()->CurrentContext(); 135 } 136 137 138 int 139 TestContext::PrintArgs(const char* format, va_list args) 140 { 141 return Output().PrintArgs(format, args); 142 } 143 144 145 int 146 TestContext::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 157 void 158 TestContext::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 167 void 168 TestContext::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 175 void 176 TestContext::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