Commit 5cc7b069 authored by Pekka Pessi's avatar Pekka Pessi
Browse files

tests: added 2nd check-based test suite for nua

darcs-hash:20080506175321-db55f-ed774b60e6c4ef29b9825706c69e976b18b28830.gz
parent 069b3ca2
......@@ -16,20 +16,27 @@ AM_CFLAGS += @CHECK_CFLAGS@
if HAVE_CHECK
TESTS += check_sofia
tests_PROGRAMS += check_sofia
TESTS += check2_sofia check_sofia
tests_PROGRAMS += check2_sofia check_sofia
check2_sofia_SOURCES = \
check2_sofia.c check2_sofia.h s2tester.h s2tester.c suite2_for_nua.c
check2_sofia_LDADD = \
${sofiabuilddir}/libsofia-sip-ua.la \
@CHECK_LIBS@
check_sofia_SOURCES = check_sofia.c check_sofia.h \
suite_for_nua.c
CHECKLIBS = ${sofiabuilddir}/nua/libtestnua.la \
NUA_TEST_LIBS := ${sofiabuilddir}/nua/libtestnua.la \
${sofiabuilddir}/nua/libtestproxy.la \
${sofiabuilddir}/nua/libtestnat.la
$(CHECKLIBS):
$(NUA_TEST_LIBS):
cd ${sofiabuilddir}/nua && make checklib
check_sofia_LDADD = \
$(CHECKLIBS) ${sofiabuilddir}/libsofia-sip-ua.la \
$(NUA_TEST_LIBS) ${sofiabuilddir}/libsofia-sip-ua.la \
@CHECK_LIBS@
endif
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE check2_sofia.c
*
* @brief Check-driven tester for Sofia SIP User Agent library
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @copyright (C) 2007 Nokia Corporation.
*/
#include "config.h"
#include "check2_sofia.h"
#include <stdlib.h>
int main(int argc, char *argv[])
{
int failed = 0;
Suite *suite;
SRunner *runner;
suite = suite2_for_nua();
runner = srunner_create(suite);
if (argv[1]) {
srunner_set_xml(runner, argv[1]);
}
srunner_run_all(runner, CK_VERBOSE);
failed = srunner_ntests_failed(runner);
srunner_free(runner);
exit(failed ? EXIT_FAILURE : EXIT_SUCCESS);
}
#ifndef CHECK2_SOFIA_H
#include <check.h>
Suite *suite2_for_nua(void);
#endif
This diff is collapsed.
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2008 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef S2TESTER_H
#define S2TESTER_H
#define TP_STACK_T struct tester
#define SU_ROOT_MAGIC_T struct tester
#include <check.h>
#include <sofia-sip/su_wait.h>
#include <sofia-sip/sip.h>
#include <sofia-sip/tport.h>
#include <sofia-sip/nua.h>
struct tester
{
su_home_t home[1];
su_root_t *root;
msg_mclass_t const *mclass;
int flags;
char const *hostname;
tport_t *master;
sip_to_t *local;
sip_contact_t *contact;
struct {
sip_contact_t *contact;
tport_t *tport;
} udp, tcp, tls;
nua_t *nua;
struct message {
struct message *next, **prev;
msg_t *msg;
sip_t *sip;
tport_t *tport;
su_time_t when;
} *received;
struct event {
struct event *next, **prev;
nua_saved_event_t event[1];
nua_handle_t *nh;
nua_event_data_t const *data;
su_time_t when;
} *events;
struct {
sip_to_t *aor;
sip_contact_t *contact;
tport_t *tport;
} registration[1];
unsigned long tid;
/* Settings */
int server_uses_rport;
};
struct dialog
{
su_home_t home[1];
sip_from_t *local;
sip_to_t *remote;
sip_call_id_t *call_id;
uint32_t lseq, rseq;
sip_contact_t *target;
sip_route_t *route;
sip_contact_t *contact;
};
extern struct tester *s2tester;
extern tp_stack_class_t const s2_stack[1];
void s2_case(char const *tag,
char const *title,
char const *description);
struct event *s2_remove_event(struct event *);
void s2_free_event(struct event *);
void s2_flush_events(void);
struct event *s2_next_event(void);
struct event *s2_wait_for_event(nua_event_t event, int status);
int s2_check_event(nua_event_t event, int status);
int s2_check_callstate(enum nua_callstate state);
struct message *s2_remove_message(struct message *m);
void s2_free_message(struct message *m);
void s2_flush_messages(void);
struct message *s2_next_response(void);
struct message *s2_wait_for_response(int status, sip_method_t , char const *);
int s2_check_response(int status, sip_method_t method, char const *name);
struct message *s2_next_request(void);
struct message *s2_wait_for_request(sip_method_t method, char const *name);
int s2_check_request(sip_method_t method, char const *name);
#define SIP_METHOD_UNKNOWN sip_method_unknown, NULL
struct message *s2_respond_to(struct message *m, struct dialog *d,
int status, char const *phrase,
tag_type_t tag, tag_value_t value, ...);
int s2_request_to(struct dialog *d,
sip_method_t method, char const *name,
tport_t *tport,
tag_type_t tag, tag_value_t value, ...);
int s2_update_dialog(struct dialog *d, struct message *response);
int s2_save_register(struct message *m);
void s2_flush_all(void);
void s2_setup(char const *hostname);
void s2_setup_logs(int level);
void s2_setup_tport(char const * const *protocols,
tag_type_t tag, tag_value_t value, ...);
void s2_setup_nua(tag_type_t tag, tag_value_t value, ...);
void s2_teardown(void);
#endif
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE suite2_for_nua.c
*
* @brief Check-driven tester for Sofia SIP User Agent library
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @copyright (C) 2007 Nokia Corporation.
*/
#include "config.h"
#include "check_sofia.h"
#include "s2tester.h"
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sip_header.h>
#include <sofia-sip/soa.h>
#include <sofia-sip/su_tagarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static nua_t *nua;
int s2_verbose = 0;
static void s2_ua_setup(void)
{
s2_setup(NULL);
if (s2_verbose) {
s2_setup_logs(7);
s2_setup_tport(NULL, TPTAG_LOG(1), TAG_END());
}
else {
s2_setup_logs(0);
s2_setup_tport(NULL, TPTAG_LOG(0), TAG_END());
}
assert(s2tester->contact);
s2_setup_nua(SIPTAG_FROM_STR("Alice <sip:alice@example.org>"),
NUTAG_PROXY((url_string_t *)s2tester->contact->m_url),
TAG_END());
nua = s2tester->nua;
}
void s2_ua_teardown(void)
{
s2_ua_teardown();
}
/* ====================================================================== */
nua_handle_t *rnh;
void s2_register_setup(void)
{
struct message *m;
s2_case("0.1", "Registration Setup", "");
rnh = nua_handle(nua, NULL, TAG_END());
nua_register(rnh, TAG_END());
m = s2_wait_for_request(SIP_METHOD_REGISTER);
fail_if(m == NULL, NULL);
s2_save_register(m);
s2_respond_to(m, NULL,
SIP_200_OK,
SIPTAG_CONTACT(s2tester->registration->contact),
TAG_END());
s2_free_message(m);
fail_if(s2tester->registration->contact == NULL);
fail_unless(s2_check_event(nua_r_register, 200));
}
void s2_register_teardown(void)
{
if (rnh) {
struct message *m;
s2_case("0.2", "Registration Teardown", "");
nua_unregister(rnh, TAG_END());
fail_if((m = s2_wait_for_request(SIP_METHOD_REGISTER)) == NULL);
s2_save_register(m);
s2_respond_to(m, NULL,
SIP_200_OK,
SIPTAG_CONTACT(s2tester->registration->contact),
TAG_END());
fail_unless(s2tester->registration->contact == NULL);
s2_free_message(m);
fail_unless(s2_check_event(nua_r_unregister, 200));
nua_handle_destroy(rnh), rnh = NULL;
}
}
START_TEST(basic_register)
{
nua_handle_t *nh = nua_handle(nua, NULL, TAG_END());
struct message *m;
s2_case("1.5", "Failed Register", "REGISTER returned 403 response");
nua_register(nh, TAG_END());
fail_unless((m = s2_wait_for_request(SIP_METHOD_REGISTER)) != NULL, NULL);
s2_respond_to(m, NULL,
SIP_403_FORBIDDEN,
TAG_END());
s2_free_message(m);
fail_unless(s2_check_event(nua_r_register, 403));
nua_register(nh, TAG_END());
fail_unless((m = s2_wait_for_request(SIP_METHOD_REGISTER)) != NULL, NULL);
s2_respond_to(m, NULL,
SIP_403_FORBIDDEN,
TAG_END());
s2_free_message(m);
fail_unless(s2_check_event(nua_r_register, 403));
} END_TEST
/* ====================================================================== */
/* Call cases */
static soa_session_t *soa = NULL;
static struct dialog *dialog = NULL;
void s2_call_setup(void)
{
s2_ua_setup();
soa = soa_create(NULL, s2tester->root, NULL);
fail_if(!soa);
soa_set_params(soa,
SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0\r\n"
"m=video 5010 RTP/AVP 34\r\n"),
TAG_END());
dialog = su_home_new(sizeof *dialog); fail_if(!dialog);
s2_register_setup();
}
void s2_call_teardown(void)
{
mark_point();
s2_register_teardown();
nua_shutdown(nua);
fail_unless(s2_check_event(nua_r_shutdown, 200));
s2_ua_teardown();
}
void s2_save_sdp(struct message *message)
{
sip_payload_t *pl;
char const *body;
isize_t bodylen;
fail_if(!message);
fail_if(!message->sip->sip_content_length);
fail_if(!message->sip->sip_content_type);
fail_if(strcmp(message->sip->sip_content_type->c_type,
"application/sdp"));
fail_if(!message->sip->sip_payload);
pl = message->sip->sip_payload;
body = pl->pl_data, bodylen = pl->pl_len;
fail_if(soa_set_remote_sdp(soa, NULL, body, (issize_t)bodylen) != 1);
}
void s2_process_offer(struct message *message)
{
s2_save_sdp(message);
fail_if(soa_generate_answer(soa, NULL) < 0);
}
void s2_process_answer(struct message *message)
{
s2_save_sdp(message);
fail_if(soa_process_answer(soa, NULL) < 0);
}
void s2_respond_with_sdp(struct message *request,
struct dialog *dialog,
int status, char const *phrase,
tag_type_t tag, tag_value_t value, ...)
{
ta_list ta;
char const *body;
isize_t bodylen;
fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1);
ta_start(ta, tag, value);
s2_respond_to(request, dialog, status, phrase,
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(body),
ta_tags(ta));
ta_end(ta);
}
void s2_request_with_sdp(struct dialog *dialog,
sip_method_t method, char const *name,
tport_t *tport,
tag_type_t tag, tag_value_t value, ...)
{
ta_list ta;
char const *body;
isize_t bodylen;
fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1);
ta_start(ta, tag, value);
fail_if(
s2_request_to(dialog, method, name, tport,
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(body),
ta_tags(ta)));
ta_end(ta);
}
void
s2_invite_by_nua(nua_handle_t *nh,
tag_type_t tag, tag_value_t value, ...)
{
struct message *invite;
ta_list ta;
ta_start(ta, tag, value);
nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"),
ta_tags(ta));
ta_end(ta);
fail_unless(s2_check_callstate(nua_callstate_calling));
invite = s2_wait_for_request(SIP_METHOD_INVITE);
s2_process_offer(invite);
s2_respond_with_sdp(
invite, dialog, SIP_180_RINGING,
SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"),
TAG_END());
fail_unless(s2_check_event(nua_r_invite, 180));
fail_unless(s2_check_callstate(nua_callstate_proceeding));
s2_respond_with_sdp(
invite, dialog, SIP_200_OK,
SIPTAG_CONTENT_DISPOSITION_STR("session"),
TAG_END());
s2_free_message(invite);
fail_unless(s2_check_event(nua_r_invite, 200));
fail_unless(s2_check_callstate(nua_callstate_ready));
fail_unless(s2_check_request(SIP_METHOD_ACK));
}
nua_handle_t *
s2_invite_to_nua(void)
{
struct event *invite;
struct message *response;
nua_handle_t *nh;
sip_cseq_t cseq[1];
//s2_setup_logs(7);
//tport_set_params(s2tester->master, TPTAG_LOG(1), TAG_END());
soa_generate_offer(soa, 1, NULL);
s2_request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END());
invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL);
fail_unless(s2_check_callstate(nua_callstate_received));
nh = invite->nh;
fail_if(!nh);
sip_cseq_init(cseq);
cseq->cs_method = sip_method_ack;
cseq->cs_method_name = "ACK";
cseq->cs_seq = sip_object(invite->data->e_msg)->sip_cseq->cs_seq;
s2_free_event(invite);
response = s2_wait_for_response(100, SIP_METHOD_INVITE);
fail_if(!response);
nua_respond(nh, SIP_180_RINGING,
SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"),
TAG_END());
fail_unless(s2_check_callstate(nua_callstate_early));
response = s2_wait_for_response(180, SIP_METHOD_INVITE);
fail_if(!response);
s2_update_dialog(dialog, response);
s2_process_answer(response);
s2_free_message(response);
nua_respond(nh, SIP_200_OK, TAG_END());
fail_unless(s2_check_callstate(nua_callstate_completed));
response = s2_wait_for_response(200, SIP_METHOD_INVITE);
fail_if(!response);
s2_update_dialog(dialog, response);
s2_free_message(response);
fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL,
SIPTAG_CSEQ(cseq), TAG_END()));
fail_unless(s2_check_event(nua_i_ack, 200));
fail_unless(s2_check_callstate(nua_callstate_ready));
return nh;
}
void
s2_bye_by_nua(nua_handle_t *nh,
tag_type_t tag, tag_value_t value, ...)