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