torture_su_port.c 7.62 KB
Newer Older
Pekka Pessi's avatar
Pekka Pessi committed
1 2 3 4 5 6 7
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
8
 * This library is free software; you can redistribute it and/or
Pekka Pessi's avatar
Pekka Pessi committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 * 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
 *
 */

/**
 * @file torture_su_port.c
 * @brief Test su_port interface
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 * @date Created: Wed Mar 10 17:05:23 2004 ppessi
 */

#include "config.h"

35 36 37 38
struct su_root_magic_s;

#define SU_ROOT_MAGIC_T struct su_root_magic_s

Pekka Pessi's avatar
Pekka Pessi committed
39 40
#include "su_port.c"

41 42 43 44 45 46 47
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
static char const __func__[] = "torture_su_port";
#endif

Pekka Pessi's avatar
Pekka Pessi committed
48 49 50 51 52
int tstflags;

#define TSTFLAGS tstflags

#include <stdio.h>
53
#include <sofia-sip/tstdef.h>
Pekka Pessi's avatar
Pekka Pessi committed
54 55 56

char const *name = "torture_su_port";

57
int N0 = SU_HAVE_MBOX, N = 128, I = 128 + 1;
Pekka Pessi's avatar
Pekka Pessi committed
58 59 60

int test_sup_indices(su_port_t const *port)
{
61 62 63 64 65 66 67
  int i, n;
  int *indices = port->sup_indices;
  int *reverses = port->sup_reverses;
  int N = port->sup_size_waits;

  if (indices == NULL)
    return N == 0 && port->sup_n_waits == 0;
Pekka Pessi's avatar
Pekka Pessi committed
68

69 70 71
  for (i = 0, n = 0; i < N; i++) {
    if (reverses[i] > 0) {
      if (indices[reverses[i]] != i)
Pekka Pessi's avatar
Pekka Pessi committed
72 73 74 75 76
	return 0;
      n++;
    }
  }

77 78 79 80
  if (n != port->sup_n_waits)
    return 0;
  
  n = 0;
Pekka Pessi's avatar
Pekka Pessi committed
81

82 83 84 85 86 87 88 89 90 91
  for (i = 1; i <= N; i++) {
    if (indices[i] >= 0) {
      if (reverses[indices[i]] != i)
	return 0;
      n++;
    }
  }

  if (n != port->sup_n_waits)
    return 0;
Pekka Pessi's avatar
Pekka Pessi committed
92

93 94
  for (i = indices[0]; -i <= N; i = indices[-i]) {
    if (i >= 0)
Pekka Pessi's avatar
Pekka Pessi committed
95
      return 0;
96
    n++;
Pekka Pessi's avatar
Pekka Pessi committed
97 98 99 100 101
  }

  return n == port->sup_size_waits;
}

102 103 104 105 106 107 108 109 110
struct su_root_magic_s 
{
  int error, *sockets, *regs, *wakeups;
};

static int callback(su_root_magic_t *magic, 
		    su_wait_t *w,
		    su_wakeup_arg_t *arg)
{
111
  intptr_t i = (intptr_t)arg;
112 113

  assert(magic);
114
 
115
  if (i <= 0 || i > I)
116 117
    return ++magic->error;

118 119
  su_wait_events(w, magic->sockets[i]);

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
  magic->wakeups[i]++;

#if HAVE_POLL
  if (w->fd != magic->sockets[i])
    return ++magic->error;
#endif

  return 0;
}

int test_wakeup(su_port_t *port, su_root_magic_t *magic)
{
  int i;

  for (i = N0; i < N; i++) {
    su_sockaddr_t su[1]; socklen_t sulen = sizeof su;
    int n, woken = magic->wakeups[i];
    char buf[1];
    if (magic->regs[i] == 0)
      continue;

    if (getsockname(magic->sockets[i], &su->su_sa, &sulen) < 0)
      su_perror("getsockname"), exit(1);
143
    if (su_sendto(magic->sockets[1], "X", 1, 0, su, sulen) < 0)
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
      su_perror("su_sendto"), exit(1);
    n = su_port_wait_events(port, 100);
    if (n != 1)
      return 1;
    if (magic->error)
      return 2;
    if (magic->wakeups[i] != woken + 1)
      return 3;
    if (recv(magic->sockets[i], buf, 1, 0) != 1)
      return 4;
  }

  return 0;
}

