blob: 258db026863f829a6ee670fc4863a871b8f8efdd [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono5dcb38d2005-11-21 01:55:47 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include "test.h"
20
21/**
22 * \page page_pjlib_timer_test Test: Timer
23 *
24 * This file provides implementation of \b timer_test(). It tests the
25 * functionality of the timer heap.
26 *
27 *
28 * This file is <b>pjlib-test/timer.c</b>
29 *
30 * \include pjlib-test/timer.c
31 */
32
33
34#if INCLUDE_TIMER_TEST
35
36#include <pjlib.h>
37
38#define LOOP 16
39#define MIN_COUNT 250
40#define MAX_COUNT (LOOP * MIN_COUNT)
41#define MIN_DELAY 2
42#define D (MAX_COUNT / 32000)
43#define DELAY (D < MIN_DELAY ? MIN_DELAY : D)
44#define THIS_FILE "timer_test"
45
46
47static void timer_callback(pj_timer_heap_t *ht, pj_timer_entry *e)
48{
49 PJ_UNUSED_ARG(ht);
50 PJ_UNUSED_ARG(e);
51}
52
53static int test_timer_heap(void)
54{
55 int i, j;
56 pj_timer_entry *entry;
57 pj_pool_t *pool;
58 pj_timer_heap_t *timer;
59 pj_time_val delay;
60 pj_status_t rc; int err=0;
61 unsigned size, count;
62
63 size = pj_timer_heap_mem_size(MAX_COUNT)+MAX_COUNT*sizeof(pj_timer_entry);
64 pool = pj_pool_create( mem, NULL, size, 4000, NULL);
65 if (!pool) {
66 PJ_LOG(3,("test", "...error: unable to create pool of %u bytes",
67 size));
68 return -10;
69 }
70
71 entry = (pj_timer_entry*)pj_pool_calloc(pool, MAX_COUNT, sizeof(*entry));
72 if (!entry)
73 return -20;
74
75 for (i=0; i<MAX_COUNT; ++i) {
76 entry[i].cb = &timer_callback;
77 }
78 rc = pj_timer_heap_create(pool, MAX_COUNT, &timer);
79 if (rc != PJ_SUCCESS) {
80 app_perror("...error: unable to create timer heap", rc);
81 return -30;
82 }
83
84 count = MIN_COUNT;
85 for (i=0; i<LOOP; ++i) {
86 int early = 0;
87 int done=0;
88 int cancelled=0;
89 int rc;
90 pj_timestamp t1, t2, t_sched, t_cancel, t_poll;
91 pj_time_val now, expire;
92
93 pj_gettimeofday(&now);
94 pj_srand(now.sec);
95 t_sched.u32.lo = t_cancel.u32.lo = t_poll.u32.lo = 0;
96
97 // Register timers
98 for (j=0; j<(int)count; ++j) {
99 delay.sec = pj_rand() % DELAY;
100 delay.msec = pj_rand() % 1000;
101
102 // Schedule timer
103 pj_get_timestamp(&t1);
104 rc = pj_timer_heap_schedule(timer, &entry[j], &delay);
105 if (rc != 0)
106 return -40;
107 pj_get_timestamp(&t2);
108
109 t_sched.u32.lo += (t2.u32.lo - t1.u32.lo);
110
111 // Poll timers.
112 pj_get_timestamp(&t1);
113 rc = pj_timer_heap_poll(timer, NULL);
114 pj_get_timestamp(&t2);
115 if (rc > 0) {
116 t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);
117 early += rc;
118 }
119 }
120
121 // Set the time where all timers should finish
122 pj_gettimeofday(&expire);
123 delay.sec = DELAY;
124 delay.msec = 0;
125 PJ_TIME_VAL_ADD(expire, delay);
126
127 // Wait unfil all timers finish, cancel some of them.
128 do {
129 int index = pj_rand() % count;
130 pj_get_timestamp(&t1);
131 rc = pj_timer_heap_cancel(timer, &entry[index]);
132 pj_get_timestamp(&t2);
133 if (rc > 0) {
134 cancelled += rc;
135 t_cancel.u32.lo += (t2.u32.lo - t1.u32.lo);
136 }
137
138 pj_gettimeofday(&now);
139
140 pj_get_timestamp(&t1);
141 rc = pj_timer_heap_poll(timer, NULL);
142 pj_get_timestamp(&t2);
143 if (rc > 0) {
144 done += rc;
145 t_poll.u32.lo += (t2.u32.lo - t1.u32.lo);
146 }
147
148 } while (PJ_TIME_VAL_LTE(now, expire)&&pj_timer_heap_count(timer) > 0);
149
150 if (pj_timer_heap_count(timer)) {
151 PJ_LOG(3, (THIS_FILE, "ERROR: %d timers left",
152 pj_timer_heap_count(timer)));
153 ++err;
154 }
155 t_sched.u32.lo /= count;
156 t_cancel.u32.lo /= count;
157 t_poll.u32.lo /= count;
158 PJ_LOG(4, (THIS_FILE,
159 "...ok (count:%d, early:%d, cancelled:%d, "
160 "sched:%d, cancel:%d poll:%d)",
161 count, early, cancelled, t_sched.u32.lo, t_cancel.u32.lo,
162 t_poll.u32.lo));
163
164 count = count * 2;
165 if (count > MAX_COUNT)
166 break;
167 }
168
169 pj_pool_release(pool);
170 return err;
171}
172
173
174int timer_test()
175{
176 return test_timer_heap();
177}
178
179#else
180/* To prevent warning about "translation unit is empty"
181 * when this test is disabled.
182 */
183int dummy_timer_test;
184#endif /* INCLUDE_TIMER_TEST */
185
186