An error occurred while loading the file. Please try again.
-
Simon Morlat authorededb92f1d
liblinphone_tester.c 12.84 KiB
/*
liblinphone_tester - liblinphone test suite
Copyright (C) 2013 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
the Free Software Foundation, either version 2 of the License, or
(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/>.
*/
#include "linphone/core.h"
#include "liblinphone_tester.h"
#include "tester_utils.h"
static FILE * log_file = NULL;
static const char* liblinphone_helper =
"\t\t\t--domain <test sip domain>\n"
"\t\t\t--auth-domain <test auth domain>\n"
"\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"
"\t\t\t--disable-leak-detector\n"
"\t\t\t--disable-tls-support\n"
"\t\t\t--no-ipv6 (turn off IPv6 in LinphoneCore, tests requiring IPv6 will be skipped)\n"
"\t\t\t--show-account-manager-logs (show temporary test account creation logs)\n"
"\t\t\t--no-account-creator (use file database flexisip for account creation)\n"
;
static int liblinphone_tester_start(int argc, char *argv[]) {
int i;
int ret;
liblinphone_tester_init(NULL);
linphone_core_set_log_level(ORTP_ERROR);
for(i = 1; i < argc; ++i) {
if (strcmp(argv[i],"--domain")==0){
CHECK_ARG("--domain", ++i, argc);
test_domain=argv[i];
} else if (strcmp(argv[i],"--auth-domain")==0){
CHECK_ARG("--auth-domain", ++i, argc);
auth_domain=argv[i];
}else if (strcmp(argv[i],"--dns-hosts")==0){
CHECK_ARG("--dns-hosts", ++i, argc);
userhostsfile=argv[i];
} else if (strcmp(argv[i],"--keep-recorded-files")==0){
liblinphone_tester_keep_recorded_files(TRUE);
} else if (strcmp(argv[i],"--disable-leak-detector")==0){
liblinphone_tester_disable_leak_detector(TRUE);
} else if (strcmp(argv[i],"--disable-tls-support")==0){
liblinphone_tester_tls_support_disabled = TRUE;
} else if (strcmp(argv[i],"--no-ipv6")==0){
liblinphonetester_ipv6 = FALSE;
} else if (strcmp(argv[i],"--show-account-manager-logs")==0){
liblinphonetester_show_account_manager_logs=TRUE;
} else if (strcmp(argv[i],"--no-account-creator")==0){
liblinphonetester_no_account_creator=TRUE;
} else {
int bret = bc_tester_parse_args(argc, argv, i);
if (bret>0) {
i += bret - 1;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
continue;
} else if (bret<0) {
bc_tester_helper(argv[0], liblinphone_helper);
}
return bret;
}
}
ret = bc_tester_start(argv[0]);
return ret;
}
static void liblinphone_tester_stop(void) {
liblinphone_tester_uninit();
}
#ifdef __ANDROID__
#include <android/log.h>
#include <jni.h>
#define CALLBACK_BUFFER_SIZE 1024
static JNIEnv *current_env = NULL;
static jobject current_obj = 0;
jobject system_context = 0; // Application context
static const char* LogDomain = "liblinphone_tester";
int main(int argc, char** argv);
static jstring get_jstring_from_char(JNIEnv *env, const char* cString) {
int len;
jmethodID constructorString;
jbyteArray bytesArray = NULL;
jstring javaString = NULL;
jclass classString = (*env)->FindClass(env, "java/lang/String");
if (classString == NULL) {
bctbx_error("Cannot find java.lang.String class.\n");
goto error;
}
constructorString = (*env)->GetMethodID(env, classString, "<init>", "([BLjava/lang/String;)V");
if (constructorString == NULL) {
bctbx_error("Cannot find String <init> method.\n");
goto error;
}
len = (int)strlen(cString);
bytesArray = (*env)->NewByteArray(env, len);
if (bytesArray) {
(*env)->SetByteArrayRegion(env, bytesArray, 0, len, (jbyte *)cString);
jstring UTF8 = (*env)->NewStringUTF(env, "UTF8");
javaString = (jstring)(*env)->NewObject(env, classString, constructorString, bytesArray, UTF8);
(*env)->DeleteLocalRef(env, bytesArray);
(*env)->DeleteLocalRef(env, UTF8);
}
error:
if (classString) (*env)->DeleteLocalRef(env, classString);
return javaString;
}
void liblinphone_android_log_handler(int prio, const char *fmt, va_list args) {
char str[4096];
char *current;
char *next;
vsnprintf(str, sizeof(str) - 1, fmt, args);
str[sizeof(str) - 1] = '\0';
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
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);
}
}
static void liblinphone_android_ortp_log_handler(const char *domain, OrtpLogLevel lev, const char *fmt, va_list args) {
int prio;
switch(lev){
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;
}
liblinphone_android_log_handler(prio, fmt, args);
}
static void liblinphone_android_bctbx_log_handler(const char *domain, BctbxLogLevel lev, const char *fmt, va_list args) {
int prio;
switch(lev){
case BCTBX_LOG_DEBUG: prio = ANDROID_LOG_DEBUG; break;
case BCTBX_LOG_MESSAGE: prio = ANDROID_LOG_INFO; break;
case BCTBX_LOG_WARNING: prio = ANDROID_LOG_WARN; break;
case BCTBX_LOG_ERROR: prio = ANDROID_LOG_ERROR; break;
case BCTBX_LOG_FATAL: prio = ANDROID_LOG_FATAL; break;
default: prio = ANDROID_LOG_DEFAULT; break;
}
liblinphone_android_log_handler(prio, fmt, args);
}
void bcunit_android_trace_handler(int level, const char *fmt, va_list args) {
char buffer[CALLBACK_BUFFER_SIZE];
jstring javaString;
jclass cls;
jmethodID method;
jint javaLevel = level;
JNIEnv *env = current_env;
if(env == NULL) return;
vsnprintf(buffer, CALLBACK_BUFFER_SIZE, fmt, args);
javaString = (*env)->NewStringUTF(env, buffer);
cls = (*env)->GetObjectClass(env, current_obj);
method = (*env)->GetMethodID(env, cls, "printLog", "(ILjava/lang/String;)V");
(*env)->CallVoidMethod(env, current_obj, method, javaLevel, javaString);
(*env)->DeleteLocalRef(env,javaString);
(*env)->DeleteLocalRef(env,cls);
}
JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_setApplicationContext(JNIEnv *env, jclass obj, jobject context) {
system_context = (jobject)(*env)->NewGlobalRef(env, context);
}
JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_removeApplicationContext(JNIEnv *env, jclass obj) {
if (system_context) {
(*env)->DeleteGlobalRef(env, system_context);
system_context = 0;
}
}
JNIEXPORT jint JNICALL Java_org_linphone_tester_Tester_run(JNIEnv *env, jobject obj, jobjectArray stringArray) {
int i, ret;
int argc = (*env)->GetArrayLength(env, stringArray);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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;
bc_set_trace_handler(bcunit_android_trace_handler);
ret = main(argc, argv);
current_env = NULL;
bc_set_trace_handler(NULL);
for (i=0; i<argc; i++) {
free(argv[i]);
}
free(argv);
return ret;
}
JNIEXPORT jstring JNICALL Java_org_linphone_tester_Tester_run2(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;
bc_set_trace_handler(bcunit_android_trace_handler);
ret = liblinphone_tester_start(argc, argv);
jstring failedAsserts = NULL;
if (ret != 0) {
char *failed_asserts = bc_tester_get_failed_asserts();
failedAsserts = get_jstring_from_char(env, failed_asserts);
free(failed_asserts);
}
liblinphone_tester_stop();
current_env = NULL;
bc_set_trace_handler(NULL);
for (i=0; i<argc; i++) {
free(argv[i]);
}
free(argv);
return failedAsserts;
}
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();
}
#endif /* __ANDROID__ */
static void log_handler(int lev, const char *fmt, va_list args) {
#ifdef _WIN32
vfprintf(lev == ORTP_ERROR ? stderr : stdout, fmt, args);
fprintf(lev == ORTP_ERROR ? stderr : stdout, "\n");
#else
va_list cap;
va_copy(cap,args);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
#ifdef __ANDROID__
/* IMPORTANT: needed by liblinphone tester to retrieve suite list...*/
bcunit_android_trace_handler(lev == ORTP_ERROR, fmt, cap);
#else
/* Otherwise, we must use stdio to avoid log formatting (for autocompletion etc.) */
vfprintf(lev == ORTP_ERROR ? stderr : stdout, fmt, cap);
fprintf(lev == ORTP_ERROR ? stderr : stdout, "\n");
#endif
va_end(cap);
#endif
bctbx_logv(BCTBX_LOG_DOMAIN, lev, fmt, args);
}
int silent_arg_func(const char *arg) {
linphone_core_set_log_level(ORTP_FATAL);
return 0;
}
int verbose_arg_func(const char *arg) {
linphone_core_set_log_level(ORTP_MESSAGE);
return 0;
}
int logfile_arg_func(const char *arg) {
if (liblinphone_tester_set_log_file(arg) < 0) return -2;
return 0;
}
void liblinphone_tester_add_suites() {
bc_tester_add_suite(&setup_test_suite);
bc_tester_add_suite(®ister_test_suite);
bc_tester_add_suite(&group_chat_test_suite);
bc_tester_add_suite(&secure_group_chat_test_suite);
bc_tester_add_suite(&tunnel_test_suite);
bc_tester_add_suite(&offeranswer_test_suite);
bc_tester_add_suite(&call_test_suite);
bc_tester_add_suite(&call_recovery_test_suite);
bc_tester_add_suite(&call_with_ice_test_suite);
#ifdef VIDEO_ENABLED
bc_tester_add_suite(&call_video_test_suite);
#endif // ifdef VIDEO_ENABLED
bc_tester_add_suite(&audio_bypass_suite);
bc_tester_add_suite(&multi_call_test_suite);
bc_tester_add_suite(&message_test_suite);
bc_tester_add_suite(&presence_test_suite);
bc_tester_add_suite(&presence_server_test_suite);
bc_tester_add_suite(&account_creator_test_suite);
bc_tester_add_suite(&stun_test_suite);
bc_tester_add_suite(&event_test_suite);
bc_tester_add_suite(&conference_event_test_suite);
bc_tester_add_suite(&contents_test_suite);
bc_tester_add_suite(&flexisip_test_suite);
bc_tester_add_suite(&remote_provisioning_test_suite);
bc_tester_add_suite(&quality_reporting_test_suite);
bc_tester_add_suite(&log_collection_test_suite);
bc_tester_add_suite(&player_test_suite);
bc_tester_add_suite(&dtmf_test_suite);
bc_tester_add_suite(&cpim_test_suite);
bc_tester_add_suite(&multipart_test_suite);
bc_tester_add_suite(&clonable_object_test_suite);
bc_tester_add_suite(&main_db_test_suite);
bc_tester_add_suite(&property_container_test_suite);
#ifdef VIDEO_ENABLED
bc_tester_add_suite(&video_test_suite);
#endif // ifdef VIDEO_ENABLED
bc_tester_add_suite(&multicast_call_test_suite);
bc_tester_add_suite(&proxy_config_test_suite);
#if HAVE_SIPP
bc_tester_add_suite(&complex_sip_call_test_suite);
#endif
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
#ifdef VCARD_ENABLED
bc_tester_add_suite(&vcard_test_suite);
#endif
bc_tester_add_suite(&utils_test_suite);
}
void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) {
bctbx_init_logger(FALSE);
if (! log_file) {
#if defined(__ANDROID__)
linphone_core_set_log_handler(liblinphone_android_ortp_log_handler);
bctbx_set_log_handler(liblinphone_android_bctbx_log_handler);
#endif
}
if (ftester_printf == NULL) ftester_printf = log_handler;
bc_tester_set_silent_func(silent_arg_func);
bc_tester_set_verbose_func(verbose_arg_func);
bc_tester_set_logfile_func(logfile_arg_func);
bc_tester_init(ftester_printf, ORTP_MESSAGE, ORTP_ERROR, "rcfiles");
liblinphone_tester_add_suites();
}
int liblinphone_tester_set_log_file(const char *filename) {
if (log_file) {
fclose(log_file);
}
log_file = fopen(filename, "w");
if (!log_file) {
ms_error("Cannot open file [%s] for writing logs because [%s]", filename, strerror(errno));
return -1;
}
ms_message("Redirecting traces to file [%s]", filename);
linphone_core_set_log_file(log_file);
return 0;
}
#if !TARGET_OS_IPHONE && !(defined(LINPHONE_WINDOWS_PHONE) || defined(LINPHONE_WINDOWS_UNIVERSAL))
int main (int argc, char *argv[])
{
int ret = liblinphone_tester_start(argc, argv);
liblinphone_tester_stop();
return ret;
}
#endif