liblinphone_tester.c 7.62 KB
Newer Older
jehan's avatar
jehan committed
1
/*
2 3
 liblinphone_tester - liblinphone test suite
 Copyright (C) 2013  Belledonne Communications SARL
jehan's avatar
jehan committed
4

5 6 7 8
 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
 the Free Software Foundation, either version 2 of the License, or
 (at your option) any later version.
jehan's avatar
jehan committed
9

10 11 12 13
 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.
jehan's avatar
jehan committed
14

15 16 17
 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

jehan's avatar
jehan committed
20
#include "linphonecore.h"
21
#include "private.h"
jehan's avatar
jehan committed
22
#include "liblinphone_tester.h"
jehan's avatar
jehan committed
23 24 25
#if HAVE_CU_CURSES
#include "CUnit/CUCurses.h"
#endif
26 27 28
#ifdef HAVE_GTK
#include <gtk/gtk.h>
#endif
29

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
30 31
static FILE * log_file = NULL;

Yann Diorcet's avatar
Yann Diorcet committed
32
#ifdef ANDROID
33

34
#include <android/log.h>
35 36 37
#include <jni.h>
#include <CUnit/Util.h>
#define CALLBACK_BUFFER_SIZE  1024
38

39 40
static JNIEnv *current_env = NULL;
static jobject current_obj = 0;
41 42
static const char* LogDomain = "liblinphone_tester";

43 44
int main(int argc, char** argv);

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
45
void liblinphone_android_log_handler(int prio, const char *fmt, va_list args) {
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	char str[4096];
	char *current;
	char *next;

	vsnprintf(str, sizeof(str) - 1, fmt, args);
	str[sizeof(str) - 1] = '\0';
	if (strlen(str) < 512) {
		__android_log_write(prio, LogDomain, str);
	} else {
		current = str;
		while ((next = strchr(current, '\n')) != NULL) {
			*next = '\0';
			__android_log_write(prio, LogDomain, current);
			current = next + 1;
		}
		__android_log_write(prio, LogDomain, current);
	}
}

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
65
static void liblinphone_android_ortp_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) {
66 67
	int prio;
	switch(lev){
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
68 69 70 71 72 73
		case ORTP_DEBUG:	prio = ANDROID_LOG_DEBUG;	break;
		case ORTP_MESSAGE:	prio = ANDROID_LOG_INFO;	break;
		case ORTP_WARNING:	prio = ANDROID_LOG_WARN;	break;
		case ORTP_ERROR:	prio = ANDROID_LOG_ERROR;	break;
		case ORTP_FATAL:	prio = ANDROID_LOG_FATAL;	break;
		default:			prio = ANDROID_LOG_DEFAULT;	break;
74
	}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
75
	liblinphone_android_log_handler(prio, fmt, args);
76
}
77 78 79 80 81 82 83 84 85 86 87 88

void cunit_android_trace_handler(int level, const char *fmt, va_list args) {
	char buffer[CALLBACK_BUFFER_SIZE];
	JNIEnv *env = current_env;
	if(env == NULL) return;
	vsnprintf(buffer, CALLBACK_BUFFER_SIZE, fmt, args);
	jstring javaString = (*env)->NewStringUTF(env, buffer);
	jint javaLevel = level;
	jclass cls = (*env)->GetObjectClass(env, current_obj);
	jmethodID method = (*env)->GetMethodID(env, cls, "printLog", "(ILjava/lang/String;)V");
	(*env)->CallVoidMethod(env, current_obj, method, javaLevel, javaString);
	(*env)->DeleteLocalRef(env,javaString);
89
	(*env)->DeleteLocalRef(env,cls);
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
}

JNIEXPORT jint JNICALL Java_org_linphone_tester_Tester_run(JNIEnv *env, jobject obj, jobjectArray stringArray) {
	int i, ret;
	int argc = (*env)->GetArrayLength(env, stringArray);
	char **argv = (char**) malloc(sizeof(char*) * argc);

	for (i=0; i<argc; i++) {
		jstring string = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
		const char *rawString = (const char *) (*env)->GetStringUTFChars(env, string, 0);
		argv[i] = strdup(rawString);
		(*env)->ReleaseStringUTFChars(env, string, rawString);
	}
	current_env = env;
	current_obj = obj;
	CU_set_trace_handler(cunit_android_trace_handler);
	ret = main(argc, argv);
	current_env = NULL;
	CU_set_trace_handler(NULL);
	for (i=0; i<argc; i++) {
		free(argv[i]);
	}
	free(argv);
	return ret;
}

116 117 118 119 120 121 122
JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_keepAccounts(JNIEnv *env, jclass c, jboolean keep) {
	liblinphone_tester_keep_accounts((int)keep);
}

JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_clearAccounts(JNIEnv *env, jclass c) {
	liblinphone_tester_clear_accounts();
}
123
#endif /* ANDROID */
Ghislain MARY's avatar
Ghislain MARY committed
124

125 126 127 128 129 130
#ifdef __QNX__
static void liblinphone_tester_qnx_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) {
	ortp_qnx_log_handler("liblinphone_tester", lev, fmt, args);
}
#endif /* __QNX__ */

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
131
static void log_handler(int lev, const char *fmt, va_list args) {
Ghislain MARY's avatar
Ghislain MARY committed
132
#ifdef _WIN32
133 134 135 136 137
	vfprintf(lev == ORTP_ERROR ? stderr : stdout, fmt, args);
	fprintf(lev == ORTP_ERROR ? stderr : stdout, "\n");
#else
	va_list cap;
	va_copy(cap,args);
138 139
#ifdef ANDROID
	/* IMPORTANT: needed by liblinphone tester to retrieve suite list...*/
140
	cunit_android_trace_handler(lev == ORTP_ERROR, fmt, cap);
141
#else
142
	/* Otherwise, we must use stdio to avoid log formatting (for autocompletion etc.) */
143 144 145 146
	vfprintf(lev == ORTP_ERROR ? stderr : stdout, fmt, cap);
	fprintf(lev == ORTP_ERROR ? stderr : stdout, "\n");
#endif
	va_end(cap);
147
#endif
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
148
	if (log_file){
149
		ortp_logv_out(lev, fmt, args);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
150 151 152
	}
}

