tester automatically creates unique accounts on flexisip server before running tests. This allows several developer to run the test suite simultaneously !

This commit is contained in:
Simon Morlat 2014-12-01 15:25:08 +01:00
parent b06019c599
commit 93493976b3
14 changed files with 320 additions and 17 deletions

View file

@ -201,6 +201,37 @@ int linphone_address_get_port(const LinphoneAddress *u) {
return sal_address_get_port(u);
}
/**
* Set the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param addr the LinphoneAddress
* @param passwd the password to set.
**/
void linphone_address_set_password(LinphoneAddress *addr, const char *passwd){
sal_address_set_password(addr,passwd);
}
/**
* Get the password encoded in the address.
* It is used for basic authentication (not recommended).
* @param addr the address
* @return the password, if any, NULL otherwise.
**/
const char *linphone_address_get_password(const LinphoneAddress *addr){
return sal_address_get_password(addr);
}
/**
* Set a header into the address.
* Headers appear in the URI with '?', such as <sip:test@linphone.org?SomeHeader=SomeValue>.
* @param addr the address
* @param header_name the header name
* @param header_value the header value
**/
void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value){
sal_address_set_header(addr,header_name,header_value);
}
LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) {
return linphone_address_new(address);
}

View file

@ -117,6 +117,14 @@ void sal_address_set_username(SalAddress *addr, const char *username){
SAL_ADDRESS_SET(addr,user,username);
}
void sal_address_set_password(SalAddress *addr, const char *passwd){
SAL_ADDRESS_SET(addr,user_password,passwd);
}
const char* sal_address_get_password(const SalAddress *addr){
SAL_ADDRESS_GET(addr,user_password);
}
void sal_address_set_domain(SalAddress *addr, const char *host){
SAL_ADDRESS_SET(addr,host,host);
}
@ -180,6 +188,10 @@ void sal_address_set_uri_params(SalAddress *addr, const char *params){
belle_sip_parameters_set(parameters,params);
}
void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value){
belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr)),header_name, header_value);
}
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
if (!sal_address_is_secure(addr)){
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));

View file

@ -1077,6 +1077,10 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
return belle_sip_random_bytes(ret,size);
}
char *sal_get_random_token(int size){
return belle_sip_random_token(ms_malloc(size),size);
}
unsigned int sal_get_random(void){
unsigned int ret=0;
belle_sip_random_bytes((unsigned char*)&ret,4);

View file

@ -103,6 +103,7 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri);
}
belle_sip_uri_set_user_password(contact_uri,NULL);
belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op));
if (op->privacy!=SalPrivacyNone){
belle_sip_uri_set_user(contact_uri,NULL);

View file

@ -6048,6 +6048,8 @@ void sip_config_uninit(LinphoneCore *lc)
if (i>=20) ms_warning("Cannot complete unregistration, giving up");
}
config->proxies=ms_list_free_with_data(config->proxies,(void (*)(void*)) _linphone_proxy_config_release);
config->deleted_proxies=ms_list_free_with_data(config->deleted_proxies,(void (*)(void*)) _linphone_proxy_config_release);
/*no longuer need to write proxy config if not changedlinphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */

View file

