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 /**@CFILE test_nua.c
26 * @brief High-level tester for Sofia SIP User Agent Engine
27 *
28 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
29 * @author Martti Mela <Martti Mela@nokia.com>
30 *
31 * @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
32 */
33
34 #include "config.h"
35
36 #include "test_nua.h"
37
38 #if HAVE_ALARM
39 #include <signal.h>
40 #endif
41
42 #if defined(_WIN32)
43 #include <fcntl.h>
44 #endif
45
46 SOFIAPUBVAR su_log_t nua_log[];
47 SOFIAPUBVAR su_log_t soa_log[];
48 SOFIAPUBVAR su_log_t nea_log[];
49 SOFIAPUBVAR su_log_t nta_log[];
50 SOFIAPUBVAR su_log_t tport_log[];
51 SOFIAPUBVAR su_log_t su_log_default[];
52
53 char const name[] = "test_nua";
54 int print_headings = 1;
55 int tstflags = 0;
56
57 #if HAVE_FUNC
58 #elif HAVE_FUNCTION
59 #define __func__ __FUNCTION__
60 #else
61 #define __func__ name
62 #endif
63
64 #if HAVE_ALARM
sig_alarm(int s)65 static RETSIGTYPE sig_alarm(int s)
66 {
67 fprintf(stderr, "%s: FAIL! test timeout!\n", name);
68 if (tstflags & tst_abort)
69 abort();
70 exit(1);
71 }
72 #endif
73
74 static char const options_usage[] =
75 " -v | --verbose be verbose\n"
76 " -q | --quiet be quiet\n"
77 " -a | --abort abort on error\n"
78 " -s use only single thread\n"
79 " -l level set logging level (0 by default)\n"
80 " -e | --events print nua events\n"
81 " -A print nua events for A\n"
82 " -B print nua events for B\n"
83 " -C print nua events for C\n"
84 " --log=a log messages for A\n"
85 " --log=b log messages for B\n"
86 " --log=c log messages for C\n"
87 " --log=proxy log messages for proxy\n"
88 " --attach print pid, wait for a debugger to be attached\n"
89 " --no-proxy do not use internal proxy\n"
90 " --no-nat do not use internal \"nat\"\n"
91 " --symmetric run internal \"nat\" in symmetric mode\n"
92 " -N print events from internal \"nat\"\n"
93 " --loop loop main tests for ever\n"
94 " --no-alarm don't ask for guard ALARM\n"
95 " -p uri specify uri of outbound proxy (implies --no-proxy)\n"
96 " --proxy-tests run tests involving proxy, too\n"
97 #if SU_HAVE_OSX_CF_API /* If compiled with CoreFoundation events */
98 " --osx-runloop use OSX CoreFoundation runloop instead of poll() loop\n"
99 #endif
100 " -k do not exit after first error\n"
101 ;
102
usage(int exitcode)103 static void usage(int exitcode)
104 {
105 fprintf(stderr, "usage: %s OPTIONS\n where OPTIONS are\n%s",
106 name, options_usage);
107 exit(exitcode);
108 }
109
main(int argc,char * argv[])110 int main(int argc, char *argv[])
111 {
112 int retval = 0;
113 int i, o_quiet = 0, o_attach = 0, o_alarm = 1, o_loop = 0;
114 int o_events_init = 0, o_events_a = 0, o_events_b = 0, o_events_c = 0;
115 int o_iproxy = 1, o_inat = 1;
116 int o_inat_symmetric = 0, o_inat_logging = 0, o_expensive = 0;
117 url_t const *o_proxy = NULL;
118 int level = 0;
119
120 struct context ctx[1] = {{{ SU_HOME_INIT(ctx) }}};
121
122 #if HAVE_OPEN_C
123 dup2(1, 2);
124 #endif
125
126 if (getenv("EXPENSIVE_CHECKS"))
127 o_expensive = 1;
128
129 ctx->threading = 1;
130 ctx->quit_on_single_failure = 1;
131
132 endpoint_init(ctx, &ctx->a, 'a');
133 endpoint_init(ctx, &ctx->b, 'b');
134 endpoint_init(ctx, &ctx->c, 'c');
135
136 for (i = 1; argv[i]; i++) {
137 if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
138 tstflags |= tst_verbatim;
139 else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--abort") == 0)
140 tstflags |= tst_abort;
141 else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0)
142 tstflags &= ~tst_verbatim, o_quiet = 1;
143 else if (strcmp(argv[i], "-k") == 0)
144 ctx->quit_on_single_failure = 0;
145 else if (strncmp(argv[i], "-l", 2) == 0) {
146 char *rest = NULL;
147
148 if (argv[i][2])
149 level = strtol(argv[i] + 2, &rest, 10);
150 else if (argv[i + 1])
151 level = strtol(argv[i + 1], &rest, 10), i++;
152 else
153 level = 3, rest = "";
154
155 if (rest == NULL || *rest)
156 usage(1);
157
158 su_log_set_level(nua_log, level);
159 su_log_soft_set_level(soa_log, level);
160 su_log_soft_set_level(nea_log, level);
161 su_log_soft_set_level(nta_log, level);
162 su_log_soft_set_level(tport_log, level);
163 }
164 else if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--events") == 0) {
165 o_events_init = o_events_a = o_events_b = o_events_c = 1;
166 }
167 else if (strcmp(argv[i], "-I") == 0) {
168 o_events_init = 1;
169 }
170 else if (strcmp(argv[i], "-A") == 0) {
171 o_events_a = 1;
172 }
173 else if (strcmp(argv[i], "-B") == 0) {
174 o_events_b = 1;
175 }
176 else if (strcmp(argv[i], "-C") == 0) {
177 o_events_c = 1;
178 }
179 else if (strcmp(argv[i], "-s") == 0) {
180 ctx->threading = 0;
181 }
182 else if (strcmp(argv[i], "--attach") == 0) {
183 o_attach = 1;
184 }
185 else if (strncmp(argv[i], "-p", 2) == 0) {
186 if (argv[i][2])
187 o_proxy = URL_STRING_MAKE(argv[i] + 2)->us_url;
188 else if (!argv[++i] || argv[i][0] == '-')
189 usage(1);
190 else
191 o_proxy = URL_STRING_MAKE(argv[i])->us_url;
192 }
193 else if (strcmp(argv[i], "--proxy-tests") == 0) {
194 ctx->proxy_tests = 1;
195 }
196 else if (strcmp(argv[i], "--no-proxy") == 0) {
197 o_iproxy = 0;
198 }
199 else if (strcmp(argv[i], "--no-nat") == 0) {
200 o_inat = 0;
201 }
202 else if (strcmp(argv[i], "--nat") == 0) {
203 o_inat = 1;
204 }
205 else if (strcmp(argv[i], "--symmetric") == 0) {
206 o_inat_symmetric = 1;
207 }
208 else if (strcmp(argv[i], "-N") == 0) {
209 o_inat_logging = 1;
210 }
211 else if (strcmp(argv[i], "--expensive") == 0) {
212 o_expensive = 1;
213 }
214 else if (strcmp(argv[i], "--no-alarm") == 0) {
215 o_alarm = 0;
216 }
217 else if (strcmp(argv[i], "--loop") == 0) {
218 o_alarm = 0, o_loop = 1;
219 }
220 else if (strcmp(argv[i], "--print-tags") == 0) {
221 ctx->print_tags = 1;
222 }
223 else if (strcmp(argv[i], "--tags=a") == 0) {
224 ctx->a.print_tags = 1;
225 }
226 else if (strcmp(argv[i], "--tags=b") == 0) {
227 ctx->b.print_tags = 1;
228 }
229 else if (strcmp(argv[i], "--tags=c") == 0) {
230 ctx->c.print_tags = 1;
231 }
232 else if (strcmp(argv[i], "--log=a") == 0) {
233 ctx->a.logging = 1;
234 }
235 else if (strcmp(argv[i], "--log=b") == 0) {
236 ctx->b.logging = 1;
237 }
238 else if (strcmp(argv[i], "--log=c") == 0) {
239 ctx->c.logging = 1;
240 }
241 else if (strcmp(argv[i], "--log=proxy") == 0) {
242 ctx->proxy_logging = 1;
243 }
244 #if SU_HAVE_OSX_CF_API /* If compiled with CoreFoundation events */
245 else if (strcmp(argv[i], "--osx-runloop") == 0) {
246 ctx->osx_runloop = 1;
247 }
248 #endif
249 else if (strcmp(argv[i], "-") == 0) {
250 i++; break;
251 }
252 else if (argv[i][0] != '-') {
253 break;
254 }
255 else {
256 fprintf(stderr, "test_nua: unknown argument \"%s\"\n\n", argv[i]);
257 usage(1);
258 }
259 }
260
261 if (o_attach) {
262 char line[10], *l;
263 printf("%s: pid %lu\n", name, (unsigned long)getpid());
264 printf("<Press RETURN to continue>\n");
265 l = fgets(line, sizeof line, stdin);
266 }
267 #if HAVE_ALARM
268 else if (o_alarm) {
269 signal(SIGALRM, sig_alarm);
270 if (o_expensive) {
271 printf("%s: extending timeout to %u because expensive tests\n",
272 name, 240);
273 alarm(240);
274 }
275 else {
276 alarm(120);
277 }
278 }
279 #endif
280
281 #if HAVE_OPEN_C
282 tstflags |= tst_verbatim;
283 level = 9;
284 o_inat = 1; /* No NATs */
285 ctx->threading = 1;
286 ctx->quit_on_single_failure = 1;
287 su_log_soft_set_level(nua_log, level);
288 su_log_soft_set_level(soa_log, level);
289 su_log_soft_set_level(su_log_default, level);
290 su_log_soft_set_level(nea_log, level);
291 su_log_soft_set_level(nta_log, level);
292 su_log_soft_set_level(tport_log, level);
293 setenv("SU_DEBUG", "9", 1);
294 setenv("NUA_DEBUG", "9", 1);
295 setenv("NTA_DEBUG", "9", 1);
296 setenv("TPORT_DEBUG", "9", 1);
297 o_events_a = o_events_b = 1;
298 #endif
299
300 su_init();
301
302 if (!(TSTFLAGS & tst_verbatim)) {
303 if (level == 0 && !o_quiet)
304 level = 1;
305 su_log_soft_set_level(nua_log, level);
306 su_log_soft_set_level(soa_log, level);
307 su_log_soft_set_level(su_log_default, level);
308 su_log_soft_set_level(nea_log, level);
309 su_log_soft_set_level(nta_log, level);
310 su_log_soft_set_level(tport_log, level);
311 }
312
313 if (!o_quiet || (TSTFLAGS & tst_verbatim)
314 || o_events_a || o_events_b || o_events_c)
315 print_headings = 1;
316
317 #if !HAVE_OPEN_C
318 #define SINGLE_FAILURE_CHECK() \
319 do { fflush(stdout); \
320 if (retval && ctx->quit_on_single_failure) { \
321 su_deinit(); return retval; } \
322 } while(0)
323 #else
324 #define SINGLE_FAILURE_CHECK() \
325 do { fflush(stdout); \
326 if (retval && ctx->quit_on_single_failure) { \
327 su_deinit(); sleep(10); return retval; } \
328 } while(0)
329 #endif
330
331 ctx->a.printer = o_events_init ? print_event : NULL;
332
333 retval |= test_nua_api_errors(ctx); SINGLE_FAILURE_CHECK();
334
335 retval |= test_tag_filter(); SINGLE_FAILURE_CHECK();
336
337 retval |= test_nua_params(ctx); SINGLE_FAILURE_CHECK();
338
339 retval |= test_nua_destroy(ctx); SINGLE_FAILURE_CHECK();
340
341 retval |= test_stack_errors(ctx); SINGLE_FAILURE_CHECK();
342
343 retval |= test_nua_init(ctx, o_iproxy, o_proxy, o_inat,
344 TESTNATTAG_SYMMETRIC(o_inat_symmetric),
345 TESTNATTAG_LOGGING(o_inat_logging),
346 TAG_END());
347
348 ctx->expensive = o_expensive;
349
350 if (retval == 0) {
351 ctx->a.printer = o_events_a ? print_event : NULL;
352 if (o_events_b)
353 ctx->b.printer = print_event;
354 if (o_events_c)
355 ctx->c.printer = print_event;
356
357 retval |= test_register(ctx);
358
359 if (retval == 0)
360 retval |= test_connectivity(ctx);
361
362 if (retval == 0 && o_inat)
363 retval |= test_nat_timeout(ctx);
364
365 while (retval == 0) {
366 retval |= test_basic_call(ctx); SINGLE_FAILURE_CHECK();
367 retval |= test_rejects(ctx); SINGLE_FAILURE_CHECK();
368 retval |= test_call_cancel(ctx); SINGLE_FAILURE_CHECK();
369 retval |= test_call_destroy(ctx); SINGLE_FAILURE_CHECK();
370 retval |= test_early_bye(ctx); SINGLE_FAILURE_CHECK();
371 retval |= test_offer_answer(ctx); SINGLE_FAILURE_CHECK();
372 retval |= test_reinvites(ctx); SINGLE_FAILURE_CHECK();
373 retval |= test_session_timer(ctx); SINGLE_FAILURE_CHECK();
374 retval |= test_refer(ctx); SINGLE_FAILURE_CHECK();
375 retval |= test_100rel(ctx); SINGLE_FAILURE_CHECK();
376 retval |= test_simple(ctx); SINGLE_FAILURE_CHECK();
377 retval |= test_events(ctx); SINGLE_FAILURE_CHECK();
378 retval |= test_extension(ctx); SINGLE_FAILURE_CHECK();
379 if (!o_loop)
380 break;
381 }
382
383 if (ctx->proxy_tests && (retval == 0 || !ctx->p))
384 retval |= test_unregister(ctx); SINGLE_FAILURE_CHECK();
385 }
386 retval |= test_deinit(ctx);
387
388 su_home_deinit(ctx->home);
389
390 su_deinit();
391
392 #if HAVE_OPEN_C
393 sleep(7);
394 #endif
395
396 return retval;
397 }
398