belle_sip_tester.c 12.7 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 2 of the License, or
jehan's avatar
jehan committed
8 9 10 11 12 13 14 15 16 17
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
Simon Morlat's avatar
Simon Morlat committed
18 19 20
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Ghislain MARY's avatar
Ghislain MARY committed
21
#include "belle_sip_tester.h"
Simon Morlat's avatar
Simon Morlat committed
22

jehan's avatar
jehan committed
23 24
#include <stdio.h>
#include "CUnit/Basic.h"
25
#include "CUnit/MyMem.h"
26
#include "CUnit/Automated.h"
Ghislain MARY's avatar
Ghislain MARY committed
27
#ifdef HAVE_CU_CURSES
28 29
#include "CUnit/CUCurses.h"
#endif
Simon Morlat's avatar
Simon Morlat committed
30
#include <belle-sip/belle-sip.h>
jehan's avatar
jehan committed
31

32 33
#include "port.h"

Simon Morlat's avatar
Simon Morlat committed
34
extern const char *test_domain;
35
extern const char *auth_domain;
Ghislain MARY's avatar
Ghislain MARY committed
36

37
static const char *belle_sip_tester_root_ca_path = NULL;
Ghislain MARY's avatar
Ghislain MARY committed
38 39
static test_suite_t **test_suite = NULL;
static int nb_test_suites = 0;
40
static int belle_sip_tester_use_log_file=0;
Simon Morlat's avatar
Simon Morlat committed
41

42 43 44 45 46 47
#ifdef ANDROID
const char *belle_sip_tester_writable_dir_prefix = "/data/data/org.linphone.tester/cache";
#else
const char *belle_sip_tester_writable_dir_prefix = ".";
#endif

Ghislain MARY's avatar
Ghislain MARY committed
48
#ifdef HAVE_CU_CURSES
jehan's avatar
jehan committed
49 50
	static unsigned char curses = 0;
#endif
51

52 53
static const char *belle_sip_tester_xml_file = NULL;
static unsigned char belle_sip_tester_xml_enabled = FALSE;
54

55

Ghislain MARY's avatar
Ghislain MARY committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
static void add_test_suite(test_suite_t *suite) {
	if (test_suite == NULL) {
		test_suite = (test_suite_t **)malloc(10 * sizeof(test_suite_t *));
	}
	test_suite[nb_test_suites] = suite;
	nb_test_suites++;
	if ((nb_test_suites % 10) == 0) {
		test_suite = (test_suite_t **)realloc(test_suite, (nb_test_suites + 10) * sizeof(test_suite_t *));
	}
}

static int run_test_suite(test_suite_t *suite) {
	int i;

	CU_pSuite pSuite = CU_add_suite(suite->name, suite->init_func, suite->cleanup_func);

	for (i = 0; i < suite->nb_tests; i++) {
		if (NULL == CU_add_test(pSuite, suite->tests[i].name, suite->tests[i].func)) {
			return CU_get_error();
		}
	}

	return 0;
}

static int test_suite_index(const char *suite_name) {
	int i;
83

Ghislain MARY's avatar
Ghislain MARY committed
84 85 86 87 88
	for (i = 0; i < belle_sip_tester_nb_test_suites(); i++) {
		if ((strcmp(suite_name, test_suite[i]->name) == 0) && (strlen(suite_name) == strlen(test_suite[i]->name))) {
			return i;
		}
	}
89

Ghislain MARY's avatar
Ghislain MARY committed
90 91
	return -1;
}
92

Ghislain MARY's avatar
Ghislain MARY committed
93 94 95
int belle_sip_tester_nb_test_suites(void) {
	return nb_test_suites;
}
96

Ghislain MARY's avatar
Ghislain MARY committed
97 98 99 100 101
int belle_sip_tester_nb_tests(const char *suite_name) {
	int i = test_suite_index(suite_name);
	if (i < 0) return 0;
	return test_suite[i]->nb_tests;
}
102

Ghislain MARY's avatar
Ghislain MARY committed
103 104 105 106
const char * belle_sip_tester_test_suite_name(int suite_index) {
	if (suite_index >= belle_sip_tester_nb_test_suites()) return NULL;
	return test_suite[suite_index]->name;
}
107