@ -400,6 +400,9 @@ LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,Linphon
LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
LINPHONE_PUBLIC void linphone_address_set_password(LinphoneAddress *addr, const char *passwd);
LINPHONE_PUBLIC const char *linphone_address_get_password(const LinphoneAddress *addr);
LINPHONE_PUBLIC void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value);
LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u);
/**
@ -477,6 +480,8 @@ enum _LinphoneIceState{
**/
typedef enum _LinphoneIceState LinphoneIceState;
LINPHONE_PUBLIC const char *linphone_ice_state_to_string(LinphoneIceState state);
/**
* Enum describing uPnP states.
* @ingroup initializing

View file

@ -641,6 +641,24 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
return 0;
}
const char *linphone_ice_state_to_string(LinphoneIceState state){
switch(state){
case LinphoneIceStateFailed:
return "IceStateFailed";
case LinphoneIceStateHostConnection:
return "IceStateHostConnection";
case LinphoneIceStateInProgress:
return "IceStateInProgress";
case LinphoneIceStateNotActivated:
return "IceStateNotActivated";
case LinphoneIceStateReflexiveConnection:
return "IceStateReflexiveConnection";
case LinphoneIceStateRelayConnection:
return "IceStateRelayConnection";
}
return "invalid";
}
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
{
IceCheckList *audio_check_list;
@ -699,6 +717,8 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
}
}
ms_message("Call [%p] New ICE state: audio: [%s] video: [%s]", call,
linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state), linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state));
}
void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)

View file

@ -110,6 +110,9 @@ void sal_address_set_transport_name(SalAddress* addr,const char* transport);
void sal_address_set_params(SalAddress *addr, const char *params);
void sal_address_set_uri_params(SalAddress *addr, const char *params);
bool_t sal_address_is_ipv6(SalAddress *addr);
void sal_address_set_password(SalAddress *addr, const char *passwd);
const char *sal_address_get_password(const SalAddress *addr);
void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value);
Sal * sal_init();
void sal_uninit(Sal* sal);
@ -755,6 +758,7 @@ LINPHONE_PUBLIC bool_t sal_dns_srv_enabled(const Sal *sal);
LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file);
LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal);
unsigned int sal_get_random(void);
char *sal_get_random_token(int size);
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name);
void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer);

View file

@ -25,7 +25,8 @@ liblinphonetester_la_SOURCES = tester.c \
log_collection_tester.c \
transport_tester.c \
player_tester.c \
dtmf_tester.c
dtmf_tester.c \
accountmanager.c
liblinphonetester_la_LDFLAGS= -no-undefined
liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS)

215
tester/accountmanager.c Normal file
View file

@ -0,0 +1,215 @@
/*
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 "liblinphone_tester.h"
#include "private.h"
struct _Account{
LinphoneAddress *identity;
LinphoneAddress *modified_identity;
char *password;
int created;
int done;
int auth_requested;
};
typedef struct _Account Account;
Account *account_new(LinphoneAddress *identity, const char *unique_id){
char *modified_username;
Account *obj=ms_new0(Account,1);
/* we need to inhibit leak detector because the two LinphoneAddress will remain behond the scope of the test being run */
belle_sip_object_inhibit_leak_detector(TRUE);
obj->identity=linphone_address_clone(identity);
obj->password=sal_get_random_token(8);
obj->modified_identity=linphone_address_clone(identity);
modified_username=ms_strdup_printf("%s_%s",linphone_address_get_username(identity), unique_id);
linphone_address_set_username(obj->modified_identity, modified_username);
ms_free(modified_username);
belle_sip_object_inhibit_leak_detector(FALSE);
return obj;
};
void account_destroy(Account *obj){
linphone_address_unref(obj->identity);
linphone_address_unref(obj->modified_identity);
ms_free(obj->password);
ms_free(obj);
}
struct _AccountManager{
char *unique_id;
MSList *accounts;
};
typedef struct _AccountManager AccountManager;
static AccountManager *the_am=NULL;
AccountManager *account_manager_get(void){
if (the_am==NULL){
the_am=ms_new0(AccountManager,1);
the_am->unique_id=sal_get_random_token(6);
}
return the_am;
}
void account_manager_destroy(void){
if (the_am){
ms_free(the_am->unique_id);
ms_list_free_with_data(the_am->accounts,(void(*)(void*))account_destroy);
ms_free(the_am);
}
the_am=NULL;
}
Account *account_manager_get_account(AccountManager *m, const LinphoneAddress *identity){
MSList *it;
for(it=m->accounts;it!=NULL;it=it->next){
Account *a=(Account*)it->data;
if (linphone_address_weak_equal(a->identity,identity)){
return a;
}
}
return NULL;
}
static void account_created_on_server_cb(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *info){
Account *account=(Account*)linphone_core_get_user_data(lc);
switch(state){
case LinphoneRegistrationOk:
account->created=1;
break;
case LinphoneRegistrationCleared:
account->done=1;
break;
default:
break;
}
}
static void account_created_auth_requested_cb(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
Account *account=(Account*)linphone_core_get_user_data(lc);
account->auth_requested=1;
}
void account_create_on_server(Account *account, const LinphoneProxyConfig *refcfg){
LinphoneCoreVTable vtable={0};
LinphoneCore *lc;
LinphoneAddress *tmp_identity=linphone_address_clone(account->modified_identity);
LinphoneProxyConfig *cfg;
LinphoneAuthInfo *ai;
char *tmp;
LinphoneAddress *server_addr;
vtable.registration_state_changed=account_created_on_server_cb;
vtable.auth_info_requested=account_created_auth_requested_cb;
lc=configure_lc_from(&vtable,NULL,NULL,account);
cfg=linphone_core_create_proxy_config(lc);
linphone_address_set_password(tmp_identity,account->password);
linphone_address_set_header(tmp_identity,"X-Create-Account","yes");
tmp=linphone_address_as_string(tmp_identity);
linphone_proxy_config_set_identity(cfg,tmp);
ms_free(tmp);
linphone_address_unref(tmp_identity);
server_addr=linphone_address_new(linphone_proxy_config_get_server_addr(refcfg));
linphone_address_set_transport(server_addr,LinphoneTransportTcp); /*use tcp for account creation*/
tmp=linphone_address_as_string(server_addr);
linphone_proxy_config_set_server_addr(cfg,tmp);
ms_free(tmp);
linphone_address_unref(server_addr);
linphone_proxy_config_set_expires(cfg,3600);
linphone_core_add_proxy_config(lc,cfg);
if (wait_for_until(lc,NULL,&account->auth_requested,1,10000)==FALSE){
ms_fatal("Account for %s could not be created on server.", linphone_proxy_config_get_identity(refcfg));
}
linphone_proxy_config_stop_refreshing(cfg); /*so that op is destroyed; we need to remove the X-create-account*/
linphone_proxy_config_edit(cfg);
tmp=linphone_address_as_string(account->modified_identity);
linphone_proxy_config_set_identity(cfg,tmp); /*remove the X-Create-Account header*/
ms_free(tmp);
linphone_proxy_config_done(cfg);
ai=linphone_auth_info_new(linphone_address_get_username(account->modified_identity),
NULL,
account->password,NULL,NULL,linphone_address_get_domain(account->modified_identity));
linphone_core_add_auth_info(lc,ai);
linphone_auth_info_destroy(ai);
if (wait_for_until(lc,NULL,&account->created,1,3000)==FALSE){
ms_fatal("Account for %s is not working on server.", linphone_proxy_config_get_identity(refcfg));
}
linphone_core_remove_proxy_config(lc,cfg);
linphone_proxy_config_unref(cfg);
if (wait_for_until(lc,NULL,&account->done,1,3000)==FALSE){
ms_error("Account creation could not clean the registration context.");
}
linphone_core_destroy(lc);
}
LinphoneAddress *account_manager_check_account(AccountManager *m, LinphoneProxyConfig *cfg){
LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
const char *identity=linphone_proxy_config_get_identity(cfg);
LinphoneAddress *id_addr=linphone_address_new(identity);
Account *account=account_manager_get_account(m,id_addr);
LinphoneAuthInfo *ai;
char *tmp;
bool_t create_account=FALSE;
if (!account){
account=account_new(id_addr,m->unique_id);
ms_message("No account for %s exists, going to create one.",identity);
create_account=TRUE;
m->accounts=ms_list_append(m->accounts,account);
}
tmp=linphone_address_as_string(account->modified_identity);
linphone_proxy_config_set_identity(cfg,tmp);
ms_free(tmp);
if (create_account){
account_create_on_server(account,cfg);
}
ai=linphone_auth_info_new(linphone_address_get_username(account->modified_identity),
NULL,
account->password,NULL,NULL,linphone_address_get_domain(account->modified_identity));
linphone_core_add_auth_info(lc,ai);
linphone_auth_info_destroy(ai);
linphone_address_unref(id_addr);
return account->modified_identity;
}
void linphone_core_manager_check_accounts(LinphoneCoreManager *m){
const MSList *it;
AccountManager *am=account_manager_get();
for(it=linphone_core_get_proxy_config_list(m->lc);it!=NULL;it=it->next){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)it->data;
LinphoneAddress *modified_identity=account_manager_check_account(am,cfg);
if (m->identity){
linphone_address_unref(m->identity);
}
m->identity=linphone_address_ref(modified_identity);
}
}

