From 9f5f3adfac9e393030fc70b2665f852b26f517b9 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Wed, 11 Feb 2009 17:10:38 +0000 Subject: [PATCH] Wed Jan 21 11:53:25 CST 2009 Pekka Pessi * nua: added check_etsi.c with ETSI test cases git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11840 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- .../sofia-sip/libsofia-sip-ua/nua/Makefile.am | 1 + .../libsofia-sip-ua/nua/check_etsi.c | 271 ++++++++++++++++++ .../sofia-sip/libsofia-sip-ua/nua/check_nua.c | 1 + .../sofia-sip/libsofia-sip-ua/nua/check_nua.h | 1 + libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c | 17 ++ libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h | 3 + 6 files changed, 294 insertions(+) create mode 100644 libs/sofia-sip/libsofia-sip-ua/nua/check_etsi.c diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am index 145150b8d9..a89480a864 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am @@ -45,6 +45,7 @@ COVERAGE_INPUT = $(libnua_la_SOURCES) $(include_sofia_HEADERS) check_nua_SOURCES = check_nua.c check_nua.h \ check_session.c check_register.c \ + check_etsi.c \ test_s2.h test_s2.c check_nua_LDADD = $(nua_libs) @CHECK_LIBS@ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_etsi.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_etsi.c new file mode 100644 index 0000000000..67ba4153d1 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_etsi.c @@ -0,0 +1,271 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * 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 check_session.c + * + * @brief NUA module tests for SIP session handling + * + * @author Pekka Pessi + * + * @copyright (C) 2008 Nokia Corporation. + */ + +#include "config.h" + +#include "check_nua.h" + +#include "test_s2.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* ====================================================================== */ + +static nua_t *nua; +static soa_session_t *soa = NULL; +static struct dialog *d1 = NULL; +static struct dialog *d2 = NULL; + +#define CRLF "\r\n" + +static void etsi_setup(void) +{ + nua = s2_nua_setup("ETSI", + NUTAG_OUTBOUND("no-options-keepalive, no-validate"), + TAG_END()); + + soa = soa_create(NULL, s2->root, NULL); + + fail_if(!soa); + + soa_set_params(soa, + SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF + "m=video 5010 RTP/AVP 34" CRLF), + TAG_END()); + + d1 = su_home_new(sizeof *d1); fail_if(!d1); + d2 = su_home_new(sizeof *d2); fail_if(!d2); +} + +static void etsi_teardown(void) +{ + s2_teardown_started("ETSI"); + + mark_point(); + + nua_shutdown(nua); + fail_unless(s2_check_event(nua_r_shutdown, 200)); + + s2_nua_teardown(); +} + +static void save_sdp_to_soa(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) < 0); +} + +static void process_offer(struct message *message) +{ + save_sdp_to_soa(message); + fail_if(soa_generate_answer(soa, NULL) < 0); +} + +static void +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), + SIPTAG_CONTENT_DISPOSITION_STR("session"), + ta_tags(ta)); + ta_end(ta); +} + +static struct message * +invite_sent_by_nua(nua_handle_t *nh, + tag_type_t tag, tag_value_t value, ...) +{ + 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)); + + return s2_wait_for_request(SIP_METHOD_INVITE); +} + +static void +bye_by_nua(struct dialog *dialog, nua_handle_t *nh, + tag_type_t tag, tag_value_t value, ...) +{ + ta_list ta; + struct message *bye; + + ta_start(ta, tag, value); + nua_bye(nh, ta_tags(ta)); + ta_end(ta); + + bye = s2_wait_for_request(SIP_METHOD_BYE); + fail_if(!bye); + s2_respond_to(bye, dialog, SIP_200_OK, TAG_END()); + s2_free_message(bye); + fail_unless(s2_check_event(nua_r_bye, 200)); + fail_unless(s2_check_callstate(nua_callstate_terminated)); +} + +/* ====================================================================== */ +/* 6 - ETSI cases */ + +/* 6.1 Call Control - Originating Endpoint - Call Establishment */ + +START_TEST(SIP_CC_OE_CE_V_019) +{ + nua_handle_t *nh; + struct message *invite; + + s2_case("6.1.1", "SIP_CC_OE_CE_V_019", + "Ensure that the IUT when an INVITE client transaction " + "is in the Calling state, on receipt of Success (200 OK) " + "responses differing only on the tag in the To header, " + "sends an ACK request with a To header identical to the " + "received one for each received Success (200 OK) responses."); + + nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END()); + + invite = invite_sent_by_nua(nh, TAG_END()); + + process_offer(invite); + + respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); + + 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)); + + respond_with_sdp(invite, d2, SIP_200_OK, TAG_END()); + s2_free_message(invite); + + fail_unless(s2_check_event(nua_i_fork, 200)); + fail_unless(s2_check_callstate(nua_callstate_ready)); + fail_unless(s2_check_request(SIP_METHOD_ACK)); + + bye_by_nua(d1, nh, TAG_END()); + + nua_handle_destroy(nh); +} +END_TEST + + +START_TEST(SIP_CC_OE_CE_TI_008) +{ + nua_handle_t *nh; + struct message *invite; + + s2_case("6.1.2", "SIP_CC_OE_CE_TI_008", + "If an unreliable transport is used, ensure that the IUT, " + "when an INVITE client transaction is in the Completed state, " + "on receipt of final responses that matches the transaction, " + "still answer with an ACK request until timer D set to at " + "least 32 second expires."); + + nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END()); + + invite = invite_sent_by_nua(nh, TAG_END()); + + process_offer(invite); + + respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); + + 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)); + + respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); + fail_unless(s2_check_request(SIP_METHOD_ACK)); + + s2_fast_forward(32); + + respond_with_sdp(invite, d1, SIP_200_OK, TAG_END()); + s2_free_message(invite); + fail_if(s2_check_request_timeout(SIP_METHOD_ACK, 500)); + + bye_by_nua(d1, nh, TAG_END()); + + nua_handle_destroy(nh); +} +END_TEST + +TCase *sip_cc_oe_ce_tcase(void) +{ + TCase *tc = tcase_create("6.1 - ETSI CC OE - Call Establishment"); + tcase_add_checked_fixture(tc, etsi_setup, etsi_teardown); + { + tcase_add_test(tc, SIP_CC_OE_CE_TI_008); + tcase_add_test(tc, SIP_CC_OE_CE_V_019); + } + return tc; +} + +/* ====================================================================== */ + +void check_etsi_cases(Suite *suite) +{ + suite_add_tcase(suite, sip_cc_oe_ce_tcase()); +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c index b46f8a34d1..60e6b0356c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c @@ -111,6 +111,7 @@ int main(int argc, char *argv[]) check_register_cases(suite); check_session_cases(suite); + check_etsi_cases(suite); runner = srunner_create(suite); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h index 0537aebaaa..2eb11d1177 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h @@ -10,6 +10,7 @@ void check_nua_tcase_add_test(TCase *, TFun, char const *name); void check_session_cases(Suite *suite); void check_register_cases(Suite *suite); +void check_etsi_cases(Suite *suite); void check_simple_cases(Suite *suite); #endif diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c index 7c3a0b1fbd..c42e63e4e5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c @@ -358,8 +358,15 @@ s2_next_request(void) struct message * s2_wait_for_request(sip_method_t method, char const *name) +{ + return s2_wait_for_request_timeout(method, name, -1); +} + +struct message * +s2_wait_for_request_timeout(sip_method_t method, char const *name, int timeout) { struct message *m; + int t = timeout; for (;;) { for (m = s2->received; m; m = m->next) { @@ -374,6 +381,8 @@ s2_wait_for_request(sip_method_t method, char const *name) } su_root_step(s2->root, 100); + if (timeout != -1 && ((t -= 100) <= 0)) + break; } return NULL; @@ -387,6 +396,14 @@ s2_check_request(sip_method_t method, char const *name) return m != NULL; } +int +s2_check_request_timeout(sip_method_t method, char const *name, int timeout) +{ + struct message *m = s2_wait_for_request_timeout(method, name, timeout); + s2_free_message(m); + return m != NULL; +} + void s2_save_uas_dialog(struct dialog *d, sip_t *sip) { diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h index c5698ab23b..f93d290f5d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h @@ -144,7 +144,10 @@ 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); +struct message *s2_wait_for_request_timeout(sip_method_t, char const *, + int timeout); int s2_check_request(sip_method_t method, char const *name); +int s2_check_request_timeout(sip_method_t method, char const *, int timeout); int s2_check_substate(struct event *e, enum nua_substate state);