Ghislain MARY's avatar
Ghislain MARY committed
108 109 110 111 112 113
const char * belle_sip_tester_test_name(const char *suite_name, int test_index) {
	int suite_index = test_suite_index(suite_name);
	if ((suite_index < 0) || (suite_index >= belle_sip_tester_nb_test_suites())) return NULL;
	if (test_index >= test_suite[suite_index]->nb_tests) return NULL;
	return test_suite[suite_index]->tests[test_index].name;
}
114

Simon Morlat's avatar
Simon Morlat committed
115 116 117 118 119 120 121 122 123 124 125 126
static int _belle_sip_tester_ipv6_available(void){
	struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_INET6,"2a01:e00::2",53);
	if (ai){
		struct sockaddr_storage ss;
		struct addrinfo src;
		socklen_t slen=sizeof(ss);
		char localip[128];
		int port=0;
		belle_sip_get_src_addr_for(ai->ai_addr,ai->ai_addrlen,(struct sockaddr*) &ss,&slen,4444);
		src.ai_addr=(struct sockaddr*) &ss;
		src.ai_addrlen=slen;
		belle_sip_addrinfo_to_ip(&src,localip, sizeof(localip),&port);
127
		belle_sip_freeaddrinfo(ai);
Simon Morlat's avatar
Simon Morlat committed
128 129 130 131 132 133 134 135 136 137 138
		return strcmp(localip,"::1")!=0;
	}
	return FALSE;
}

static int ipv6_available=0;

int belle_sip_tester_ipv6_available(void){
	return ipv6_available;
}

Simon Morlat's avatar
Simon Morlat committed
139
void belle_sip_tester_init() {
140
	belle_sip_init_sockets();
141
	belle_sip_object_enable_marshal_check(TRUE);
Simon Morlat's avatar
Simon Morlat committed
142
	ipv6_available=_belle_sip_tester_ipv6_available();
Ghislain MARY's avatar
Ghislain MARY committed
143
	add_test_suite(&cast_test_suite);
144 145
	add_test_suite(&sip_uri_test_suite);
	add_test_suite(&generic_uri_test_suite);
Ghislain MARY's avatar
Ghislain MARY committed
146
	add_test_suite(&headers_test_suite);
147
	add_test_suite(&core_test_suite);
Ghislain MARY's avatar
Ghislain MARY committed
148 149 150 151 152 153 154
	add_test_suite(&sdp_test_suite);
	add_test_suite(&resolver_test_suite);
	add_test_suite(&message_test_suite);
	add_test_suite(&authentication_helper_test_suite);
	add_test_suite(&register_test_suite);
	add_test_suite(&dialog_test_suite);
	add_test_suite(&refresher_test_suite);
Simon Morlat's avatar
Simon Morlat committed
155
	add_test_suite(&http_test_suite);
Ghislain MARY's avatar
Ghislain MARY committed
156
}
157

158 159 160 161 162 163 164 165
const char * belle_sip_tester_get_root_ca_path(void) {
	return belle_sip_tester_root_ca_path;
}

void belle_sip_tester_set_root_ca_path(const char *root_ca_path) {
	belle_sip_tester_root_ca_path = root_ca_path;
}

166 167
void belle_sip_tester_set_xml_output(const char *xml_path ) {
	belle_sip_tester_xml_file = xml_path;
168
}
Simon Morlat's avatar
Simon Morlat committed
169 170


Ghislain MARY's avatar
Ghislain MARY committed
171
void belle_sip_tester_uninit(void) {
172
	belle_sip_uninit_sockets();
Ghislain MARY's avatar
Ghislain MARY committed
173 174 175 176 177 178
	if (test_suite != NULL) {
		free(test_suite);
		test_suite = NULL;
		nb_test_suites = 0;
	}
}
179 180 181 182 183 184 185 186