View file

@ -206,9 +206,6 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params));
}
/*linphone_core_invite(caller_mgr->lc,"pauline");*/
did_received_call = wait_for(callee_mgr->lc
,caller_mgr->lc
,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived
@ -641,7 +638,7 @@ static void simple_call_compatibility_mode(void) {
CU_ASSERT_TRUE (wait_for(lc_marie,lc_marie,&stat_marie->number_of_LinphoneRegistrationOk,1));
linphone_core_invite(lc_marie,"pauline");
linphone_core_invite_address(lc_marie,pauline->identity);
CU_ASSERT_TRUE (wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallIncomingReceived,1));
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc_pauline));
@ -674,7 +671,7 @@ static void cancelled_call(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"marie");
LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity);
linphone_call_ref(out_call);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
@ -730,7 +727,7 @@ static void call_failed_because_of_codecs(void) {
disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1);
disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1);
out_call = linphone_core_invite(pauline->lc,"marie");
out_call = linphone_core_invite_address(pauline->lc,marie->identity);
linphone_call_ref(out_call);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
@ -801,7 +798,7 @@ static void cancelled_ringing_call(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"marie");
LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity);
linphone_call_ref(out_call);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
@ -823,7 +820,7 @@ static void early_declined_call(void) {
LinphoneCall* out_call;
linphone_core_set_max_calls(marie->lc,0);
out_call = linphone_core_invite(pauline->lc,"marie");
out_call = linphone_core_invite_address(pauline->lc,marie->identity);
linphone_call_ref(out_call);
/*wait until flexisip transfers the busy...*/
@ -943,7 +940,7 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee
linphone_core_iterate(callee->lc);
}
ms_usleep(20000);
}while(!liblinphone_tester_clock_elapsed(&ts,5000));
}while(!liblinphone_tester_clock_elapsed(&ts,10000));
}
/*make sure encryption mode are preserved*/
@ -980,7 +977,6 @@ static void _call_with_ice_base(LinphoneCoreManager* pauline,LinphoneCoreManager
CU_ASSERT_TRUE(call(pauline,marie));
if (callee_with_ice && caller_with_ice) {
check_ice(pauline,marie,LinphoneIceStateHostConnection);
/*wait for the ICE reINVITE to complete*/
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
@ -1631,7 +1627,7 @@ static void video_call_with_ice_no_matching_audio_codecs(void) {
linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce);
linphone_core_set_stun_server(pauline->lc, "stun.linphone.org");
out_call = linphone_core_invite(marie->lc, "pauline");
out_call = linphone_core_invite_address(marie->lc, pauline->identity);
linphone_call_ref(out_call);
CU_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallOutgoingInit, 1));
@ -2822,7 +2818,7 @@ static void call_established_with_rejected_reinvite_with_error(void) {
static void call_rejected_because_wrong_credentials_with_params(const char* user_agent,bool_t enable_auth_req_cb) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneAuthInfo* good_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(marie->lc)->data));
LinphoneAuthInfo* good_auth_info=linphone_auth_info_clone(linphone_core_find_auth_info(marie->lc,NULL,linphone_address_get_username(marie->identity),NULL));
LinphoneAuthInfo* wrong_auth_info=linphone_auth_info_clone(good_auth_info);
bool_t result=FALSE;
linphone_auth_info_set_passwd(wrong_auth_info,"passecretdutout");
@ -2855,7 +2851,7 @@ static void call_rejected_because_wrong_credentials_with_params(const char* user
/*to make sure unregister will work*/
linphone_core_clear_all_auth_info(marie->lc);
linphone_core_add_auth_info(marie->lc,good_auth_info);
linphone_auth_info_destroy(good_auth_info);
linphone_core_manager_destroy(marie);
}

