1 |
sf-pippijn |
1.1 |
#ifndef JSONTEST_H_INCLUDED |
2 |
|
|
#define JSONTEST_H_INCLUDED |
3 |
|
|
|
4 |
|
|
#include <deque> |
5 |
|
|
#include <stdio.h> |
6 |
|
|
#include <string> |
7 |
|
|
|
8 |
|
|
/* |
9 |
|
|
* ////////////////////////////////////////////////////////////////// |
10 |
|
|
* ////////////////////////////////////////////////////////////////// |
11 |
|
|
* Mini Unit Testing framework |
12 |
|
|
* ////////////////////////////////////////////////////////////////// |
13 |
|
|
* ////////////////////////////////////////////////////////////////// |
14 |
|
|
*/ |
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
|
|
/** \brief Unit testing framework. |
19 |
|
|
* \warning: all assertions are non-aborting, test case execution will continue |
20 |
|
|
* even if an assertion namespace. |
21 |
|
|
* This constraint is for portability: the framework needs to compile |
22 |
|
|
* on Visual Studio 6 and must not require exception usage. |
23 |
|
|
*/ |
24 |
|
|
namespace JsonTest |
25 |
|
|
{ |
26 |
|
|
struct Failure |
27 |
|
|
{ |
28 |
|
|
const char *file_; |
29 |
|
|
std::string expr_; |
30 |
|
|
std::string message_; |
31 |
|
|
unsigned int line_; |
32 |
|
|
unsigned int nestingLevel_; |
33 |
|
|
}; |
34 |
|
|
|
35 |
|
|
|
36 |
|
|
/* |
37 |
|
|
* / Context used to create the assertion callstack on failure. |
38 |
|
|
* / Must be a POD to allow inline initialisation without stepping |
39 |
|
|
* / into the debugger. |
40 |
|
|
*/ |
41 |
|
|
struct PredicateContext |
42 |
|
|
{ |
43 |
|
|
typedef size_t Id; |
44 |
|
|
Id id_; |
45 |
|
|
const char *file_; |
46 |
|
|
size_t line_; |
47 |
|
|
const char *expr_; |
48 |
|
|
PredicateContext *next_; |
49 |
|
|
/* |
50 |
|
|
* / Related Failure, set when the PredicateContext is converted |
51 |
|
|
* / into a Failure. |
52 |
|
|
*/ |
53 |
|
|
Failure *failure_; |
54 |
|
|
}; |
55 |
|
|
|
56 |
|
|
class TestResult |
57 |
|
|
{ |
58 |
|
|
public: |
59 |
|
|
TestResult (); |
60 |
|
|
|
61 |
|
|
/* |
62 |
|
|
* / \internal Implementation detail for assertion macros |
63 |
|
|
* / Not encapsulated to prevent step into when debugging failed assertions |
64 |
|
|
* / Incremented by one on assertion predicate entry, decreased by one |
65 |
|
|
* / by addPredicateContext(). |
66 |
|
|
*/ |
67 |
|
|
PredicateContext::Id predicateId_; |
68 |
|
|
|
69 |
|
|
/* / \internal Implementation detail for predicate macros */ |
70 |
|
|
PredicateContext *predicateStackTail_; |
71 |
|
|
|
72 |
|
|
void setTestName (const std::string &name); |
73 |
|
|
|
74 |
|
|
/* / Adds an assertion failure. */ |
75 |
|
|
TestResult &addFailure (const char *file, unsigned int line, const char *expr = 0); |
76 |
|
|
|
77 |
|
|
/* |
78 |
|
|
* / Removes the last PredicateContext added to the predicate stack |
79 |
|
|
* / chained list. |
80 |
|
|
* / Next messages will be targed at the PredicateContext that was removed. |
81 |
|
|
*/ |
82 |
|
|
TestResult &popPredicateContext (); |
83 |
|
|
|
84 |
|
|
bool failed () const; |
85 |
|
|
|
86 |
|
|
void printFailure (bool printTestName) const; |
87 |
|
|
|
88 |
|
|
TestResult &operator << (bool value); |
89 |
|
|
TestResult &operator << (int value); |
90 |
|
|
TestResult &operator << (unsigned int value); |
91 |
|
|
TestResult &operator << (double value); |
92 |
|
|
TestResult &operator << (const char *value); |
93 |
|
|
TestResult &operator << (const std::string &value); |
94 |
|
|
|
95 |
|
|
private: |
96 |
|
|
TestResult &addToLastFailure (const std::string &message); |
97 |
|
|
unsigned int getAssertionNestingLevel () const; |
98 |
|
|
/* / Adds a failure or a predicate context */ |
99 |
|
|
void addFailureInfo (const char *file, unsigned int line, const char *expr, unsigned int nestingLevel); |
100 |
|
|
static std::string indentText (const std::string &text, const std::string &indent); |
101 |
|
|
|
102 |
|
|
typedef std::deque<Failure> Failures; |
103 |
|
|
Failures failures_; |
104 |
|
|
std::string name_; |
105 |
|
|
PredicateContext rootPredicateNode_; |
106 |
|
|
PredicateContext::Id lastUsedPredicateId_; |
107 |
|
|
/* / Failure which is the target of the messages added using operator << */ |
108 |
|
|
Failure *messageTarget_; |
109 |
|
|
}; |
110 |
|
|
|
111 |
|
|
|
112 |
|
|
class TestCase |
113 |
|
|
{ |
114 |
|
|
public: |
115 |
|
|
TestCase (); |
116 |
|
|
|
117 |
|
|
virtual |
118 |
|
|
~TestCase (); |
119 |
|
|
|
120 |
|
|
void run (TestResult &result); |
121 |
|
|
|
122 |
|
|
virtual const char *testName () const = 0; |
123 |
|
|
|
124 |
|
|
protected: |
125 |
|
|
TestResult *result_; |
126 |
|
|
|
127 |
|
|
private: |
128 |
|
|
virtual void runTestCase () = 0; |
129 |
|
|
}; |
130 |
|
|
|
131 |
|
|
/* / Function pointer type for TestCase factory */ |
132 |
|
|
typedef TestCase *(*TestCaseFactory)(); |
133 |
|
|
|
134 |
|
|
class Runner |
135 |
|
|
{ |
136 |
|
|
public: |
137 |
|
|
Runner (); |
138 |
|
|
|
139 |
|
|
/* / Adds a test to the suite */ |
140 |
|
|
Runner &add (TestCaseFactory factory); |
141 |
|
|
|
142 |
|
|
/* |
143 |
|
|
* / Runs test as specified on the command-line |
144 |
|
|
* / If no command-line arguments are provided, run all tests. |
145 |
|
|
* / If --list-tests is provided, then print the list of all test cases |
146 |
|
|
* / If --test <testname> is provided, then run test testname. |
147 |
|
|
*/ |
148 |
|
|
int runCommandLine (int argc, const char *argv[]) const; |
149 |
|
|
|
150 |
|
|
/* / Runs all the test cases */ |
151 |
|
|
bool runAllTest (bool printSummary) const; |
152 |
|
|
|
153 |
|
|
/* / Returns the number of test case in the suite */ |
154 |
|
|
unsigned int testCount () const; |
155 |
|
|
|
156 |
|
|
/* / Returns the name of the test case at the specified index */ |
157 |
|
|
std::string testNameAt (unsigned int index) const; |
158 |
|
|
|
159 |
|
|
/* / Runs the test case at the specified index using the specified TestResult */ |
160 |
|
|
void runTestAt (unsigned int index, TestResult &result) const; |
161 |
|
|
|
162 |
|
|
static void printUsage (const char *appName); |
163 |
|
|
|
164 |
|
|
private: |
165 |
|
|
/* prevents copy construction and assignment */ |
166 |
|
|
Runner (const Runner &other); |
167 |
|
|
Runner &operator = (const Runner &other); |
168 |
|
|
|
169 |
|
|
private: |
170 |
|
|
void listTests () const; |
171 |
|
|
bool testIndex (const std::string &testName, unsigned int &index) const; |
172 |
|
|
static void preventDialogOnCrash (); |
173 |
|
|
|
174 |
|
|
private: |
175 |
|
|
typedef std::deque<TestCaseFactory> Factories; |
176 |
|
|
Factories tests_; |
177 |
|
|
}; |
178 |
|
|
|
179 |
|
|
template<typename T> |
180 |
|
|
TestResult & |
181 |
|
|
checkEqual (TestResult &result, const T &expected, const T &actual, const char *file, unsigned int line, const char *expr) |
182 |
|
|
{ |
183 |
|
|
if (expected != actual) |
184 |
|
|
{ |
185 |
|
|
result.addFailure (file, line, expr); |
186 |
|
|
result << "Expected: " << expected << "\n"; |
187 |
|
|
result << "Actual : " << actual; |
188 |
|
|
} |
189 |
|
|
return result; |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
TestResult &checkStringEqual (TestResult &result, const std::string &expected, const std::string &actual, const char *file, unsigned int line, const char *expr); |
193 |
|
|
} /* namespace JsonTest */ |
194 |
|
|
|
195 |
|
|
|
196 |
|
|
/* |
197 |
|
|
* / \brief Asserts that the given expression is true. |
198 |
|
|
* / JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; |
199 |
|
|
* / JSONTEST_ASSERT( x == y ); |
200 |
|
|
*/ |
201 |
|
|
#define JSONTEST_ASSERT(expr) \ |
202 |
|
|
if (condition) \ |
203 |
|
|
{ \ |
204 |
|
|
} \ |
205 |
|
|
else \ |
206 |
|
|
result_->addFailure (__FILE__, __LINE__, # expr) |
207 |
|
|
|
208 |
|
|
/* |
209 |
|
|
* / \brief Asserts that the given predicate is true. |
210 |
|
|
* / The predicate may do other assertions and be a member function of the fixture. |
211 |
|
|
*/ |
212 |
|
|
#define JSONTEST_ASSERT_PRED(expr) \ |
213 |
|
|
{ \ |
214 |
|
|
JsonTest::PredicateContext _minitest_Context = { \ |
215 |
|
|
result_->predicateId_, __FILE__, __LINE__, # expr }; \ |
216 |
|
|
result_->predicateStackTail_->next_ = &_minitest_Context; \ |
217 |
|
|
result_->predicateId_ += 1; \ |
218 |
|
|
result_->predicateStackTail_ = &_minitest_Context; \ |
219 |
|
|
(expr); \ |
220 |
|
|
result_->popPredicateContext (); \ |
221 |
|
|
} \ |
222 |
|
|
*result_ |
223 |
|
|
|
224 |
|
|
/* / \brief Asserts that two values are equals. */ |
225 |
|
|
#define JSONTEST_ASSERT_EQUAL(expected, actual) \ |
226 |
|
|
JsonTest::checkEqual (*result_, expected, actual, \ |
227 |
|
|
__FILE__, __LINE__, \ |
228 |
|
|
# expected " == " # actual) |
229 |
|
|
|
230 |
|
|
/* / \brief Asserts that two values are equals. */ |
231 |
|
|
#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \ |
232 |
|
|
JsonTest::checkStringEqual (*result_, \ |
233 |
|
|
std::string (expected), std::string (actual), \ |
234 |
|
|
# expected " == " # actual) |
235 |
|
|
|
236 |
|
|
/* / \brief Begin a fixture test case. */ |
237 |
|
|
#define JSONTEST_FIXTURE(FixtureType, name) \ |
238 |
|
|
class Test ## FixtureType ## name \ |
239 |
|
|
: public FixtureType \ |
240 |
|
|
{ \ |
241 |
|
|
public: \ |
242 |
|
|
static JsonTest::TestCase *factory () \ |
243 |
|
|
{ \ |
244 |
|
|
return new Test ## FixtureType ## name (); \ |
245 |
|
|
} \ |
246 |
|
|
public: \ |
247 |
|
|
/* overidden from TestCase */ \ |
248 |
|
|
virtual const char *testName () const \ |
249 |
|
|
{ \ |
250 |
|
|
return # FixtureType "/" # name; \ |
251 |
|
|
} \ |
252 |
|
|
virtual void runTestCase (); \ |
253 |
|
|
}; \ |
254 |
|
|
\ |
255 |
|
|
void Test ## FixtureType ## name::runTestCase () |
256 |
|
|
|
257 |
|
|
#define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \ |
258 |
|
|
& Test ## FixtureType ## name::factory |
259 |
|
|
|
260 |
|
|
#define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \ |
261 |
|
|
(runner).add (JSONTEST_FIXTURE_FACTORY (FixtureType, name)) |
262 |
|
|
|
263 |
|
|
#endif /* ifndef JSONTEST_H_INCLUDED */ |