/*derivated from cunit*/
static void test_complete_message_handler(const CU_pTest pTest,
                                                const CU_pSuite pSuite,
                                                const CU_pFailureRecord pFailureList) {
    int i;
    CU_pFailureRecord pFailure = pFailureList;
	if (pFailure) {
jehan's avatar
jehan committed
187
		if (belle_sip_tester_use_log_file) belle_sip_warning("Suite [%s], Test [%s] had failures:", pSuite->pName, pTest->pName);
188 189
		printf("\nSuite [%s], Test [%s] had failures:", pSuite->pName, pTest->pName);
	} else {
190
		if (belle_sip_tester_use_log_file) belle_sip_warning(" passed");
191 192 193
		printf(" passed");
	}
      for (i = 1 ; (NULL != pFailure) ; pFailure = pFailure->pNext, i++) {
194
    	  if (belle_sip_tester_use_log_file) belle_sip_warning("\n    %d. %s:%u  - %s", i,
195 196 197 198 199 200 201 202 203 204 205 206
            (NULL != pFailure->strFileName) ? pFailure->strFileName : "",
            pFailure->uiLineNumber,
            (NULL != pFailure->strCondition) ? pFailure->strCondition : "");
    	  printf("\n    %d. %s:%u  - %s", i,
            (NULL != pFailure->strFileName) ? pFailure->strFileName : "",
            pFailure->uiLineNumber,
            (NULL != pFailure->strCondition) ? pFailure->strCondition : "");
      }
 }


static void test_all_tests_complete_message_handler(const CU_pFailureRecord pFailure) {
207
  char *result_string;
jehan's avatar
jehan committed
208
  if (belle_sip_tester_use_log_file) belle_sip_warning("\n\n %s",CU_get_run_results_string());
209 210 211 212 213
  result_string = CU_get_run_results_string();
  if (result_string != NULL) {
	  printf("\n\n %s",result_string);
	  CU_FREE(result_string);
  }
214 215 216
}

static void test_suite_init_failure_message_handler(const CU_pSuite pSuite) {
217
	if (belle_sip_tester_use_log_file) belle_sip_warning("Suite initialization failed for [%s].", pSuite->pName);
218 219 220 221
    printf("Suite initialization failed for [%s].", pSuite->pName);
}

static void test_suite_cleanup_failure_message_handler(const CU_pSuite pSuite) {
222
	if (belle_sip_tester_use_log_file) belle_sip_warning("Suite cleanup failed for '%s'.", pSuite->pName);
223 224 225 226
	printf("Suite cleanup failed for [%s].", pSuite->pName);
}

static void test_start_message_handler(const CU_pTest pTest, const CU_pSuite pSuite) {
jehan's avatar
jehan committed
227
	if (belle_sip_tester_use_log_file) belle_sip_warning("Suite [%s] Test [%s]", pSuite->pName,pTest->pName);
228 229
	printf("\nSuite [%s] Test [%s]", pSuite->pName,pTest->pName);
}
jehan's avatar
jehan committed
230 231 232 233
static void test_suite_start_message_handler(const CU_pSuite pSuite) {
	if (belle_sip_tester_use_log_file) belle_sip_warning("Suite [%s]", pSuite->pName);
	printf("\nSuite [%s]", pSuite->pName);
}
Ghislain MARY's avatar
Ghislain MARY committed
234
int belle_sip_tester_run_tests(const char *suite_name, const char *test_name) {
jehan's avatar
jehan committed
235
	int i,ret;
Simon Morlat's avatar
Simon Morlat committed
236
	belle_sip_object_pool_t *pool;
237

Ghislain MARY's avatar
Ghislain MARY committed
238 239 240
	/* initialize the CUnit test registry */
	if (CUE_SUCCESS != CU_initialize_registry())
		return CU_get_error();
241

Ghislain MARY's avatar
Ghislain MARY committed
242 243 244
	for (i = 0; i < belle_sip_tester_nb_test_suites(); i++) {
		run_test_suite(test_suite[i]);
	}
Simon Morlat's avatar
Simon Morlat committed
245
	pool=belle_sip_object_pool_push();
246 247 248 249 250
	CU_set_test_start_handler(test_start_message_handler);
	CU_set_test_complete_handler(test_complete_message_handler);
	CU_set_all_test_complete_handler(test_all_tests_complete_message_handler);
	CU_set_suite_init_failure_handler(test_suite_init_failure_message_handler);
	CU_set_suite_cleanup_failure_handler(test_suite_cleanup_failure_message_handler);
jehan's avatar
jehan committed
251
	CU_set_suite_start_handler(test_suite_start_message_handler);
252

253 254
	if(belle_sip_tester_xml_file != NULL){
		CU_set_output_filename(belle_sip_tester_xml_file);
255
	}
256
	if(belle_sip_tester_xml_enabled){
257
		CU_automated_run_tests();
258
	} else {
Ghislain MARY's avatar
Ghislain MARY committed
259
#ifdef HAVE_CU_GET_SUITE
260 261 262 263 264
		if (suite_name){
			CU_pSuite suite;
			suite=CU_get_suite(suite_name);
			if (suite==NULL){
				fprintf(stderr,"There is no suite named '%s'",suite_name);
Simon Morlat's avatar
Simon Morlat committed
265 266
				exit(-1);
			}
267 268 269 270 271 272 273 274 275
			if (test_name) {
				CU_pTest test=CU_get_test_by_name(test_name, suite);
				if (test==NULL){
					fprintf(stderr,"There is no test named '%s'",suite_name);
					exit(-1);
				}
				CU_run_test(suite, test);
			} else
				CU_run_suite(suite);
276 277
		} else
#endif
278
		{
Ghislain MARY's avatar
Ghislain MARY committed
279
#ifdef HAVE_CU_CURSES
280 281 282 283 284
			if (curses) {
				/* Run tests using the CUnit curses interface */
				CU_curses_run_tests();
			}
			else
285
#endif
286 287 288
			{
				CU_run_all_tests();
			}
289 290 291
		}
	}

Simon Morlat's avatar
Simon Morlat committed
292
	belle_sip_object_unref(pool);
jehan's avatar
jehan committed
293
	ret=CU_get_number_of_tests_failed()!=0;
294
	CU_cleanup_registry();
jehan's avatar
jehan committed
295
	return ret;
296 297 298
}