View file

@ -205,6 +205,15 @@ hashed-passwords=false
# Default value: false
new-auth-on-407=false
# Enable a feature useful for automatic tests, allowing a client
# to create a temporary account in the password database in memory.
# This MUST not be used for production as it is a real security
# hole.
# Default value: false
enable-test-accounts-creation=true
##
## ...
##

View file

@ -278,6 +278,9 @@ void liblinphone_tester_chat_message_msg_state_changed(LinphoneChatMessage *msg,
void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee);
void liblinphone_tester_clock_start(MSTimeSpec *start);
bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms);
void linphone_core_manager_check_accounts(LinphoneCoreManager *m);
void account_manager_destroy(void);
LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data);
#ifdef ANDROID
void cunit_android_trace_handler(int level, const char *fmt, va_list args) ;
#endif

View file

@ -25,8 +25,6 @@
#include "CUnit/CUCurses.h"
#endif
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data);
static test_suite_t **test_suite = NULL;
static int nb_test_suites = 0;
@ -108,7 +106,7 @@ void reset_counters( stats* counters) {
memset(counters,0,sizeof(stats));
}
static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data) {
LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data) {
LinphoneCore* lc;
LpConfig* config = NULL;
char *filepath = NULL;
@ -252,6 +250,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
reset_counters(&mgr->stat);
if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file);
mgr->lc=configure_lc_from(&mgr->v_table, liblinphone_tester_file_prefix, rc_path, mgr);
linphone_core_manager_check_accounts(mgr);
/*CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),proxy_count);*/
if (check_for_proxies && rc_file) /**/
proxy_count=ms_list_size(linphone_core_get_proxy_config_list(mgr->lc));
@ -545,6 +544,7 @@ int liblinphone_tester_run_tests(const char *suite_name, const char *test_name)
}
CU_cleanup_registry();
account_manager_destroy();
return ret;
}