torture_su_timer.c 5.63 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
 * 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
 *
 */

/**@ingroup su_root_ex
26
 * @CFILE torture_su_timer.c
Pekka Pessi's avatar
Pekka Pessi committed
27 28 29 30 31 32
 *
 * @brief Test program for su timers
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @internal
33
 *
Pekka Pessi's avatar
Pekka Pessi committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
 * @date Created: Fri Oct 19 08:53:55 2001 pessi
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <assert.h>

struct tester;

#define SU_ROOT_MAGIC_T struct tester
#define SU_INTERNAL_P   su_root_t *
#define SU_TIMER_ARG_T  struct timing

51 52 53
#include "sofia-sip/su.h"
#include "sofia-sip/su_wait.h"
#include "sofia-sip/su_log.h"
Pekka Pessi's avatar
Pekka Pessi committed
54 55 56 57 58 59 60 61 62 63 64 65

struct timing
{
  int       t_run;
  int       t_times;
  su_time_t t_prev;
};

struct tester
{
  su_root_t *root;
  su_timer_t *t, *t1;
66 67
  unsigned times;
  void *sentinel;
Pekka Pessi's avatar
Pekka Pessi committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
};

void
print_stamp(struct tester *x, su_timer_t *t, struct timing *ti)
{
  su_time_t now = su_now(), prev = ti->t_prev;

  ti->t_prev = now;

  if (!ti->t_run)
    su_timer_set(t, print_stamp, ti);

  printf("timer interval %f\n", 1000 * su_time_diff(now, prev));

  if (++ti->t_times >= 10)
    su_timer_reset(t);
}

void
print_X(struct tester *x, su_timer_t *t1, struct timing *ti)
{
  su_timer_set(t1, print_X, ti);
  putchar('X'); fflush(stdout);
}

93 94 95 96
#if HAVE_SIGNAL

#include <signal.h>

Pekka Pessi's avatar
Pekka Pessi committed
97 98
su_msg_r intr_msg = SU_MSG_R_INIT;

Pekka Pessi's avatar
Pekka Pessi committed
99
static RETSIGTYPE intr_handler(int signum)
Pekka Pessi's avatar
Pekka Pessi committed
100 101 102 103 104 105 106 107 108
{
  su_msg_send(intr_msg);
}

static void test_break(struct tester *tester, su_msg_r msg, su_msg_arg_t *arg)
{
  su_root_break(tester->root);
}

109 110
#endif

Pekka Pessi's avatar
Pekka Pessi committed
111 112 113 114 115 116 117 118 119
void
end_test(struct tester *tester, su_timer_t *t, struct timing *ti)
{
  su_timer_destroy(t);
  su_timer_reset(tester->t);
  su_timer_reset(tester->t1);
  su_root_break(tester->root);
}

120 121 122 123 124 125 126 127 128
void
increment(struct tester *tester, su_timer_t *t, struct timing *ti)
{
  tester->times++;

  if ((void *)ti == (void*)tester->sentinel)
    su_root_break(tester->root);
}

Pekka Pessi's avatar
Pekka Pessi committed
129 130 131
void
usage(char const *name)
{
132
  fprintf(stderr, "usage: %s [-1r] [-Nnum] [interval]\n", name);
Pekka Pessi's avatar
Pekka Pessi committed
133 134 135 136 137 138 139 140 141 142 143 144
  exit(1);
}

/*
 * test su_timer functionality:
 *
 * Create a timer, executing print_stamp() in every 20 ms
 */
