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