blob: 285b2a3c757fc7d4b5b390b936b83d577aa048b2 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
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#include <pj/os.h>
21#include <pj/log.h>
Benny Prijono37e8d332006-01-20 21:03:36 +000022#include <pj/rand.h>
Benny Prijono5dcb38d2005-11-21 01:55:47 +000023
24
25/**
26 * \page page_pjlib_timestamp_test Test: Timestamp
27 *
28 * This file provides implementation of timestamp_test()
29 *
30 * \section timestamp_test_sec Scope of the Test
31 *
32 * This tests whether timestamp API works.
33 *
34 * API tested:
35 * - pj_get_timestamp_freq()
36 * - pj_get_timestamp()
37 * - pj_elapsed_usec()
38 * - PJ_LOG()
39 *
40 *
41 * This file is <b>pjlib-test/timestamp.c</b>
42 *
43 * \include pjlib-test/timestamp.c
44 */
45
46#if INCLUDE_TIMESTAMP_TEST
47
48#define THIS_FILE "timestamp"
49
Benny Prijono4fda1eb2006-04-05 18:42:13 +000050static int timestamp_accuracy()
51{
52 pj_timestamp freq, t1, t2;
53 pj_time_val tv1, tv2, tvtmp;
54 pj_uint32_t msec, tics;
55 pj_int64_t diff;
56
57 PJ_LOG(3,(THIS_FILE, "...testing frequency accuracy (pls wait)"));
58
59 pj_get_timestamp_freq(&freq);
60
61 /* Get the start time */
62 pj_gettimeofday(&tvtmp);
63 do {
64 pj_gettimeofday(&tv1);
65 } while (PJ_TIME_VAL_EQ(tvtmp, tv1));
66 pj_get_timestamp(&t1);
67
68 /* Sleep for 5 seconds */
69 pj_thread_sleep(10000);
70
71 /* Get end time */
72 pj_gettimeofday(&tvtmp);
73 do {
74 pj_gettimeofday(&tv2);
75 } while (PJ_TIME_VAL_EQ(tvtmp, tv2));
76 pj_get_timestamp(&t2);
77
78 /* Get the elapsed time */
79 PJ_TIME_VAL_SUB(tv2, tv1);
80 msec = PJ_TIME_VAL_MSEC(tv2);
81
82 /* Check that the frequency match the elapsed time */
83 tics = (unsigned)(t2.u64 - t1.u64);
84 diff = tics - (msec * freq.u64 / 1000);
85 if (diff < 0)
86 diff = -diff;
87
88 /* Only allow 1 msec mismatch */
89 if (diff > (pj_int64_t)(freq.u64 / 1000)) {
90 PJ_LOG(3,(THIS_FILE, "....error: timestamp drifted by %d usec after "
91 "%d msec",
92 (pj_uint32_t)(diff * 1000000 / freq.u64),
93 msec));
94 return -2000;
95
96 /* Otherwise just print warning if timestamp drifted by >1 usec */
97 } else if (diff > (pj_int64_t)(freq.u64 / 1000000)) {
98 PJ_LOG(3,(THIS_FILE, "....warning: timestamp drifted by %d usec after "
99 "%d msec",
100 (pj_uint32_t)(diff * 1000000 / freq.u64),
101 msec));
Benny Prijono2a816342006-04-05 19:04:34 +0000102 } else {
103 PJ_LOG(3,(THIS_FILE, "....good. Timestamp is accurate down to"
104 " nearest usec."));
Benny Prijono4fda1eb2006-04-05 18:42:13 +0000105 }
106
107 return 0;
108}
109
110
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000111int timestamp_test(void)
112{
Benny Prijono37e8d332006-01-20 21:03:36 +0000113 enum { CONSECUTIVE_LOOP = 100 };
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000114 volatile unsigned i;
115 pj_timestamp freq, t1, t2;
Benny Prijono37e8d332006-01-20 21:03:36 +0000116 pj_time_val tv1, tv2;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000117 unsigned elapsed;
118 pj_status_t rc;
119
120 PJ_LOG(3,(THIS_FILE, "...Testing timestamp (high res time)"));
121
122 /* Get and display timestamp frequency. */
123 if ((rc=pj_get_timestamp_freq(&freq)) != PJ_SUCCESS) {
124 app_perror("...ERROR: get timestamp freq", rc);
125 return -1000;
126 }
127
128 PJ_LOG(3,(THIS_FILE, "....frequency: hiword=%lu loword=%lu",
129 freq.u32.hi, freq.u32.lo));
130
131 PJ_LOG(3,(THIS_FILE, "...checking if time can run backwards (pls wait).."));
132
133 /*
134 * Check if consecutive readings should yield timestamp value
135 * that is bigger than previous value.
136 * First we get the first timestamp.
137 */
138 rc = pj_get_timestamp(&t1);
139 if (rc != PJ_SUCCESS) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000140 app_perror("...ERROR: pj_get_timestamp", rc);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000141 return -1001;
142 }
Benny Prijono37e8d332006-01-20 21:03:36 +0000143 rc = pj_gettimeofday(&tv1);
144 if (rc != PJ_SUCCESS) {
145 app_perror("...ERROR: pj_gettimeofday", rc);
146 return -1002;
147 }
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000148 for (i=0; i<CONSECUTIVE_LOOP; ++i) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000149
150 pj_thread_sleep(pj_rand() % 100);
151
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000152 rc = pj_get_timestamp(&t2);
153 if (rc != PJ_SUCCESS) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000154 app_perror("...ERROR: pj_get_timestamp", rc);
155 return -1003;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000156 }
Benny Prijono37e8d332006-01-20 21:03:36 +0000157 rc = pj_gettimeofday(&tv2);
158 if (rc != PJ_SUCCESS) {
159 app_perror("...ERROR: pj_gettimeofday", rc);
160 return -1004;
161 }
162
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000163 /* compare t2 with t1, expecting t2 >= t1. */
164 if (t2.u32.hi < t1.u32.hi ||
165 (t2.u32.hi == t1.u32.hi && t2.u32.lo < t1.u32.lo))
166 {
Benny Prijono37e8d332006-01-20 21:03:36 +0000167 PJ_LOG(3,(THIS_FILE, "...ERROR: timestamp run backwards!"));
168 return -1005;
169 }
170
171 /* compare tv2 with tv1, expecting tv2 >= tv1. */
172 if (PJ_TIME_VAL_LT(tv2, tv1)) {
173 PJ_LOG(3,(THIS_FILE, "...ERROR: time run backwards!"));
174 return -1006;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000175 }
176 }
177
178 /*
179 * Simple test to time some loop.
180 */
181 PJ_LOG(3,(THIS_FILE, "....testing simple 1000000 loop"));
182
183
184 /* Mark start time. */
185 if ((rc=pj_get_timestamp(&t1)) != PJ_SUCCESS) {
186 app_perror("....error: cat't get timestamp", rc);
187 return -1010;
188 }
189
190 /* Loop.. */
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000191 for (i=0; i<1000000; ++i) {
192 /* Try to do something so that smart compilers wont
193 * remove this silly loop.
194 */
195 null_func();
196 }
197
Benny Prijonod8410532006-06-15 11:04:33 +0000198 pj_thread_sleep(0);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000199
200 /* Mark end time. */
201 pj_get_timestamp(&t2);
202
203 /* Get elapsed time in usec. */
204 elapsed = pj_elapsed_usec(&t1, &t2);
205 PJ_LOG(3,(THIS_FILE, "....elapsed: %u usec", (unsigned)elapsed));
206
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000207 /* See if elapsed time is "reasonable".
208 * This should be good even on 50Mhz embedded powerpc.
209 */
210 if (elapsed < 1 || elapsed > 1000000) {
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000211 PJ_LOG(3,(THIS_FILE, "....error: elapsed time outside window (%u, "
212 "t1.u32.hi=%u, t1.u32.lo=%u, "
213 "t2.u32.hi=%u, t2.u32.lo=%u)",
214 elapsed,
215 t1.u32.hi, t1.u32.lo, t2.u32.hi, t2.u32.lo));
216 return -1030;
217 }
Benny Prijono4fda1eb2006-04-05 18:42:13 +0000218
219 /* Testing time/timestamp accuracy */
220 rc = timestamp_accuracy();
221 if (rc != 0)
222 return rc;
223
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000224 return 0;
225}
226
227
228#else
229/* To prevent warning about "translation unit is empty"
230 * when this test is disabled.
231 */
232int dummy_timestamp_test;
233#endif /* INCLUDE_TIMESTAMP_TEST */
234