Pekka Pessi's avatar
Pekka Pessi committed
159 160 161 162
int test_register(void)
{
  su_port_t *port;
  su_sockaddr_t su[1];
163
  intptr_t i;
164 165 166
  int sockets[256] = { 0 };
  int reg[256] = { 0 };
  int wakeups[256] = { 0 };
167
  int prioritized;
168
  su_wait_t wait[256];
169 170
  su_root_magic_t magic[1] = {{ 0 }};
  su_root_t root[1] = {{ sizeof root }};
Pekka Pessi's avatar
Pekka Pessi committed
171 172 173

  BEGIN();

174 175
  root->sur_magic = magic;

Pekka Pessi's avatar
Pekka Pessi committed
176 177 178
  memset(su, 0, sizeof su);
  su->su_len = sizeof su->su_sin;
  su->su_family = AF_INET;
179
  su->su_sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
Pekka Pessi's avatar
Pekka Pessi committed
180 181 182

  memset(wait, 0, sizeof wait);

183 184 185
  memset(magic->sockets = sockets, -1, sizeof sockets);
  memset(magic->regs = reg, 0, sizeof reg);
  memset(magic->wakeups = wakeups, 0, sizeof wakeups);
186

Pekka Pessi's avatar
Pekka Pessi committed
187 188 189 190 191 192 193 194
  su_root_size_hint = 16;

  TEST_1(port = su_port_create());
  TEST(su_port_threadsafe(port), 0);
  SU_PORT_INCREF(port, __func__);

  TEST_1(test_sup_indices(port));

195
  for (i = N0; i < N; i++) {
Pekka Pessi's avatar
Pekka Pessi committed
196 197
    sockets[i] = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(sockets[i] != -1);

198 199
    if (bind(sockets[i], &su->su_sa, sizeof su->su_sin) != 0)
      perror("bind"), assert(0);
Pekka Pessi's avatar
Pekka Pessi committed
200 201 202
    
    TEST(su_wait_create(wait + i, sockets[i], SU_WAIT_IN), 0);

203
    reg[i] = su_port_register(port, root, wait + i, callback, (void*)i, 0);
Pekka Pessi's avatar
Pekka Pessi committed
204 205 206 207

    TEST_1(reg[i] > 0);
  }

208
  TEST(port->sup_indices[0], -I);
Pekka Pessi's avatar
Pekka Pessi committed
209
  TEST_1(test_sup_indices(port));
210
  TEST(test_wakeup(port, magic), 0);
Pekka Pessi's avatar
Pekka Pessi committed
211

212
  for (i = 1; i < N; i += 2) {
Pekka Pessi's avatar
Pekka Pessi committed
213
    TEST(su_port_deregister(port, reg[i]), reg[i]);
214
    TEST_1(test_sup_indices(port));
Pekka Pessi's avatar
Pekka Pessi committed
215 216 217 218
  }

  TEST_1(test_sup_indices(port));

219 220
  prioritized = 0;

221
  for (i = N - 1; i >= N0; i -= 2) {
Pekka Pessi's avatar
Pekka Pessi committed
222
    TEST(su_wait_create(wait + i, sockets[i], SU_WAIT_IN), 0);
223
    reg[i] = su_port_register(port, root, wait + i, callback, (void *)i, 1);
Pekka Pessi's avatar
Pekka Pessi committed
224
    TEST_1(reg[i] > 0);
225
    prioritized++;		/* Count number of prioritized registrations */
226 227 228 229 230 231 232 233
#if HAVE_EPOLL
    /* With epoll we do not bother to prioritize the wait list */
    if (port->sup_epoll != -1) {
      int N = port->sup_n_waits;
      TEST_M(wait + i, port->sup_waits + N - 1, sizeof wait[0]);
    }
    else
#endif
Pekka Pessi's avatar
Pekka Pessi committed
234 235 236
    TEST_M(wait + i, port->sup_waits, sizeof wait[0]);
  }

237 238
  TEST(port->sup_indices[0], -I);

239
#if 0
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
#if HAVE_EPOLL
  /* With epoll we do not bother to prioritize the wait list */
  if (port->sup_epoll != -1) {
    TEST_M(wait + 15, port->sup_waits + 8, sizeof wait[0]);
    TEST_M(wait + 13, port->sup_waits + 9, sizeof wait[0]);
    TEST_M(wait + 11, port->sup_waits + 10, sizeof wait[0]);
    TEST_M(wait + 9, port->sup_waits + 11, sizeof wait[0]);
    TEST_M(wait + 7, port->sup_waits + 12, sizeof wait[0]);
    TEST_M(wait + 5, port->sup_waits + 13, sizeof wait[0]);
    TEST_M(wait + 3, port->sup_waits + 14, sizeof wait[0]);
    TEST_M(wait + 1, port->sup_waits + 15, sizeof wait[0]);
  }
  else
#endif
  {
Pekka Pessi's avatar
Pekka Pessi committed
255 256 257 258 259 260 261 262
  TEST_M(wait + 15, port->sup_waits + 7, sizeof wait[0]);
  TEST_M(wait + 13, port->sup_waits + 6, sizeof wait[0]);
  TEST_M(wait + 11, port->sup_waits + 5, sizeof wait[0]);
  TEST_M(wait + 9, port->sup_waits + 4, sizeof wait[0]);
  TEST_M(wait + 7, port->sup_waits + 3, sizeof wait[0]);
  TEST_M(wait + 5, port->sup_waits + 2, sizeof wait[0]);
  TEST_M(wait + 3, port->sup_waits + 1, sizeof wait[0]);
  TEST_M(wait + 1, port->sup_waits + 0, sizeof wait[0]);
263
  }
264
#endif
Pekka Pessi's avatar
Pekka Pessi committed
265 266

  TEST_1(test_sup_indices(port));
267
  TEST(test_wakeup(port, magic), 0);
Pekka Pessi's avatar
Pekka Pessi committed
268 269

  for (i = 1; i <= 8; i++) {
270
    TEST(su_port_deregister(port, reg[i]), reg[i]); reg[i] = 0;
271 272
    if (i % 2 == (N - 1) % 2)
      prioritized--;		/* Count number of prioritized registrations */
Pekka Pessi's avatar
Pekka Pessi committed
273 274
  }

275 276 277 278
#if HAVE_EPOLL
  /* With epoll we do not bother to prioritize the wait list */
  if (port->sup_epoll == -1) 
#endif
279
    TEST(port->sup_pri_offset, prioritized);
Pekka Pessi's avatar
Pekka Pessi committed
280 281 282 283 284

  TEST_1(test_sup_indices(port));

  TEST(su_port_deregister(port, 0), -1);
  TEST(su_port_deregister(port, -1), -1);
285
  TEST(su_port_deregister(port, 130), -1);
Pekka Pessi's avatar
Pekka Pessi committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

  TEST_1(test_sup_indices(port));

  for (i = 1; i <= 8; i++) {
    TEST(su_port_deregister(port, reg[i]), -1);
  }

  TEST_VOID(su_port_decref(port, 1, __func__));

  END();
}

void usage(void)
{
  fprintf(stderr,
	  "usage: %s [-v]\n",
	  name);
}

int main(int argc, char *argv[])
{
  int retval = 0;
  int i;

310
#if SU_HAVE_WINSOCK
311 312
  if (N > SU_WAIT_MAX)
    N = SU_WAIT_MAX;
313 314 315
  if (I - 1 >= SU_WAIT_MAX)
    I = (unsigned)SU_WAIT_MAX + 1;
#endif
316

Pekka Pessi's avatar
Pekka Pessi committed
317 318 319 320 321 322 323
  for (i = 1; argv[i]; i++) {
    if (strcmp(argv[i], "-v") == 0)
      tstflags |= tst_verbatim;
    else
      usage();
  }

324 325
  su_init();

Pekka Pessi's avatar
Pekka Pessi committed
326 327
  retval |= test_register(); fflush(stdout);

328 329
  su_deinit();

Pekka Pessi's avatar
Pekka Pessi committed
330 331
  return retval;
}