Ghislain MARY's avatar
Ghislain MARY committed
299 300 301 302 303
void helper(const char *name) {
	fprintf(stderr,"%s \t--help\n"
		"\t\t\t--verbose\n"
		"\t\t\t--domain <test sip domain>\n"
		"\t\t\t--auth-domain <test auth domain>\n"
304
		"\t\t\t--root-ca <root ca file path>\n"
305
		"\t\t\t--log-file <output log file path>\n"
Ghislain MARY's avatar
Ghislain MARY committed
306 307 308 309 310 311 312 313 314
#ifdef HAVE_CU_GET_SUITE
		"\t\t\t--list-suites\n"
		"\t\t\t--list-tests <suite>\n"
		"\t\t\t--suite <suite name>\n"
		"\t\t\t--test <test name>\n"
#endif
#ifdef HAVE_CU_CURSES
		"\t\t\t--curses\n"
#endif
315 316
		"\t\t\t--xml\n"
		"\t\t\t--xml-file <xml file prefix (will be suffixed by '-Results.xml')>\n"
Ghislain MARY's avatar
Ghislain MARY committed
317 318 319 320 321 322 323 324 325
		, name);
}

#define CHECK_ARG(argument, index, argc) \
	if (index >= argc) { \
		fprintf(stderr, "Missing argument for \"%s\"\n", argument); \
		return -1; \
	}

326
#ifndef WINAPI_FAMILY_PHONE_APP
327

