Commit 5e36756e authored by Martti Mela's avatar Martti Mela

torture_su_root_osx follows now torture_su_root code

darcs-hash:20061009102630-1b897-0c4d77b945b134fa0fd79d2bff272a416e7961aa.gz
parent 32dc9c45
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005-2006 Nokia Corporation.
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
......@@ -23,545 +23,341 @@
*/
/**@ingroup su_root_ex
* @CFILE torture_su_root_osx.c
*
* @file torture_su_root_osx.c
*
* @brief Test program for OSX Core Foundation Run Loop and su root
* event loop integration.
* Test su_root_register functionality.
*
* @author Martti Mela <Martti.Mela@nokia.com>
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Tue Sep 26 17:16:02 EEST 2006 mela
* @author Martti Mela <Martti.Mela@nokia.com>
*
* Copyright (c) 2006 Nokia Research Center. All rights reserved.
*
* @date Created: Mon Oct 9 13:25:10 EEST 2006 mela
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
struct pinger;
#define SU_ROOT_MAGIC_T struct pinger
#define SU_INTERNAL_P su_root_t *
#define SU_MSG_ARG_T su_sockaddr_t
#define SU_HAVE_OSX_CF_API 1
#include "sofia-sip/su.h"
#include "sofia-sip/su_wait.h"
#include "sofia-sip/su_log.h"
#include "sofia-sip/su_debug.h"
#include "sofia-sip/su_osx_runloop.h"
#if HAVE_FUNC
#define enter (void)SU_DEBUG_9(("torture_su_root_osx: %s: entering\n", __func__))
#define nh_enter (void)SU_DEBUG_9(("torture_su_root_osx %s(%p): entering\n", __func__, nh))
#elif HAVE_FUNCTION
#define enter (void)SU_DEBUG_9(("torture_su_root_osx: %s: entering\n", __FUNCTION__))
#define nh_enter (void)SU_DEBUG_9(("torture_su_root_osx %s(%p): entering\n", __FUNCTION__, nh))
#define __func__ __FUNCTION__
#else
#define enter ((void)0)
#define nh_enter ((void)0)
#define __func__ "torture_su_root_osx"
#endif
struct pinger {
enum { PINGER = 1, PONGER = 2 } const sort;
char const * name;
unsigned running : 1;
unsigned : 0;
su_root_t *root;
su_socket_t s;
su_timer_t *t;
int id;
int rindex;
su_time_t when;
su_sockaddr_t addr;
double rtt_total;
int rtt_n;
};
short opt_family = AF_INET;
short opt_verbatim = 0;
short opt_singlethread = 0;
static su_socket_t udpsocket(void)
{
su_socket_t s;
su_sockaddr_t su = { 0 };
socklen_t sulen = sizeof(su);
char nbuf[64];
enter;
char const *name = "torture_su_root_osx";
su.su_family = opt_family;
#include <stdio.h>
#include <string.h>
su_getlocalip(&su);
#define TSTFLAGS rt->rt_flags
#include <sofia-sip/tstdef.h>
s = su_socket(su.su_family, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET) {
su_perror("udpsocket: socket");
exit(1);
}
typedef struct root_test_s root_test_t;
typedef struct test_ep_s test_ep_t;
if (bind(s, &su.su_sa, su_sockaddr_size(&su)) == SOCKET_ERROR) {
su_perror("udpsocket: bind");
exit(1);
}
#define SU_ROOT_MAGIC_T root_test_t
#define SU_WAKEUP_ARG_T test_ep_t
if (getsockname(s, &su.su_sa, &sulen) == SOCKET_ERROR) {
su_perror("udpsocket: getsockname");
exit(1);
}
#include <sofia-sip/su_osx_runloop.h>
#include <sofia-sip/su_wait.h>
#include <sofia-sip/su_alloc.h>
if (opt_verbatim)
printf("udpsocket: using address [%s]:%u\n",
inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)),
ntohs(su.su_sin.sin_port));
typedef struct test_ep_s {
int i;
int s;
su_wait_t wait[1];
int registered;
socklen_t addrlen;
su_sockaddr_t addr[1];
} test_ep_at[1];
return s;
}
struct root_test_s {
su_home_t rt_home[1];
int rt_flags;
static char *snow(su_time_t now)
{
static char buf[24];
su_root_t *rt_root;
short rt_family;
int rt_status;
int rt_received;
int rt_wakeup;
enter;
su_clone_r rt_clone;
su_time_print(buf, sizeof(buf), &now);
unsigned rt_fail_init:1;
unsigned rt_fail_deinit:1;
unsigned rt_success_init:1;
unsigned rt_success_deinit:1;
return buf;
}
test_ep_at rt_ep[5];
};
void
do_ping(struct pinger *p, su_timer_t *t, void *p0)
/** Test root initialization */
int init_test(root_test_t *rt)
{
char buf[1024];
su_sockaddr_t su[1] = {{ 0 }};
int i;
enter;
BEGIN();
printf("%s: pinger p == %x\n", __func__, (unsigned int) p);
su_init();
assert(p == su_root_magic(su_timer_root(t)));
assert(p->sort == PINGER);
su->su_family = rt->rt_family;
p->when = su_now();
TEST_1(rt->rt_root = su_root_osx_runloop_create(rt));
snprintf(buf, sizeof(buf), "Ping %d at %s", p->id++, snow(p->when));
if (sendto(p->s, buf, strlen(buf), 0,
&p->addr.su_sa, su_sockaddr_size(&p->addr)) == -1) {
su_perror("do_ping: send");
for (i = 0; i < 5; i++) {
test_ep_t *ep = rt->rt_ep[i];
ep->i = i;
ep->addrlen = su_sockaddr_size(su);
TEST_1((ep->s = su_socket(su->su_family, SOCK_DGRAM, 0)) != -1);
TEST_1(bind(ep->s, &su->su_sa, ep->addrlen) != -1);
TEST_1(su_wait_create(ep->wait, ep->s, SU_WAIT_IN|SU_WAIT_ERR) != -1);
TEST_1(getsockname(ep->s, &ep->addr->su_sa, &ep->addrlen) != -1);
if (SU_HAS_INADDR_ANY(ep->addr)) {
inet_pton(su->su_family,
su->su_family == AF_INET ? "127.0.0.1" : "::1",
SU_ADDR(ep->addr));
}
}
if (opt_verbatim) {
puts(buf);
fflush(stdout);
}
END();
}
int
do_rtt(struct pinger *p, su_wait_t *w, void *p0)
static int deinit_test(root_test_t *rt)
{
su_sockaddr_t su;
struct sockaddr * const susa = &su.su_sa;
socklen_t susize[] = { sizeof(su)};
char buf[1024];
char nbuf[1024];
int n;
su_time_t now = su_now();
double rtt;
BEGIN();
enter;
TEST_VOID(su_root_destroy(rt->rt_root)); rt->rt_root = NULL;
TEST_VOID(su_root_destroy(NULL));
assert(p0 == p);
assert(p->sort == PINGER);
su_deinit();
rtt = su_time_diff(now, p->when);
p->rtt_total += rtt, p->rtt_n++;
su_wait_events(w, p->s);
END();
}
n = recvfrom(p->s, buf, sizeof(buf) - 1, 0, susa, susize);
if (n < 0) {
su_perror("do_rtt: recvfrom");
return 0;
}
buf[n] = 0;
int wakeup(root_test_t *rt,
su_wait_t *w,
test_ep_t *ep)
{
char buffer[64];
int n, error;
su_wait_events(w, ep->s);
if (opt_verbatim)
printf("do_rtt: %d bytes from [%s]:%u: \"%s\", rtt = %lg ms\n",
n, inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)),
ntohs(su.su_sin.sin_port), buf, rtt / 1000);
n = recv(ep->s, buffer, sizeof(buffer), 0);
error = su_errno();
if (n < 0)
fprintf(stderr, "%s: %s\n", "recv", su_strerror(error));
do_ping(p, p->t, NULL);
TEST_1(n > 0);
rt->rt_received = ep->i;
return 0;
}
void
do_pong(struct pinger *p, su_timer_t *t, void *p0)
static int wakeup0(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
{
char buf[1024];
enter;
rt->rt_wakeup = 0;
return wakeup(rt, w, ep);
}
static int wakeup1(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
{
rt->rt_wakeup = 1;
return wakeup(rt, w, ep);
}
static int wakeup2(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
{
rt->rt_wakeup = 2;
return wakeup(rt, w, ep);
}
static int wakeup3(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
{
rt->rt_wakeup = 3;
return wakeup(rt, w, ep);
}
static int wakeup4(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
{
rt->rt_wakeup = 4;
return wakeup(rt, w, ep);
}
assert(p == su_root_magic(su_timer_root(t)));
assert(p->sort == PONGER);
static
su_wakeup_f wakeups[5] = { wakeup0, wakeup1, wakeup2, wakeup3, wakeup4 };
p->id = 0;
snprintf(buf, sizeof(buf), "Pong at %s", snow(su_now()));
if (sendto(p->s, buf, strlen(buf), 0,
&p->addr.su_sa, su_sockaddr_size(&p->addr)) == -1) {
su_perror("do_pong: send");
}
static
void test_run(root_test_t *rt)
{
rt->rt_received = -1;
if (opt_verbatim) {
puts(buf);
fflush(stdout);
while (rt->rt_received == -1) {
su_root_step(rt->rt_root, 200);
}
}
int
do_recv(struct pinger *p, su_wait_t *w, void *p0)
static int register_test(root_test_t *rt)
{
su_sockaddr_t su;
socklen_t susize[] = { sizeof(su)};
char buf[1024];
char nbuf[1024];
int n;
su_time_t now = su_now();
enter;
int i;
int s;
char msg[3] = "foo";
assert(p0 == p);
assert(p->sort == PONGER);
BEGIN();
su_wait_events(w, p->s);
TEST_1((s = su_socket(rt->rt_family, SOCK_DGRAM, 0)) != -1);
n = recvfrom(p->s, buf, sizeof(buf) - 1, 0, &su.su_sa, susize);
if (n < 0) {
su_perror("do_recv: recvfrom");
return 0;
for (i = 0; i < 5; i++) {
rt->rt_ep[i]->registered =
su_root_register(rt->rt_root, rt->rt_ep[i]->wait,
wakeups[i], rt->rt_ep[i], 0);
TEST(rt->rt_ep[i]->registered, i + 1 + SU_HAVE_PTHREADS);
}
buf[n] = 0;
if (opt_verbatim)
printf("do_recv: %d bytes from [%s]:%u: \"%s\" at %s\n",
n, inet_ntop(su.su_family, SU_ADDR(&su), nbuf, sizeof(nbuf)),
ntohs(su.su_sin.sin_port), buf, snow(now));
fflush(stdout);
#if 0
if (p->id)
puts("do_recv: already a pending reply");
if (su_timer_set(p->t, do_pong, p) < 0) {
fprintf(stderr, "do_recv: su_timer_set() error\n");
return 0;
for (i = 0; i < 5; i++) {
test_ep_t *ep = rt->rt_ep[i];
TEST(sendto(s, msg, sizeof(msg), 0, &ep->addr->su_sa, ep->addrlen),
sizeof(msg));
test_run(rt);
TEST(rt->rt_received, i);
TEST(rt->rt_wakeup, i);
}
p->id = 1;
#else
do_pong(p, p->t, NULL);
#endif
return 0;
}
void
do_exit(struct pinger *x, su_timer_t *t, void *x0)
{
enter;
if (opt_verbatim)
printf("do_exit at %s\n", snow(su_now()));
su_root_break(su_timer_root(t));
}
int
do_init(su_root_t *root, struct pinger *p)
{
su_wait_t w;
su_socket_t s;
long interval;
su_timer_t *t;
su_wakeup_f f;
int index, index0;
enter;
switch (p->sort) {
case PINGER: f = do_rtt; interval = 200; break;
case PONGER: f = do_recv; interval = 40; break;
default:
return SU_FAILURE;
for (i = 0; i < 5; i++) {
TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait,
wakeups[i], rt->rt_ep[i]),
rt->rt_ep[i]->registered);
}
/* Create a sockets, */
s = udpsocket();
if (su_wait_create(&w, s, SU_WAIT_IN) == SOCKET_ERROR)
su_perror("su_wait_create"), exit(1);
/* CFSocketEnableCallbacks(s, map_poll_revent_to_cf_event(su_wait_events(&w, s))); */
p->s = s;
p->t = t = su_timer_create(su_root_task(root), interval);
if (t == NULL) {
su_perror("su_timer_create");
return SU_FAILURE;
for (i = 0; i < 5; i++) {
rt->rt_ep[i]->registered =
su_root_register(rt->rt_root, rt->rt_ep[i]->wait,
wakeups[i], rt->rt_ep[i], 1);
TEST_1(rt->rt_ep[i]->registered > 0);
}
index0 = su_root_register(root, &w, f, p, 0);
if (index0 == SOCKET_ERROR) {
su_perror("su_root_register");
return SU_FAILURE;
for (i = 0; i < 5; i++) {
test_ep_t *ep = rt->rt_ep[i];
TEST(sendto(s, msg, sizeof(msg), 0, &ep->addr->su_sa, ep->addrlen),
sizeof(msg));
test_run(rt);
TEST(rt->rt_received, i);
TEST(rt->rt_wakeup, i);
}
index = su_root_register(root, &w, f, p, 0);
if (index == SOCKET_ERROR) {
su_perror("su_root_register");
return SU_FAILURE;
for (i = 0; i < 5; i++) {
TEST(su_root_deregister(rt->rt_root, rt->rt_ep[i]->registered),
rt->rt_ep[i]->registered);
}
su_root_deregister(root, index0);
p->rindex = index;
return 0;
}
void
do_destroy(su_root_t *root, struct pinger *p)
{
enter;
for (i = 0; i < 5; i++) {
test_ep_t *ep = rt->rt_ep[i];
TEST_1(su_wait_create(ep->wait, ep->s, SU_WAIT_IN|SU_WAIT_ERR) != -1);
ep->registered =
su_root_register(rt->rt_root, ep->wait,
wakeups[i], ep, 1);
TEST_1(ep->registered > 0);
}
if (opt_verbatim)
printf("do_destroy %s at %s\n", p->name, snow(su_now()));
for (i = 0; i < 5; i++) {
test_ep_t *ep = rt->rt_ep[i];
TEST(sendto(s, msg, sizeof(msg), 0, &ep->addr->su_sa, ep->addrlen),
sizeof(msg));
test_run(rt);
TEST(rt->rt_received, i);
TEST(rt->rt_wakeup, i);
}
su_root_deregister(root, p->rindex);
su_timer_destroy(p->t), p->t = NULL;
for (i = 0; i < 5; i++) {
TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait,
wakeups[i], rt->rt_ep[i]),
rt->rt_ep[i]->registered);
}
p->running = 0;
END();
}
void
start_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg)
int fail_init(su_root_t *root, root_test_t *rt)
{
enter;
if (!p->running)
return;
if (opt_verbatim)
printf("start_ping: %s\n", p->name);
p->addr = *arg;
p->id = 1;
su_timer_set_at(p->t, do_ping, p, su_now());
rt->rt_fail_init = 1;
return -1;
}
void
start_pong(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg)
void fail_deinit(su_root_t *root, root_test_t *rt)
{
su_msg_r reply;
enter;
if (!p->running)
return;
if (opt_verbatim)
printf("start_pong: %s\n", p->name);
p->addr = *arg;
if (su_msg_reply(reply, msg, start_ping, sizeof(p->addr)) == 0) {
socklen_t sinsize[1] = { sizeof(p->addr) };
if (getsockname(p->s, (struct sockaddr*)su_msg_data(reply), sinsize)
== SOCKET_ERROR)
su_perror("start_pong: getsockname()"), exit(1);
su_msg_send(reply);
}
else {
fprintf(stderr, "su_msg_create failed!\n");
}
rt->rt_fail_deinit = 1;
}
void
init_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg)
int success_init(su_root_t *root, root_test_t *rt)
{
su_msg_r reply;
enter;
if (opt_verbatim)
printf("init_ping: %s\n", p->name);
if (su_msg_reply(reply, msg, start_pong, sizeof(p->addr)) == 0) {
socklen_t sinsize[1] = { sizeof(p->addr) };
if (getsockname(p->s, (struct sockaddr*)su_msg_data(reply), sinsize)
== SOCKET_ERROR)
su_perror("start_pong: getsockname()"), exit(1);
su_msg_send(reply);
}
else {
fprintf(stderr, "su_msg_reply failed!\n");
}
rt->rt_success_init = 1;
return 0;
}
static
RETSIGTYPE term(int n)
void success_deinit(su_root_t *root, root_test_t *rt)
{