torture_su_root_osx.c 7.89 KB
Newer Older
1 2 3
/*
 * This file is part of the Sofia-SIP package
 *
4
 * Copyright (C) 2006 Nokia Corporation.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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
 *
 */

Pekka Pessi's avatar
Pekka Pessi committed
25
/**@internal
26
 * @file torture_su_root_osx.c
27
 *
28
 * Test su_root_register functionality.
29 30
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
31 32 33 34 35
 * @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
36 37 38 39
 */

#include "config.h"

40
char const *name = "torture_su_root_osx";
41

42 43
#include <stdio.h>
#include <string.h>
44
#include <stdlib.h>
45

46 47
#define TSTFLAGS rt->rt_flags
#include <sofia-sip/tstdef.h>
48

49 50
typedef struct root_test_s root_test_t;
typedef struct test_ep_s   test_ep_t;
51

52 53
#define SU_ROOT_MAGIC_T  root_test_t
#define SU_WAKEUP_ARG_T  test_ep_t
54

55 56 57
#include <sofia-sip/su_osx_runloop.h>
#include <sofia-sip/su_wait.h>
#include <sofia-sip/su_alloc.h>
58

59 60 61 62 63 64 65 66
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];
67

68 69 70
struct root_test_s {
  su_home_t  rt_home[1];
  int        rt_flags;
71

72 73 74 75 76
  su_root_t *rt_root;
  short      rt_family;
  int        rt_status;
  int        rt_received;
  int        rt_wakeup;
77

78
  su_clone_r rt_clone;
Martti Mela's avatar
Martti Mela committed
79

80 81 82 83
  unsigned   rt_fail_init:1;
  unsigned   rt_fail_deinit:1;
  unsigned   rt_success_init:1;
  unsigned   rt_success_deinit:1;
84

85 86
  test_ep_at rt_ep[5];
};
87

88 89
/** Test root initialization */
int init_test(root_test_t *rt)
90
{
91 92
  su_sockaddr_t su[1] = {{ 0 }};
  int i;
93

94
  BEGIN();
Martti Mela's avatar
Martti Mela committed
95

96
  su_init();
Martti Mela's avatar
Martti Mela committed
97

98
  su->su_family = rt->rt_family;
99

100
  TEST_1(rt->rt_root = su_root_osx_runloop_create(rt));
101

102 103 104 105 106 107 108 109 110 111 112 113 114
  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));
    }
115 116
  }

117
  END();
118 119
}

120
static int deinit_test(root_test_t *rt)
121
{
122
  BEGIN();
123

124 125
  TEST_VOID(su_root_destroy(rt->rt_root)); rt->rt_root = NULL;
  TEST_VOID(su_root_destroy(NULL));
Martti Mela's avatar
Martti Mela committed
126

127
  su_deinit();
128

129 130
  END();
}
131

132 133 134 135 136 137 138 139
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);
140

141 142 143 144 145
  n = recv(ep->s, buffer, sizeof(buffer), 0);
  error = su_errno();
 
  if (n < 0)
    fprintf(stderr, "%s: %s\n", "recv", su_strerror(error));
146

147
  TEST_1(n > 0);
148

149 150
  rt->rt_received = ep->i;
	   
151 152 153
  return 0;
}

154
static int wakeup0(root_test_t *rt, su_wait_t *w, test_ep_t *ep)
155
{
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
  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);
}
Martti Mela's avatar
Martti Mela committed
179

180 181
static
su_wakeup_f wakeups[5] = { wakeup0, wakeup1, wakeup2, wakeup3, wakeup4 };
182 183


184 185 186 187
static
void test_run(root_test_t *rt)
{
  rt->rt_received = -1;
188

189 190
  while (rt->rt_received == -1) {
    su_root_step(rt->rt_root, 200);
191 192 193
  }
}

194
static int register_test(root_test_t *rt)
195
{
196 197 198
  int i;
  int s;
  char msg[3] = "foo";
Martti Mela's avatar
Martti Mela committed
199

200
  BEGIN();
201

202
  TEST_1((s = su_socket(rt->rt_family, SOCK_DGRAM, 0)) != -1);
203

204 205 206 207 208
  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);
