ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/dclient/testsuite/json/jsontest.h
Revision: 1.1
Committed: Sun Oct 17 08:15:15 2010 UTC (13 years, 8 months ago) by sf-pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Log Message:
initial import

File Contents

# Content
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 */