int main(int argc, char *argv[])
{
  su_root_t *root;
  su_timer_t *t, *t1, *t_end;
145
  su_timer_t **timers;
Pekka Pessi's avatar
Pekka Pessi committed
146 147 148 149
  su_duration_t interval = 60;
  char *argv0 = argv[0];
  char *s;
  int use_t1 = 0;
150 151
  su_time_t now, started, inserted;
  unsigned i, N = 500;
152

Pekka Pessi's avatar
Pekka Pessi committed
153 154 155 156 157
  struct timing timing[1] = {{ 0 }};
  struct tester tester[1] = {{ 0 }};

  while (argv[1] && argv[1][0] == '-') {
    char *o = argv[1] + 1;
158
    while (*o) {
Pekka Pessi's avatar
Pekka Pessi committed
159 160 161 162
      if (*o == '1')
	o++, use_t1 = 1;
      else if (*o == 'r')
	o++, timing->t_run = 1;
163 164 165 166 167 168 169
      else if (*o == 'N') {
	if (o[1])
	  N = strtoul(o + 1, &o, 0);
	else if (argv[2])
	  N = strtoul(argv++[2], &o, 0);
	break;
      }
170
      else
Pekka Pessi's avatar
Pekka Pessi committed
171 172
	break;

173 174
    }
    if (*o)
Pekka Pessi's avatar
Pekka Pessi committed
175 176 177 178 179 180 181
      usage(argv0);
    argv++;
  }

  if (argv[1]) {
    interval = strtoul(argv[1], &s, 10);

182
    if (interval == 0 || s == argv[1])
Pekka Pessi's avatar
Pekka Pessi committed
183 184 185 186 187 188 189
      usage(argv0);
  }

  su_init(); atexit(su_deinit);

  tester->root = root = su_root_create(tester);

190
#if HAVE_SIGNAL
191 192 193
  su_msg_create(intr_msg,
		su_root_task(root),
		su_root_task(root),
Pekka Pessi's avatar
Pekka Pessi committed
194 195 196
		test_break, 0);

  signal(SIGINT, intr_handler);
197
#if HAVE_SIGPIPE
Pekka Pessi's avatar
Pekka Pessi committed
198 199
  signal(SIGQUIT, intr_handler);
  signal(SIGHUP, intr_handler);
200
#endif
201
#endif
Pekka Pessi's avatar
Pekka Pessi committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

  t = su_timer_create(su_root_task(root), interval);
  t1 = su_timer_create(su_root_task(root), 1);
  t_end = su_timer_create(su_root_task(root), 20 * interval);

  if (t == NULL || t1 == NULL || t_end == NULL)
    su_perror("su_timer_create"), exit(1);

  tester->t = t, tester->t1 = t1;

  timing->t_prev = su_now();

  if (timing->t_run)
    su_timer_run(t, print_stamp, timing);
  else
217
    su_timer_set(t, print_stamp, timing);
Pekka Pessi's avatar
Pekka Pessi committed
218 219 220 221 222 223 224 225

  if (use_t1)
    su_timer_set(t1, print_X, NULL);

  su_timer_set(t_end, end_test, NULL);

  su_root_run(root);

226
#if HAVE_SIGNAL
Pekka Pessi's avatar
Pekka Pessi committed
227
  su_msg_destroy(intr_msg);
228
#endif
Pekka Pessi's avatar
Pekka Pessi committed
229 230 231 232 233

  su_timer_destroy(t);
  su_timer_destroy(t1);

  if (timing->t_times != 10) {
234
    fprintf(stderr, "%s: t expired %d times (expecting 10)\n",
Pekka Pessi's avatar
Pekka Pessi committed
235 236 237 238
	    argv0, timing->t_times);
    return 1;
  }

239 240
  /* Insert timers in order */
  timers = calloc(N, sizeof *timers);
241 242 243 244 245 246 247 248
  if (!timers) { perror("calloc"); exit(1); }

  for (i = 0; i < N; i++) {
    t = su_timer_create(su_root_task(root), 1000);
    if (!t) { perror("su_timer_create"); exit(1); }
    timers[i] = t;
  }

249 250 251 252 253 254 255 256 257 258
  now = started = su_now();

  for (i = 0; i < N; i++) {
    if (++now.tv_usec == 0) ++now.tv_sec;
    su_timer_set_at(timers[i], increment, (void *)(intptr_t)i, now);
  }

  tester->sentinel = (void*)(intptr_t)(i - 1);

  inserted = su_now();
259 260 261

  su_root_run(root);

262 263
  now = su_now();

264
  printf("Inserting %u timers took %f millisec\n",
265 266 267 268 269 270
	 i, su_time_diff(inserted, started) * 1000);

  printf("Processing %u/%u timers took %f millisec (%f expected)\n",
	 tester->times, i,
	 su_time_diff(now, started) * 1000,
	 (double)i / 1000);
271 272 273 274 275 276 277 278 279

  for (i = 0; i < N; i++) {
    su_timer_destroy(timers[i]);
  }

  su_root_destroy(root);

  su_deinit();

Pekka Pessi's avatar
Pekka Pessi committed
280 281
  return 0;
}