209 210
  }

211 212
  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
213
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), 
214 215 216 217
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
218 219
  }

220 221 222 223
  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);
224 225 226
  }


227 228 229 230 231
  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);
232 233
  }

234 235
  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
236
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), 
237 238 239 240
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
241 242
  }

243 244 245
  for (i = 0; i < 5; i++) {
    TEST(su_root_deregister(rt->rt_root, rt->rt_ep[i]->registered), 
	 rt->rt_ep[i]->registered);
246 247
  }

248 249 250 251 252 253 254 255
  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);
  }
Martti Mela's avatar
Martti Mela committed
256

257 258
  for (i = 0; i < 5; i++) {
    test_ep_t *ep = rt->rt_ep[i];
259
    TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), 
260 261 262 263 264
	 sizeof(msg));
    test_run(rt);
    TEST(rt->rt_received, i);
    TEST(rt->rt_wakeup, i);
  }
Martti Mela's avatar
Martti Mela committed
265

266 267 268 269 270
  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);
  }
Martti Mela's avatar
Martti Mela committed
271

272
  END();
273 274
}

275
int fail_init(su_root_t *root, root_test_t *rt)
276
{
277 278
  rt->rt_fail_init = 1;
  return -1;
279 280
}

281
void fail_deinit(su_root_t *root, root_test_t *rt)
282
{
283
  rt->rt_fail_deinit = 1;
284 285
}

286
int success_init(su_root_t *root, root_test_t *rt)
287
{
288 289
  rt->rt_success_init = 1;
  return 0;
290 291
}

292
void success_deinit(su_root_t *root, root_test_t *rt)
293
{
294
  rt->rt_success_deinit = 1;
295 296
}

297
static int clone_test(root_test_t rt[1])
298
{
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
  BEGIN();

  rt->rt_fail_init = 0;
  rt->rt_fail_deinit = 0;
  rt->rt_success_init = 0;
  rt->rt_success_deinit = 0;

  TEST(su_clone_start(rt->rt_root,
		      rt->rt_clone,
		      rt,
		      fail_init,
		      fail_deinit), SU_FAILURE);
  TEST_1(rt->rt_fail_init);
  TEST_1(rt->rt_fail_deinit);

  TEST(su_clone_start(rt->rt_root,
		      rt->rt_clone,
		      rt,
		      success_init,
		      success_deinit), SU_SUCCESS);
  TEST_1(rt->rt_success_init);
  TEST_1(!rt->rt_success_deinit);

  TEST_VOID(su_clone_wait(rt->rt_root, rt->rt_clone));

  TEST_1(rt->rt_success_deinit);
  
  END();
327 328
}

329
void usage(int exitcode)
330
{
331
  fprintf(stderr, 
332
	  "usage: %s [-v] [-a]\n", 
333
	  name);
334
  exit(exitcode);
335 336 337 338
}

int main(int argc, char *argv[])
{
339 340 341
  root_test_t rt[1] = {{{ SU_HOME_INIT(rt) }}};
  int retval = 0;
  int i;
342

343
  rt->rt_family = AF_INET;
344

345 346 347
  for (i = 1; argv[i]; i++) {
    if (strcmp(argv[i], "-v") == 0)
      rt->rt_flags |= tst_verbatim;
348 349
    else if (strcmp(argv[i], "-a") == 0)
      rt->rt_flags |= tst_abort;
350
#if SU_HAVE_IN6
351 352
    else if (strcmp(argv[i], "-6") == 0)
      rt->rt_family = AF_INET6;
353
#endif
354
    else
355
      usage(1);
356 357
  }

358 359 360 361 362 363
  retval |= init_test(rt);
  retval |= register_test(rt);
  retval |= clone_test(rt);
  su_root_threading(rt->rt_root, 0);
  retval |= clone_test(rt);
  retval |= deinit_test(rt);
364

365
  return retval;
366
}