jehan's avatar
jehan committed
328
int main (int argc, char *argv[]) {
Simon Morlat's avatar
Simon Morlat committed
329
	int i;
Ghislain MARY's avatar
Ghislain MARY committed
330
	int ret;
331
	const char *root_ca_path = NULL;
Ghislain MARY's avatar
Ghislain MARY committed
332 333
	const char *suite_name=NULL;
	const char *test_name=NULL;
334
	const char *xml_file=NULL;
Simon Morlat's avatar
Simon Morlat committed
335
	const char *env_domain=getenv("TEST_DOMAIN");
336
	FILE* log_file=NULL;
jehan's avatar
jehan committed
337

Ghislain MARY's avatar
Ghislain MARY committed
338
	belle_sip_tester_init();
339

Simon Morlat's avatar
Simon Morlat committed
340 341
	if (env_domain)
		test_domain=env_domain;
342

Simon Morlat's avatar
Simon Morlat committed
343 344
	for(i=1;i<argc;++i){
		if (strcmp(argv[i],"--help")==0){
Ghislain MARY's avatar
Ghislain MARY committed
345 346
			helper(argv[0]);
			return 0;
Simon Morlat's avatar
Simon Morlat committed
347
		}else if (strcmp(argv[i],"--verbose")==0){
Simon Morlat's avatar
Simon Morlat committed
348
			belle_sip_set_log_level(BELLE_SIP_LOG_DEBUG);
349 350 351 352 353 354
		}else if (strcmp(argv[i],"--log-file")==0){
			CHECK_ARG("--log-file", ++i, argc);
			log_file=fopen(argv[i],"w");
			if (!log_file) {
				belle_sip_fatal("Cannot open file [%s] for writting logs because [%s]",argv[i],strerror(errno));
			} else {
355
				belle_sip_tester_use_log_file=1;
jehan's avatar
jehan committed
356
				printf ("Redirecting traces to file [%s]",argv[i]);
357 358 359
				belle_sip_set_log_file(log_file);
			}

Simon Morlat's avatar
Simon Morlat committed
360
		}else if (strcmp(argv[i],"--domain")==0){
Ghislain MARY's avatar
Ghislain MARY committed
361
			CHECK_ARG("--domain", ++i, argc);
Simon Morlat's avatar
Simon Morlat committed
362
			test_domain=argv[i];
363
		}else if (strcmp(argv[i],"--auth-domain")==0){
Ghislain MARY's avatar
Ghislain MARY committed
364 365
			CHECK_ARG("--auth-domain", ++i, argc);
			auth_domain=argv[i];
366 367 368
		} else if (strcmp(argv[i], "--root-ca") == 0) {
			CHECK_ARG("--root-ca", ++i, argc);
			root_ca_path = argv[i];
369 370 371 372 373
		} else if (strcmp(argv[i], "--xml-file") == 0){
			CHECK_ARG("--xml-file", ++i, argc);
			xml_file = argv[i];
		} else if (strcmp(argv[i], "--xml") == 0){
			belle_sip_tester_xml_enabled = 1;
jehan's avatar
jehan committed
374
		}
Ghislain MARY's avatar
Ghislain MARY committed
375
#ifdef HAVE_CU_GET_SUITE
Ghislain MARY's avatar
Ghislain MARY committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
		else if (strcmp(argv[i],"--list-suites")==0){
			int j;
			for(j = 0; j < belle_sip_tester_nb_test_suites(); j++) {
				suite_name = belle_sip_tester_test_suite_name(j);
				fprintf(stdout, "%s\n", suite_name);
			}
			return 0;
		} else if (strcmp(argv[i],"--list-tests")==0){
			int j;
			CHECK_ARG("--list-tests", ++i, argc);
			suite_name = argv[i];
			for(j = 0; j < belle_sip_tester_nb_tests(suite_name);j++) {
				test_name = belle_sip_tester_test_name(suite_name, j);
				fprintf(stdout, "%s\n", test_name);
			}
			return 0;
392
		} else if (strcmp(argv[i],"--test")==0){
Ghislain MARY's avatar
Ghislain MARY committed
393
			CHECK_ARG("--test", ++i, argc);
394
			test_name=argv[i];
jehan's avatar
jehan committed
395
		}else if (strcmp(argv[i],"--suite")==0){
Ghislain MARY's avatar
Ghislain MARY committed
396
			CHECK_ARG("--suite", ++i, argc);
jehan's avatar
jehan committed
397
			suite_name=argv[i];
Simon Morlat's avatar
Simon Morlat committed
398
		}
399
#endif
Ghislain MARY's avatar
Ghislain MARY committed
400
#ifdef HAVE_CU_CURSES
401 402 403
		else if (strcmp(argv[i], "--curses") == 0) {
			curses = 1;
		}
jehan's avatar
jehan committed
404
#endif
Ghislain MARY's avatar
Ghislain MARY committed
405 406 407 408
		else {
			helper(argv[0]);
			return -1;
		}
Simon Morlat's avatar
Simon Morlat committed
409
	}
410

411
#ifdef HAVE_CU_CURSES
Simon Morlat's avatar
Simon Morlat committed
412
	if( xml_file && curses ){
413
		printf("Cannot use both xml and curses\n");
414 415 416 417
		return -1;
	}
#endif

418 419
	if( belle_sip_tester_xml_enabled && (suite_name || test_name) ){
		printf("Cannot use both xml and specific test suite\n");
420 421 422
		return -1;
	}

423 424
	if( xml_file != NULL ){
		belle_sip_tester_set_xml_output(xml_file);
425
	}
426
	belle_sip_tester_set_root_ca_path(root_ca_path);
Ghislain MARY's avatar
Ghislain MARY committed
427 428
	ret = belle_sip_tester_run_tests(suite_name, test_name);
	belle_sip_tester_uninit();
429
	if (log_file) fclose(log_file);
Ghislain MARY's avatar
Ghislain MARY committed
430
	return ret;
jehan's avatar
jehan committed
431
}
432
#endif