Ghislain MARY's avatar
Ghislain MARY committed
153
void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) {
154
	if (! log_file) {
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
155
#if defined(ANDROID)
156
		linphone_core_set_log_handler(liblinphone_android_ortp_log_handler);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
157
#elif defined(__QNX__)
158
		linphone_core_set_log_handler(liblinphone_tester_qnx_log_handler);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
159
#endif
160
	}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
161

Ghislain MARY's avatar
Ghislain MARY committed
162 163
	if (ftester_printf == NULL) ftester_printf = log_handler;
	bc_tester_init(ftester_printf, ORTP_MESSAGE, ORTP_ERROR);
164
	liblinphone_tester_add_suites();
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
165 166 167 168 169
}

void liblinphone_tester_uninit(void) {
	bc_tester_uninit();
}
170 171


172
#if !__ios && !(defined(LINPHONE_WINDOWS_PHONE) || defined(LINPHONE_WINDOWS_UNIVERSAL))
Ghislain MARY's avatar
Ghislain MARY committed
173

174
static const char* liblinphone_helper =
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
175 176 177 178 179 180
		"\t\t\t--verbose\n"
		"\t\t\t--silent\n"
		"\t\t\t--log-file <output log file path>\n"
		"\t\t\t--config <config path>\n"
		"\t\t\t--domain <test sip domain>\n"
		"\t\t\t--auth-domain <test auth domain>\n"
181 182
		"\t\t\t--dns-hosts </etc/hosts -like file to used to override DNS names (default: tester_hosts)>\n"
		"\t\t\t--keep-recorded-files\n";
Yann Diorcet's avatar
Yann Diorcet committed
183

184 185
int main (int argc, char *argv[])
{
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
186 187 188
	int i;
	int ret;

189 190
#ifdef HAVE_GTK
	gtk_init(&argc, &argv);
François Grisez's avatar
François Grisez committed
191 192 193
#if !GLIB_CHECK_VERSION(2,32,0) // backward compatibility with Debian 6 and CentOS 6
	g_thread_init(NULL);
#endif
194
	gdk_threads_init();
195 196
#endif

Ghislain MARY's avatar
Ghislain MARY committed
197
	liblinphone_tester_init(NULL);
Ghislain MARY's avatar
Ghislain MARY committed
198

199 200 201 202 203 204
	// this allows to launch liblinphone_tester from outside of tester directory
	if (strstr(argv[0], ".libs")) {
		char* prefix = ms_strdup_printf("%s%s", argv[0][0]=='/'?"":"./", strstr(argv[0], ".libs"));
		bc_tester_set_resource_dir_prefix(prefix);
		bc_tester_set_writable_dir_prefix(prefix);
		ms_free(prefix);
205 206
	}

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
207 208
	for(i = 1; i < argc; ++i) {
		if (strcmp(argv[i], "--verbose") == 0) {
209
			linphone_core_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
210
		} else if (strcmp(argv[i], "--silent") == 0) {
211
			linphone_core_set_log_level_mask(ORTP_FATAL);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
212 213 214 215 216 217 218 219
		} else if (strcmp(argv[i],"--log-file")==0){
			CHECK_ARG("--log-file", ++i, argc);
			log_file=fopen(argv[i],"w");
			if (!log_file) {
				ms_error("Cannot open file [%s] for writing logs because [%s]",argv[i],strerror(errno));
				return -2;
			} else {
				ms_message("Redirecting traces to file [%s]",argv[i]);
220
				ortp_set_log_file(log_file);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
221
			}
Yann Diorcet's avatar
Yann Diorcet committed
222 223
		} else if (strcmp(argv[i],"--domain")==0){
			CHECK_ARG("--domain", ++i, argc);
jehan's avatar
jehan committed
224
			test_domain=argv[i];
Yann Diorcet's avatar
Yann Diorcet committed
225 226
		} else if (strcmp(argv[i],"--auth-domain")==0){
			CHECK_ARG("--auth-domain", ++i, argc);
jehan's avatar
jehan committed
227
			auth_domain=argv[i];
Yann Diorcet's avatar
Yann Diorcet committed
228 229
		} else if (strcmp(argv[i],"--config")==0){
			CHECK_ARG("--config", ++i, argc);
230
			bc_tester_set_resource_dir_prefix(argv[i]);
Simon Morlat's avatar
Simon Morlat committed
231 232 233
		}else if (strcmp(argv[i],"--dns-hosts")==0){
			CHECK_ARG("--dns-hosts", ++i, argc);
			userhostsfile=argv[i];
234 235
		} else if (strcmp(argv[i],"--keep-recorded-files")==0){
			liblinphone_tester_keep_recorded_files(TRUE);
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
236
		} else {
237 238 239
			int bret = bc_tester_parse_args(argc, argv, i);
			if (bret>0) {
				i += bret - 1;
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
240
				continue;
241
			} else if (bret<0) {
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
242 243
				bc_tester_helper(argv[0], liblinphone_helper);
			}
244
			return bret;
Yann Diorcet's avatar
Yann Diorcet committed
245 246
		}
	}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
247 248 249 250

	ret = bc_tester_start();
	liblinphone_tester_uninit();
	return ret;
Ghislain MARY's avatar
Ghislain MARY committed
251
}
252
#endif