xref: /haiku/src/tests/system/kernel/unit/TestContext.h (revision 933764d70e74117ea1e4a3cc19184b40a6aa44d1)
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 
OutputGlobalTestContext38 			TestOutput&			Output() const	{ return fOutput; }
OptionsGlobalTestContext39 			TestOptions&		Options() const	{ return fOptions; }
40 
CurrentContextGlobalTestContext41 			TestContext*		CurrentContext() const
42 									{ return fCurrentContext; }
43 			void				SetCurrentContext(TestContext* context);
44 
TotalTestsGlobalTestContext45 			int32				TotalTests() const	{ return fTotalTests; }
FailedTestsGlobalTestContext46 			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 
ThreadEntryGlobalTestContext::ThreadEntry61 				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 
GlobalContext()98 			GlobalTestContext*	GlobalContext() const { return fGlobalContext; }
Parent()99 			TestContext*		Parent() const	{ return fParent; }
Level()100 			int32				Level() const	{ return fLevel; }
Output()101 			TestOutput&			Output() const
102 									{ return fGlobalContext->Output(); }
Options()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*
Current()132 TestContext::Current()
133 {
134 	return GlobalTestContext::Current()->CurrentContext();
135 }
136 
137 
138 int
PrintArgs(const char * format,va_list args)139 TestContext::PrintArgs(const char* format, va_list args)
140 {
141 	return Output().PrintArgs(format, args);
142 }
143 
144 
145 int
Print(const char * format,...)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
Error(const char * format,...)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
AssertFailed(const char * file,int line,const char * function,const char * condition)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
AssertFailed(const char * file,int line,const char * function,const char * condition,const char * format,...)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