1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 /**@file sofia-sip/tstdef.h Macros for unit tests
26  *
27  * The macros defined here can be used by unit test programs. When a test
28  * fails, the TEST macros print the offending file name and line number.
29  * They use format that is accepted by Emacs and other fine editors so you
30  * can directly go to the source code of the failed test with next-error.
31  *
32  * @note There is no protection agains multiple inclusion.
33  *
34  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
35  *
36  * @date Created: Wed Aug 22 13:53:24 2001 ppessi
37  *
38  * @par Example Program
39  *
40  * You should define the macro TSTFLAGS to a int variable possibly
41  * containing a flag #tst_verbatim. As a convention, the int variable should
42  * be set when your test program is run with @c -v or @c --verbatim command
43  * line option. If the (TSTFLAGS & tst_verbatim) is true, the test macros
44  * log the test before executing it and the result of successful tests, too.
45  *
46  * You should typedef longlong to integer type at least 64 bit wide before
47  * including <sofia-sip/tstdef.h>, too.
48  *
49  * As an example, we provide a test program making sure that inet_ntop() and
50  * inet_pton() behave as expected and that we can create UDP/IPv4 sockets
51  * with @b su library:
52  *
53  * @code
54  * #include "config.h"
55  *
56  * #include <stdio.h>
57  * #include <limits.h>
58  *
59  * #include <sofia-sip/su.h>
60  *
61  * #define TSTFLAGS tstflags
62  *
63  * #include <stdlib.h>
64  * #include <sofia-sip/tstdef.h>
65  *
66  * static int tstflags = 0;
67  *
68  * void usage(void)
69  * {
70  *   fprintf(stderr, "usage: %s [-v|--verbatim]\n", name);
71  *   exit(2);
72  * }
73  *
74  * static int socket_test(void);
75  *
76  * int main(int argc, char *argv[])
77  * {
78  *   int retval = 0, i;
79  *
80  *   for (i = 1; argv[i]; i++) {
81  *     if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbatim") == 0)
82  *       tstflags |= tst_verbatim;
83  *     else
84  *       usage();
85  *   }
86  *
87  *   retval |= socket_test(); fflush(stdout);
88  *
89  *   return retval;
90  * }
91  *
92  * double max_bandwidth()
93  *
94  * int socket_test(void)
95  * {
96  *   su_socket_t s;
97  *   char buf[64];
98  *   unsigned long localhost = htonl(0x7f000001);
99  *   unsigned long addr;
100  *
101  *   BEGIN();
102  *
103  *   // Check inet_ntop() return value (Tests equality of integral values)
104  *   TEST(inet_ntop(AF_INET, &localhost, buf, sizeof buf), buf);
105  *
106  *   // Check inet_ntop() result (Tests equality of strings)
107  *   TEST_S(buf, "127.0.0.1");
108  *
109  *   // Check inet_pton() argument validation (Tests equality of ints)
110  *   TEST(inet_pton(0, buf, &addr), -1);
111  *
112  *   // Check inet_pton() return value (Tests for true value (non-zero))
113  *   TEST_1(inet_pton(AF_INET, buf, &addr) > 0);
114  *
115  *   // Check inet_pton() result (Tests equality of memory areas)
116  *   TEST_M(&addr, &localhost, sizeof(addr));
117  *
118  *   // Test to create UDP socket (Test for true value)
119  *   TEST_1((s = su_socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET);
120  *
121  *   // Check max bandwidth
122  *   TEST_D(max_bandwidth(), DBL_MAX);
123  *
124  *   END();
125  * }
126  * @endcode
127  */
128 
129 #ifndef SU_TYPES_H
130 #include <sofia-sip/su_types.h>
131 #endif
132 
133 SOFIA_BEGIN_DECLS
134 
135 #if HAVE_FUNC
136 #define TSTNAME name, __func__, "() "
137 #elif HAVE_FUNCTION
138 #define TSTNAME name, __FUNCTION__, "() "
139 #else
140 #define TSTNAME name, "", ""
141 #endif
142 
143 enum {
144   /** If (TSTFLAGS & tst_verbatim) is non-zero, be verbatim. */
145   tst_verbatim = 1,
146   /** If (TSTFLAGS & tst_abort) is non-zero, abort() when failed. */
147   tst_abort = 2,
148   /** If (TSTFLAGS & tst_log) is non-zero, log intermediate results. */
149   tst_log = 4
150 };
151 
152 #ifndef TSTFLAGS
153 #error <TSTFLAGS is not defined>
154 #endif
155 
156 /** Begin a test function. @HIDE */
157 #define BEGIN() BEGIN_(TSTFLAGS); { extern int tstdef_dummy
158 /** End a test function. @HIDE */
159 #define END() (void) tstdef_dummy; } END_(TSTFLAGS)
160 /**Test that @a suite returns a nonzero value.
161  * @deprecated Use TEST_1()
162  * @HIDE */
163 #define TEST0(suite) TEST_1_(TSTFLAGS, suite)
164 /** Test that @a suite returns a nonzero value. @HIDE */
165 #define TEST_1(suite) TEST_1_(TSTFLAGS, suite)
166 /** Test a void suite. @HIDE */
167 #define TEST_VOID(suite) TEST_VOID_(TSTFLAGS, suite)
168 /** Test that @a suite is equal to @a expected. @HIDE */
169 #define TEST(suite, expected) TEST_(TSTFLAGS, suite, expected)
170 /** Test that @a suite is same pointer as @a expected. @HIDE */
171 #define TEST_P(suite, expected) TEST_P_(TSTFLAGS, suite, expected)
172 /** Test that 64-bit @a suite is equal to @a expect. @HIDE */
173 #define TEST64(suite, expected) TEST64_(TSTFLAGS, suite, expected)
174 /** Test that @a suite is same double as @a expected. @HIDE */
175 #define TEST_D(suite, expected) TEST_D_(TSTFLAGS, suite, expected)
176 /** Test that @a suite is same string as @a expected. @HIDE */
177 #define TEST_S(suite, expected) TEST_S_(TSTFLAGS, suite, expected)
178 /** Test that @a suite is results as identical memory as @a expected. @HIDE */
179 #define TEST_M(suite, expected, len) TEST_M_(TSTFLAGS, suite, expected, len)
180 /** Test that @a suite has same size as @a expected. @HIDE */
181 #define TEST_SIZE(suite, expected) TEST_SIZE_(TSTFLAGS, suite, expected)
182 
183 /** Print in torture test with -l option */
184 #define TEST_LOG(x)		       \
185   do {				       \
186     if (tstflags & tst_log)	       \
187       printf x;			       \
188   } while(0)
189 
190 #define TEST_FAILED(flags) \
191   ((flags) & tst_abort) ? abort() : (void)0; return 1
192 
193 /** @HIDE */
194 #define TEST_1_(flags, suite) do { \
195   if (flags & tst_verbatim) { \
196     printf("%s: %s%stesting %s\n", TSTNAME, #suite); \
197     fflush(stdout); } \
198   if ((suite)) { if (flags & tst_verbatim) \
199   printf("%s: %s%sok: (%s)\n", TSTNAME, #suite); break ; } \
200   fprintf(stderr, "%s:%u: %s %s%sFAILED: (%s)\n", \
201           __FILE__, __LINE__, TSTNAME, #suite); fflush(stderr); \
202   TEST_FAILED(flags); }						\
203   while(0)
204 
205 /** @HIDE */
206 #define TEST_VOID_(flags, suite) do { \
207   if (flags & tst_verbatim) { \
208     printf("%s: %s%stesting %s\n", TSTNAME, #suite); \
209     fflush(stdout); } \
210   (suite); } while(0)
211 
212 /** @HIDE */
213 #define TEST_(flags, suite, expect) do {				\
214     uintptr_t _value, _expect;						\
215     if (flags & tst_verbatim) {						\
216       printf("%s: %s%stesting %s == %s\n", TSTNAME, #suite, #expect);	\
217       fflush(stdout); }							\
218     _value = (uintptr_t)(suite);					\
219     _expect = (uintptr_t)(expect);					\
220     if (_value == _expect) {						\
221       if (flags & tst_verbatim)						\
222 	printf("%s: %s%sok: %s == %s \n",				\
223 	       TSTNAME, #suite, #expect);				\
224       break;								\
225     }									\
226     fprintf(stderr, "%s:%u: %s %s%sFAILED: "				\
227 	    "%s != %s or "MOD_ZU" != "MOD_ZU"\n",			\
228 	    __FILE__, __LINE__, TSTNAME,				\
229 	    #suite, #expect, (size_t)_value, (size_t)_expect);		\
230     fflush(stderr);							\
231     TEST_FAILED(flags);							\
232   } while(0)
233 
234 /** @HIDE */
235 #define TEST_P_(flags, suite, expect) do {				\
236     void const * _value, * _expect;					\
237   if (flags & tst_verbatim) {						\
238     printf("%s: %s%stesting %s == %s\n", TSTNAME, #suite, #expect);	\
239     fflush(stdout); }							\
240   if ((_value = (suite)) == (_expect = (expect))) {			\
241     if (flags & tst_verbatim)						\
242       printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect);	\
243     break;								\
244   }									\
245   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s or %p != %p\n",	\
246 	  __FILE__, __LINE__, TSTNAME,					\
247 	  #suite, #expect, _value, _expect); fflush(stderr);		\
248   TEST_FAILED(flags);							\
249   } while(0)
250 
251 /** @HIDE */
252 #define TEST_SIZE_(flags, suite, expect) do {	\
253   size_t _value, _expect; \
254   if (flags & tst_verbatim) { \
255     printf("%s: %s%stesting %s == %s\n", TSTNAME, #suite, #expect); \
256     fflush(stdout); } \
257   if ((_value = (size_t)(suite)) == \
258       (_expect = (size_t)(expect))) \
259   { if (flags & tst_verbatim) \
260   printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect); break; } \
261   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s or "MOD_ZU" != "MOD_ZU"\n", \
262 	 __FILE__, __LINE__, TSTNAME, \
263 	  #suite, #expect, _value, _expect); fflush(stderr);		\
264   TEST_FAILED(flags);							\
265   } while(0)
266 
267 
268 /** @HIDE */
269 #define TEST64_(flags, suite, expect) do { \
270   uint64_t _value, _expect; \
271   if (flags & tst_verbatim) { \
272     printf("%s: %s%stesting %s == %s\n", TSTNAME, #suite, #expect); \
273     fflush(stdout); } \
274   if ((_value = (uint64_t)(suite)) == (_expect = (uint64_t)(expect))) \
275   { if (flags & tst_verbatim) \
276   printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect); break; } \
277   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s or "LLU" != "LLU"\n", \
278 	 __FILE__, __LINE__, TSTNAME, \
279 	  #suite, #expect, (unsigned longlong)_value,	\
280 	 (unsigned longlong)_expect); fflush(stderr);	\
281   TEST_FAILED(flags);					\
282   } while(0)
283 
284 /** @HIDE */
285 #define TEST_D_(flags, suite, expect) do { \
286   double _value, _expect; \
287   if (flags & tst_verbatim) { \
288     printf("%s: %s%stesting %s == %s\n", TSTNAME, #suite, #expect); \
289     fflush(stdout); } \
290   if ((_value = (double)(suite)) == (_expect = (double)(expect))) \
291   { if (flags & tst_verbatim) \
292   printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect); break; } \
293   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s or %g != %g\n", \
294 	 __FILE__, __LINE__, TSTNAME, \
295          #suite, #expect, _value, _expect); fflush(stderr); \
296   TEST_FAILED(flags);					    \
297   } while(0)
298 
299 /** @HIDE */
300 #define TEST_S_(flags, suite, expect) do { \
301   char const * _value, * _expect; \
302   if (flags & tst_verbatim) { \
303     printf("%s: %s%stesting %s is %s\n", TSTNAME, #suite, #expect); \
304     fflush(stdout); } \
305   _value = (suite); \
306   _expect = (expect); \
307   if (((_value == NULL || _expect == NULL) && _value == _expect) || \
308       (_value != NULL && _expect != NULL && strcmp(_value, _expect) == 0)) \
309   { if (flags & tst_verbatim) \
310   printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect);break;}\
311   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s or %s%s%s != \"%s\"\n", \
312 	 __FILE__, __LINE__, TSTNAME, \
313 	  #suite, #expect, \
314 	  _value ? "\"" : "", _value ? _value : "NULL", _value ? "\"" : "", \
315 	  _expect); fflush(stderr);					\
316   TEST_FAILED(flags);							\
317   } while(0)
318 
319 /** @HIDE */
320 #define TEST_M_(flags, suite, expect, len) do { \
321   void const * _value, * _expect; \
322   size_t _len; \
323   if (flags & tst_verbatim) { \
324     printf("%s: %s%stesting %s is %s\n", TSTNAME, #suite, #expect); \
325     fflush(stdout); } \
326   _value = (suite); \
327   _expect = (expect); \
328   _len = (size_t)(len); \
329   if (((_value == NULL || _expect == NULL) && _value == _expect) || \
330       memcmp(_value, _expect, _len) == 0) \
331   { if (flags & tst_verbatim) \
332   printf("%s: %s%sok: %s == %s \n", TSTNAME, #suite, #expect);break;}\
333   fprintf(stderr, "%s:%u: %s %s%sFAILED: %s != %s "\
334                   "or \"%.*s\" != \"%.*s\"\n", \
335 	 __FILE__, __LINE__, TSTNAME, \
336 	  #suite, #expect, (int)_len, \
337           (char *)_value, (int)_len, (char *)_expect); \
338   fflush(stderr);							\
339   TEST_FAILED(flags);							\
340   } while(0)
341 
342 /** @HIDE */
343 #define BEGIN_(flags) \
344   if (flags & tst_verbatim) printf("%s: %s%sstarting\n", TSTNAME)
345 
346 /** @HIDE */
347 #define END_(flags) \
348   if (flags & tst_verbatim) \
349     printf("%s: %s%sfinished fully successful\n", TSTNAME); \
350   return 0
351 
352 SOFIA_END_DECLS
353