1//
2// MuleUnit: A minimalistic C++ Unit testing framework based on EasyUnit.
3//
4// Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5// Copyright (c) 2004-2011 Barthelemy Dagenais ( barthelemy@prologique.com )
6//
7// This library is free software; you can redistribute it and/or
8// modify it under the terms of the GNU Lesser General Public
9// License as published by the Free Software Foundation; either
10// version 2.1 of the License, or (at your option) any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15// Lesser General Public License for more details.
16//
17// You should have received a copy of the GNU Lesser General Public
18// License along with this library; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
20//
21
22#ifndef TEST_H
23#define TEST_H
24
25#include <exception>
26
27#include <wx/string.h>
28#include <list>
29#include <string>
30
31
32/**
33 * MuleUnit namespace.
34 * This is the namespace containing all muleunit classes.
35 */
36namespace muleunit
37{
38
39class TestCase;
40class BTList;
41
42
43/** Returns the size of a static array. */
44template <typename T, size_t N>
45inline size_t ArraySize(T(&)[N])
46{
47	return N;
48}
49
50
51/** Print wide-char strings. */
52inline void Print(const wxString& str)
53{
54	wxPuts(str.c_str());
55}
56
57
58/** This exception is raised if an ASSERT fails. */
59struct CTestFailureException : public std::exception
60{
61	/** Constructor, takes a snapshot of the current context, and adds the given information. */
62	CTestFailureException(const wxString& msg, const wxChar* file, long lineNumber);
63
64	~CTestFailureException() throw();
65
66	/** Prints the context backtrace for the location where the exception was thrown. */
67	void PrintBT() const;
68
69	virtual const char* what () const throw ();
70private:
71	//! Pointer to struct containing a snapshot of the contexts
72	//! taken at the time the exception was created.
73	struct BTList* m_bt;
74
75	//! The message passed in the constructor.
76	std::string m_message;
77};
78
79/** This exception is raised if an wxASSERT fails. */
80struct CAssertFailureException : public CTestFailureException
81{
82public:
83	CAssertFailureException(const wxString& msg, const wxChar* file, long lineNumber)
84		: CTestFailureException(msg, file, lineNumber)
85	{
86	}
87};
88
89
90/**
91 * This class is used to produce informative backtraces
92 *
93 * This is done by specifying a "context" for a given scope, using
94 * the CONTEXT macro, at which point a description is added to the
95 * current list of contexts. At destruction, when the scope is exited,
96 * the context is removed from the queue.
97 *
98 * The resulting "backtrace" can then be printed by calling the
99 * PrintBT() function of an CTestFailureException.
100 */
101class CContext
102{
103public:
104	/** Adds a context with the specified information and description. */
105	CContext(const wxChar* file, int line, const wxString& desc);
106
107	/** Removes the context addded by the constructor. */
108	~CContext();
109};
110
111
112//! Used to join the CContext instance name with the line-number.
113//! This is done to prevent shadowing.
114#define DO_CONTEXT(x, y, z) x y##z
115
116//! Specifies the context of the current scope.
117#define CONTEXT(x) CContext wxCONCAT(context,__LINE__)(wxT(__FILE__), __LINE__, x)
118
119
120/**
121 * This class disables assertions while it is in scope.
122 */
123class CAssertOff
124{
125public:
126	CAssertOff();
127	~CAssertOff();
128};
129
130
131/**
132 * Test class containing all macros to do unit testing.
133 * A test object represents a test that will be executed. Once it has been
134 * executed, it reports all failures in the testPartResult linked list.
135 *
136 * A failure occurs when a test fails (condition is false).
137 */
138class Test
139{
140public:
141	/**
142	 * Main Test constructor. Used to create a test that will register itself
143	 * with TestRegistry and with its test case.
144	 * @param testCaseName Name of the test case this test belongs to
145	 * @param testName Name of this test
146	 */
147	Test(const wxString& testCaseName, const wxString& testName);
148
149	/**
150	 * Main Test desctructor
151	 * Delete the testPartResult linked list. This is why the user should
152	 * only use the macro provided by muleunit to report a test result.
153	 */
154	virtual ~Test();
155
156	/**
157	 * Fixtures that will be called after run().
158	 */
159	virtual void tearDown();
160
161	/**
162	 * Fixtures that will be called before run().
163	 */
164	virtual void setUp();
165
166	/**
167	 * Test code should be in this method.
168	 * run() will be called by the Test's TestCase, hence subclasses of Test
169	 * should override this method.
170	 */
171	virtual void run();
172
173	/**
174	 * Get the name of the TestCase this test belongs to. The name of the
175	 * TestCase is the first parameter of the test declaration. For example,
176	 * if a test is declared as TEST(TESTCASE1, TEST1), this method will return
177	 * "TESTCASE1".
178	 *
179	 * @return The TestCase name of this test
180	 */
181	const wxString& getTestCaseName() const;
182
183	/**
184	 * Get the name of this test. The name of the test is the second
185	 * parameter of the test declaration. For example,
186	 * if a test is declared as TEST(TESTCASE1, TEST1), this method will return
187	 * "TEST1".
188	 *
189	 * @return The name of this test.
190	 */
191	const wxString& getTestName() const;
192
193	template <typename A, typename B>
194	static void DoAssertEquals(const wxString& file, unsigned line, const A& a, const B& b)
195	{
196		if (!(a == b)) {
197			wxString message = wxT("Expected '") + StringFrom(a) +
198								wxT("' but got '") + StringFrom(b) + wxT("'");
199
200			throw CTestFailureException(message, file, line);
201		}
202	}
203
204protected:
205	wxString m_testCaseName;
206	wxString m_testName;
207	TestCase* m_testCase;
208};
209
210
211/**
212 * Helperfunction that converts basic types to strings.
213 */
214template <typename TYPE>
215wxString StringFrom(const TYPE& value)
216{
217	return wxString() << value;
218}
219
220inline wxString StringFrom(unsigned long long value)
221{
222	return wxString::Format(wxT("%") wxLongLongFmtSpec wxT("u"), value);
223}
224
225inline wxString StringFrom(signed long long value)
226{
227	return wxString::Format(wxT("%") wxLongLongFmtSpec wxT("i"), value);
228}
229
230
231#define THROW_TEST_FAILURE(message) \
232	throw CTestFailureException(message, wxT(__FILE__), __LINE__)
233
234
235/**
236 * Asserts that a condition is true.
237 * If the condition is not true, a failure is generated.
238 * @param condition Condition to fullfill for the assertion to pass
239 * @param message Message that will be displayed if this assertion fails
240 */
241#define ASSERT_TRUE_M(condition, message) \
242{ \
243	if (!(condition)) { \
244		THROW_TEST_FAILURE(message); \
245	} \
246}
247
248
249/**
250 * Same as ASSERT_TRUE, but without an explicit message.
251 */
252#define ASSERT_TRUE(condition) \
253	ASSERT_TRUE_M(condition, wxString(wxT("Not true: ")) + wxT(#condition));
254
255
256/**
257 * Same as ASSERT_TRUE, but without an explicit message and condition must be false.
258 */
259#define ASSERT_FALSE(condition) \
260	ASSERT_TRUE_M(!(condition), wxString(wxT("Not false: ")) + wxT(#condition));
261
262
263/**
264 * Asserts that the two parameters are equals. Operator == must be defined.
265 * If the two parameters are not equals, a failure is generated.
266 * @param expected Expected value
267 * @param actual Actual value to be compared
268 * @param message Message that will be displayed if this assertion fails
269 */
270#define ASSERT_EQUALS_M(expected,actual,message)\
271{ \
272	if (!(expected == actual)) { \
273		THROW_TEST_FAILURE(message); \
274	} \
275}
276
277
278/**
279 * Same as ASSERT_EQUALS_M, but without an explicit message.
280 */
281#define ASSERT_EQUALS(expected, actual) \
282	Test::DoAssertEquals(wxT(__FILE__), __LINE__, expected, actual)
283
284
285/**
286 * Make a test fails with the given message.
287 * @param text Failure message
288 */
289#define FAIL_M(text) \
290	THROW_TEST_FAILURE(text)
291
292/**
293 * Same as FAIL_M, but without an explicit message.
294 */
295#define FAIL() FAIL_M(wxT("Test failed."))
296
297
298/**
299 * Requires that an exception of a certain type is raised.
300 */
301#define ASSERT_RAISES_M(type, call, message) \
302	try { \
303		{ call; }\
304		THROW_TEST_FAILURE(message); \
305	} catch (const type&) { \
306	} catch (const std::exception& e) { \
307		THROW_TEST_FAILURE(wxString::FromAscii(e.what())); \
308	}
309
310
311
312/**
313 * Same as ASSERT_RAISES, but without an explicit message.
314 */
315#define ASSERT_RAISES(type, call) \
316	ASSERT_RAISES_M(type, (call), wxT("Exception of type ") wxT(#type) wxT(" not raised."))
317
318
319
320/**
321 * Define a test in a TestCase using test fixtures.
322 * User should put his test code between brackets after using this macro.
323 *
324 * This macro should only be used if test fixtures were declared earlier in
325 * this order: DECLARE, SETUP, TEARDOWN.
326 * @param testCaseName TestCase name where the test belongs to. Should be
327 * the same name of DECLARE, SETUP and TEARDOWN.
328 * @param testName Unique test name.
329 * @param testDisplayName This will be displayed when running the test.
330 */
331#define TEST_M(testCaseName, testName, testDisplayName)                        \
332    class testCaseName##testName##Test : public testCaseName##Declare##Test    \
333    {                                                                          \
334    public:                                                                    \
335        testCaseName##testName##Test()                                         \
336            : testCaseName##Declare##Test(wxT(#testCaseName), testDisplayName) \
337        {                                                                      \
338        }                                                                      \
339                                                                               \
340        void run();                                                            \
341    } testCaseName##testName##Instance;                                        \
342                                                                               \
343    void testCaseName##testName##Test::run()
344
345/**
346 * Define a test in a TestCase using test fixtures.
347 * User should put his test code between brackets after using this macro.
348 *
349 * This macro should only be used if test fixtures were declared earlier in
350 * this order: DECLARE, SETUP, TEARDOWN.
351 * @param testCaseName TestCase name where the test belongs to. Should be
352 * the same name of DECLARE, SETUP and TEARDOWN.
353 * @param testName Unique test name.
354 */
355#define TEST(testCaseName, testName)	TEST_M(testCaseName, testName, wxT(#testName))
356
357/**
358 * Location to declare variables and objets.
359 * This is where user should declare members accessible by TESTF,
360 * SETUP and TEARDOWN.
361 *
362 * User should not use brackets after using this macro. User should
363 * not initialize any members here.
364 *
365 * @param testCaseName TestCase name of the fixtures
366 * @see END_DECLARE for more information.
367 */
368#define DECLARE(testCaseName)\
369	class testCaseName##Declare##Test : public Test \
370	{ \
371	public: \
372		testCaseName##Declare##Test(const wxString& testCaseName, const wxString& testName) \
373			: Test (testCaseName, testName) {} \
374		virtual void run() = 0; \
375
376/**
377 * Ending macro used after DECLARE.
378 *
379 * User should use this macro after declaring members with
380 * DECLARE macro.
381 */
382#define END_DECLARE };
383
384
385/**
386 * Macro for creating a fixture with no setup/teardown or member variables.
387 */
388#define DECLARE_SIMPLE(testCaseName) \
389	DECLARE(testCaseName) \
390	END_DECLARE;
391
392} // MuleUnit ns
393#endif // TEST_H
394
395