Commit 601cd4f9 authored by Pekka Pessi's avatar Pekka Pessi

test_nua.c: split into smaller tests.

Added files test_nua.h test_nua_api.c test_nua_params.c test_register.c
test_basic_call.c test_call_reject.c test_cancel_bye.c test_call_hold.c
test_session_timer.c test_refer.c test_100rel.c test_simple.c
test_sip_events.c.

darcs-hash:20060821172933-65a35-cefce604828c1b301cab0b99cee19123a621c62a.gz
parent a67cc3de
......@@ -74,7 +74,14 @@ LDADD = libnua.la \
test_nua_LDFLAGS = -static
test_nua_SOURCES = test_nua.c test_proxy.h test_proxy.c \
test_nua_SOURCES = test_nua.c test_nua.h \
test_nua_api.c test_nua_params.c \
test_register.c test_basic_call.c \
test_call_reject.c test_cancel_bye.c \
test_call_hold.c test_session_timer.c \
test_refer.c test_100rel.c \
test_simple.c test_sip_events.c \
test_proxy.h test_proxy.c \
test_nat.h test_nat.c test_nat_tags.c
# ----------------------------------------------------------------------
......
This diff is collapsed.
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 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 test_nua_basic_call.c
* @brief Test basic call.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti Mela@nokia.com>
*
* @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
*/
#include "config.h"
#include "test_nua.h"
#include <sofia-sip/su_tag_class.h>
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
#define __func__ "test_basic_call"
#endif
/* ======================================================================== */
int until_terminated(CONDITION_PARAMS)
{
if (!check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))
return 0;
save_event_in_list(ctx, event, ep, call);
return event == nua_i_state && callstate(tags) == nua_callstate_terminated;
}
/*
X accept_call ep
| |
|-------INVITE------>|
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
|<--------200--------|
|---------ACK------->|
*/
int accept_call(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (callstate(tags)) {
case nua_callstate_received:
RESPOND(ep, call, nh, SIP_180_RINGING, TAG_END());
return 0;
case nua_callstate_early:
RESPOND(ep, call, nh, SIP_200_OK,
TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)),
TAG_END());
return 0;
case nua_callstate_ready:
return 1;
case nua_callstate_terminated:
if (call)
nua_handle_destroy(call->nh), call->nh = NULL;
return 1;
default:
return 0;
}
}
/*
X INVITE
| |
|-------INVITE------>|
|<--------200--------|
|---------ACK------->|
*/
int until_ready(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (callstate(tags)) {
case nua_callstate_ready:
return 1;
case nua_callstate_terminated:
if (call)
nua_handle_destroy(call->nh), call->nh = NULL;
return 1;
default:
return 0;
}
}
/* ======================================================================== */
/* Basic call:
A B
|-------INVITE------>|
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
|<------200 OK-------|
|--------ACK-------->|
| |
|<-------BYE---------|
|-------200 OK------>|
| |
Client transitions:
INIT -(C1)-> CALLING -(C2a)-> PROCEEDING -(C3+C4)-> READY
Server transitions:
INIT -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S4)-> READY
B sends BYE:
READY -(T2)-> TERMINATING -(T3)-> TERMINATED
A receives BYE:
READY -(T1)-> TERMINATED
See @page nua_call_model in nua.docs for more information
*/
int test_basic_call(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
if (print_headings)
printf("TEST NUA-3.1: Basic call\n");
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
TEST_1(!nua_handle_has_active_call(a_call->nh));
TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SOATAG_USER_SDP_STR(a_call->sdp),
TAG_END());
run_ab_until(ctx, -1, until_ready, -1, accept_call);
/* Client transitions:
INIT -(C1)-> CALLING: nua_invite(), nua_i_state
CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state
PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(is_answer_recv(e->data->e_tags));
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
TEST_1(nua_handle_has_active_call(a_call->nh));
TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
/*
Server transitions:
INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state
RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state
EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state
COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
TEST_1(nua_handle_has_active_call(b_call->nh));
TEST_1(!nua_handle_has_call_on_hold(b_call->nh));
BYE(b, b_call, b_call->nh, TAG_END());
run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
/* B transitions:
READY --(T2)--> TERMINATING: nua_bye()
TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
TEST_1(!nua_handle_has_active_call(b_call->nh));
/* A transitions:
READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_bye);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
TEST_1(!nua_handle_has_active_call(a_call->nh));
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-3.1: PASSED\n");
END();
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 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 test_nua.h
* @brief High-level tester framework for Sofia SIP User Agent Engine
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti Mela@nokia.com>
*
* @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
*/
#ifndef TEST_NUA_H
#define TEST_NUA_H
struct context;
#define NUA_MAGIC_T struct context
struct call;
#define NUA_HMAGIC_T struct call
#include "sofia-sip/nua.h"
#include "sofia-sip/sip_status.h"
#include <sofia-sip/sdp.h>
#include <sofia-sip/sip_header.h>
#include <sofia-sip/su_log.h>
#include <sofia-sip/su_tagarg.h>
#include <sofia-sip/su_tag_io.h>
#include <test_proxy.h>
#include <test_nat.h>
#include <sofia-sip/auth_module.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
extern char const name[];
extern int print_headings;
extern int tstflags;
#define TSTFLAGS tstflags
#include <sofia-sip/tstdef.h>
#define TEST_E(a, b) TEST_S(nua_event_name(a), nua_event_name(b))
#define NONE ((void*)-1)
struct endpoint;
typedef
int condition_function(nua_event_t event,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
struct endpoint *ep,
nua_handle_t *nh, struct call *call,
sip_t const *sip,
tagi_t tags[]);
typedef
void printer_function(nua_event_t event,
char const *operation,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
struct endpoint *ep,
nua_handle_t *nh, struct call *call,
sip_t const *sip,
tagi_t tags[]);
struct proxy_transaction;
struct registration_entry;
enum { event_is_extra, event_is_normal, event_is_special };
struct eventlist
{
nua_event_t kind;
struct event *head, **tail;
};
struct event
{
struct event *next, **prev;
struct call *call;
nua_saved_event_t saved_event[1];
nua_event_data_t const *data;
};
struct context
{
su_home_t home[1];
su_root_t *root;
int threading, proxy_tests, expensive;
char const *external_proxy;
struct endpoint {
char name[4];
struct context *ctx; /* Backpointer */
int running;
condition_function *next_condition;
nua_event_t next_event, last_event;
nua_t *nua;
sip_contact_t *contact;
sip_from_t *to;
printer_function *printer;
char const *instance;
/* Per-call stuff */
struct call {
struct call *next;
nua_handle_t *nh;
char const *sdp;
struct eventlist *events;
} call[1], reg[1];
int (*is_special)(nua_event_t e);
/* Normal events are saved here */
struct eventlist events[1];
/* Special events are saved here */
struct eventlist specials[1];
/* State flags for complex scenarios */
union {
struct {
unsigned bit0:1, bit1:1, bit2:1, bit3:1;
unsigned bit4:1, bit5:1, bit6:1, bit7:1;
} b;
unsigned n;
} flags;
} a, b, c;
struct proxy *p;
struct nat *nat;
};
int save_event_in_list(struct context *,
nua_event_t nevent,
struct endpoint *,
struct call *);
void free_events_in_list(struct context *,
struct eventlist *);
#define CONDITION_PARAMS \
nua_event_t event, \
int status, char const *phrase, \
nua_t *nua, struct context *ctx, \
struct endpoint *ep, \
nua_handle_t *nh, struct call *call, \
sip_t const *sip, \
tagi_t tags[]
int save_events(CONDITION_PARAMS);
int until_final_response(CONDITION_PARAMS);
int save_until_final_response(CONDITION_PARAMS);
int save_until_received(CONDITION_PARAMS);
int save_until_special(CONDITION_PARAMS);
int until_terminated(CONDITION_PARAMS);
int until_ready(CONDITION_PARAMS);
int accept_call(CONDITION_PARAMS);
void a_callback(nua_event_t event,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
nua_handle_t *nh, struct call *call,
sip_t const *sip,
tagi_t tags[]);
void b_callback(nua_event_t event,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
nua_handle_t *nh, struct call *call,
sip_t const *sip,
tagi_t tags[]);
void c_callback(nua_event_t event,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
nua_handle_t *nh, struct call *call,
sip_t const *sip,
tagi_t tags[]);
void run_abc_until(struct context *ctx,
nua_event_t a_event, condition_function *a_condition,
nua_event_t b_event, condition_function *b_condition,
nua_event_t c_event, condition_function *c_condition);
void run_ab_until(struct context *ctx,
nua_event_t a_event, condition_function *a_condition,
nua_event_t b_event, condition_function *b_condition);
int run_a_until(struct context *, nua_event_t, condition_function *);
int run_b_until(struct context *, nua_event_t, condition_function *);
int run_c_until(struct context *, nua_event_t, condition_function *);
typedef int operation_f(struct endpoint *ep, struct call *call,
nua_handle_t *nh, tag_type_t tag, tag_value_t value,
...);
operation_f INVITE, ACK, BYE, CANCEL, AUTHENTICATE, UPDATE, INFO, PRACK,
REFER, MESSAGE, OPTIONS, PUBLISH, UNPUBLISH, REGISTER, UNREGISTER,
SUBSCRIBE, UNSUBSCRIBE, NOTIFY, NOTIFIER, TERMINATE, AUTHORIZE;
int RESPOND(struct endpoint *ep,
struct call *call,
nua_handle_t *nh,
int status, char const *phrase,
tag_type_t tag, tag_value_t value,
...);
int DESTROY(struct endpoint *ep,
struct call *call,
nua_handle_t *nh);
struct call *check_handle(struct endpoint *ep,
struct call *call,
nua_handle_t *nh,
int status, char const *phrase);
int is_special(nua_event_t e);
int callstate(tagi_t const *tags);
int is_offer_sent(tagi_t const *tags);
int is_answer_sent(tagi_t const *tags);
int is_offer_recv(tagi_t const *tags);
int is_answer_recv(tagi_t const *tags);
int is_offer_answer_done(tagi_t const *tags);
int audio_activity(tagi_t const *tags);
int video_activity(tagi_t const *tags);
static inline
void eventlist_init(struct eventlist *list)
{
list->tail = &list->head;
}
static inline
void call_init(struct call *call)
{
}
void endpoint_init(struct context *ctx, struct endpoint *e, char id);
int test_nua_api_errors(struct context *ctx);
int test_stack_errors(struct context *ctx);
int test_tag_filter(void);
int test_nua_params(struct context *ctx);
int test_register(struct context *ctx);
int test_connectivity(struct context *ctx);
int test_nat_timeout(struct context *ctx);
int test_unregister(struct context *ctx);
int test_basic_call(struct context *ctx);
int test_reject_a(struct context *ctx);
int test_reject_b(struct context *ctx);
int test_reject_302(struct context *ctx);
int test_reject_401(struct context *ctx);
int test_mime_negotiation(struct context *ctx);
int test_reject_401_aka(struct context *ctx);
int test_call_cancel(struct context *ctx);
int test_call_destroy(struct context *ctx);
int test_early_bye(struct context *ctx);
int test_call_hold(struct context *ctx);
int test_session_timer(struct context *ctx);
int test_refer(struct context *ctx);
int test_100rel(struct context *ctx);
int test_simple(struct context *ctx);
int test_events(struct context *ctx);
#endif
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 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 test_nua_api.c
* @brief NUA API tester.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti Mela@nokia.com>
*
* @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
*/
#include "config.h"
#include "test_nua.h"
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
#define __func__ "test_nua_api_errors"
#endif
/* ------------------------------------------------------------------------ */
/* API tests */
SOFIAPUBVAR su_log_t nua_log[];
int check_set_status(int status, char const *phrase)
{
return status == 200 && strcmp(phrase, sip_200_OK) == 0;
}
int test_nua_api_errors(struct context *ctx)
{
BEGIN();
/* Invoke every API function with invalid arguments */
int level;
int status; char const *phrase;
if (print_headings)
printf("TEST NUA-1.0: test API\n");
/* This is a nasty macro. Test it. */
#define SET_STATUS1(x) ((status = x), status), (phrase = ((void)x))
TEST_1(check_set_status(SET_STATUS1(SIP_200_OK)));
TEST(status, 200); TEST_S(phrase, sip_200_OK);
su_log_init(nua_log);
if (!(tstflags & tst_verbatim))
su_log_set_level(nua_log, 0); /* Log at level 0 by default */
level = nua_log->log_level;
TEST_1(!nua_create(NULL, NULL, NULL, TAG_END()));
TEST_VOID(nua_shutdown(NULL));
TEST_VOID(nua_destroy(NULL));
TEST_VOID(nua_set_params(NULL, TAG_END()));
TEST_VOID(nua_get_params(NULL, TAG_END()));
TEST_1(!nua_default(NULL));
TEST_1(!nua_handle(NULL, NULL, TAG_END()));
TEST_VOID(nua_handle_destroy(NULL));
TEST_VOID(nua_handle_bind(NULL, NULL));
TEST_1(!nua_handle_has_invite(NULL));
TEST_1(!nua_handle_has_subscribe(NULL));
TEST_1(!nua_handle_has_register(NULL));
TEST_1(!nua_handle_has_active_call(NULL));
TEST_1(!nua_handle_has_call_on_hold(NULL));
TEST_1(!nua_handle_has_events(NULL));
TEST_1(!nua_handle_has_registrations(NULL));
TEST_1(!nua_handle_remote(NULL));
TEST_1(!nua_handle_local(NULL));
TEST_S(nua_event_name(-1), "NUA_UNKNOWN");
TEST_VOID(nua_register(NULL, TAG_END()));
TEST_VOID(nua_unregister(NULL, TAG_END()));
TEST_VOID(nua_invite(NULL, TAG_END()));
TEST_VOID(nua_ack(NULL, TAG_END()));
TEST_VOID(nua_prack(NULL, TAG_END()));
TEST_VOID(nua_options(NULL, TAG_END()));
TEST_VOID(nua_publish(NULL, TAG_END()));
TEST_VOID(nua_message(NULL, TAG_END()));
TEST_VOID(nua_chat(NULL, TAG_END()));
TEST_VOID(nua_info(NULL, TAG_END()));
TEST_VOID(nua_subscribe(NULL, TAG_END()));
TEST_VOID(nua_unsubscribe(NULL, TAG_END()));
TEST_VOID(nua_notify(NULL, TAG_END()));
TEST_VOID(nua_notifier(NULL, TAG_END()));
TEST_VOID(nua_terminate(NULL, TAG_END()));
TEST_VOID(nua_refer(NULL, TAG_END()));
TEST_VOID(nua_update(NULL, TAG_END()));
TEST_VOID(nua_bye(NULL, TAG_END()));
TEST_VOID(nua_cancel(NULL, TAG_END()));
TEST_VOID(nua_authenticate(NULL, TAG_END()));
TEST_VOID(nua_redirect(NULL, TAG_END()));
TEST_VOID(nua_respond(NULL, 0, "", TAG_END()));
TEST_1(!nua_handle_home(NULL));
TEST_1(!nua_save_event(NULL, NULL));
TEST_1(!nua_event_data(NULL));
TEST_VOID(nua_destroy_event(NULL));
{
nua_saved_event_t event[1];
memset(event, 0, sizeof event);
TEST_1(!nua_save_event(NULL, event));
TEST_1(!nua_event_data(event));
TEST_VOID(nua_destroy_event(event));
}