1#ifndef PyObjC_UNITTEST_H
2#define PyObjC_UNITTEST_H
3/*!
4 * @header pyobjc-unittest.h
5 * @abstract Defining C-based unittests
6 * @discussion
7 *
8 * This file defines a very simple unittest framework for the Objective-C
9 * modules of PyObjC.
10 *
11 * It is intended to be used with PyUnit, see objc.test.test_ctests for more
12 * information on that.
13 *
14 * Usage:
15 * <PRE>
16 * BEGIN_UNITEST(IntSize)
17 *     // This is a normal C block, starting with variable definitions
18 *     int i = 3;
19 *
20 *     ASSERT_EQUALS(sizeof(int), sizeof(i), "%d");
21 *
22 * END_UNITTEST
23 * </PRE>
24 *
25 * And in the PyMethodDef list for the module:
26 * <PRE>
27 *     TESTDEF(IntSize),
28 * </PRE>
29 *
30 * Use 'FAIL_IF' to abort a test due to a Python exception.
31 */
32
33#include <stdarg.h>
34
35#define BEGIN_UNITTEST(name) \
36	static PyObject* \
37	test_##name (PyObject* self __attribute__((__unused__))) \
38 	{  \
39
40#define END_UNITTEST \
41		Py_INCREF(Py_None); \
42		return Py_None; \
43	error: 			\
44		return NULL;	\
45	}
46
47#define FAIL_IF(expr) do { if ((expr)) goto error; } while(0)
48
49static inline void
50unittest_assert_failed(const char* file, int line, char* msg, ...)
51{
52	char buf[10240];
53	va_list ap;
54
55	va_start(ap, msg);
56	vsnprintf(buf, sizeof(buf), msg, ap);
57	va_end(ap);
58	PyErr_Format(PyExc_AssertionError, "%s:%d %s", file, line, buf);
59}
60
61#define ASSERT(expr) \
62	do { \
63		if (!(expr)) { \
64			unittest_assert_failed(__FILE__, __LINE__,"%s",#expr); \
65			goto error; \
66		} \
67	} while (0)
68
69#define ASSERT_EQUALS(val1, val2, fmt) \
70	do { \
71		if ((val1) != (val2)) { \
72			unittest_assert_failed(__FILE__, __LINE__, \
73					fmt " != " fmt, (val1), (val2)); \
74			goto error; \
75		} \
76	} while (0)
77
78#define ASSERT_STREQUALS(val1, val2) \
79	do { \
80		const char* _val1 = (val1); \
81		const char* _val2 = (val2); \
82		\
83		if (strcmp(_val1, _val2) != 0) { \
84			unittest_assert_failed(__FILE__, __LINE__, \
85					 "%s != %s", (_val1), (_val2)); \
86			goto error; \
87		} \
88	} while (0)
89
90#define ASSERT_ISINSTANCE(val, type) \
91	do { \
92		if (!Py##type##_Check((val))) { \
93			unittest_assert_failed(__FILE__, __LINE__, \
94				"type of value is %s not %s", \
95				(val)->ob_type->tp_name, \
96				Py##type##_Type.tp_name); \
97			goto error; \
98		} \
99	} while (0)
100
101
102#define TESTDEF(name) \
103	{ \
104		#name, \
105		(PyCFunction)test_##name,  \
106		METH_NOARGS,  \
107		NULL \
108	}
109
110#endif /* PyObjC_UNITTEST_H */
111