VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.2 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/*
39 * Test: y2ktmo
40 *
41 * Description:
42 * This test tests the interval time facilities in NSPR for Y2K
43 * compliance. All the functions that take a timeout argument
44 * are tested: PR_Sleep, socket I/O (PR_Accept is taken as a
45 * representative), PR_Poll, PR_WaitCondVar, PR_Wait, and
46 * PR_CWait. A thread of each thread scope (local, global, and
47 * global bound) is created to call each of these functions.
48 * The test should be started at the specified number of seconds
49 * (called the lead time) before a Y2K rollover test date. The
50 * timeout values for these threads will span over the rollover
51 * date by at least the specified number of seconds. For
52 * example, if the lead time is 5 seconds, the test should
53 * be started at time (D - 5), where D is a rollover date, and
54 * the threads will time out at or after time (D + 5). The
55 * timeout values for the threads are spaced one second apart.
56 *
57 * When a thread times out, it calls PR_IntervalNow() to verify
58 * that it did wait for the specified time. In addition, it
59 * calls a platform-native function to verify the actual elapsed
60 * time again, to rule out the possibility that PR_IntervalNow()
61 * is broken. We allow the actual elapsed time to deviate from
62 * the specified timeout by a certain tolerance (in milliseconds).
63 */
64
65#include "nspr.h"
66#include "plgetopt.h"
67
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71#if defined(XP_UNIX)
72#include <sys/time.h> /* for gettimeofday */
73#endif
74#if defined(WIN32)
75#include <sys/types.h>
76#include <sys/timeb.h> /* for _ftime */
77#endif
78
79#define DEFAULT_LEAD_TIME_SECS 5
80#define DEFAULT_TOLERANCE_MSECS 500
81
82static PRBool debug_mode = PR_FALSE;
83static PRInt32 lead_time_secs = DEFAULT_LEAD_TIME_SECS;
84static PRInt32 tolerance_msecs = DEFAULT_TOLERANCE_MSECS;
85static PRIntervalTime start_time;
86static PRIntervalTime tolerance;
87
88#if defined(XP_UNIX)
89static struct timeval start_time_tv;
90#endif
91#if defined(WIN32)
92static struct _timeb start_time_tb;
93#endif
94
95static void SleepThread(void *arg)
96{
97 PRIntervalTime timeout = (PRIntervalTime) arg;
98 PRIntervalTime elapsed;
99#if defined(XP_UNIX) || defined(WIN32)
100 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
101 PRInt32 elapsed_msecs;
102#endif
103#if defined(XP_UNIX)
104 struct timeval end_time_tv;
105#endif
106#if defined(WIN32)
107 struct _timeb end_time_tb;
108#endif
109
110 if (PR_Sleep(timeout) == PR_FAILURE) {
111 fprintf(stderr, "PR_Sleep failed\n");
112 exit(1);
113 }
114 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
115 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
116 fprintf(stderr, "timeout wrong\n");
117 exit(1);
118 }
119#if defined(XP_UNIX)
120 gettimeofday(&end_time_tv, NULL);
121 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
122 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
123#endif
124#if defined(WIN32)
125 _ftime(&end_time_tb);
126 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
127 + (end_time_tb.millitm - start_time_tb.millitm);
128#endif
129#if defined(XP_UNIX) || defined(WIN32)
130 if (elapsed_msecs + tolerance_msecs < timeout_msecs
131 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
132 fprintf(stderr, "timeout wrong\n");
133 exit(1);
134 }
135#endif
136 if (debug_mode) {
137 fprintf(stderr, "Sleep thread (scope %d) done\n",
138 PR_GetThreadScope(PR_GetCurrentThread()));
139 }
140}
141
142static void AcceptThread(void *arg)
143{
144 PRIntervalTime timeout = (PRIntervalTime) arg;
145 PRIntervalTime elapsed;
146#if defined(XP_UNIX) || defined(WIN32)
147 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
148 PRInt32 elapsed_msecs;
149#endif
150#if defined(XP_UNIX)
151 struct timeval end_time_tv;
152#endif
153#if defined(WIN32)
154 struct _timeb end_time_tb;
155#endif
156 PRFileDesc *sock;
157 PRNetAddr addr;
158 PRFileDesc *accepted;
159
160 sock = PR_NewTCPSocket();
161 if (sock == NULL) {
162 fprintf(stderr, "PR_NewTCPSocket failed\n");
163 exit(1);
164 }
165 memset(&addr, 0, sizeof(addr));
166 addr.inet.family = PR_AF_INET;
167 addr.inet.port = 0;
168 addr.inet.ip = PR_htonl(PR_INADDR_ANY);
169 if (PR_Bind(sock, &addr) == PR_FAILURE) {
170 fprintf(stderr, "PR_Bind failed\n");
171 exit(1);
172 }
173 if (PR_Listen(sock, 5) == PR_FAILURE) {
174 fprintf(stderr, "PR_Listen failed\n");
175 exit(1);
176 }
177 accepted = PR_Accept(sock, NULL, timeout);
178 if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) {
179 fprintf(stderr, "PR_Accept did not time out\n");
180 exit(1);
181 }
182 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
183 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
184 fprintf(stderr, "timeout wrong\n");
185 exit(1);
186 }
187#if defined(XP_UNIX)
188 gettimeofday(&end_time_tv, NULL);
189 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
190 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
191#endif
192#if defined(WIN32)
193 _ftime(&end_time_tb);
194 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
195 + (end_time_tb.millitm - start_time_tb.millitm);
196#endif
197#if defined(XP_UNIX) || defined(WIN32)
198 if (elapsed_msecs + tolerance_msecs < timeout_msecs
199 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
200 fprintf(stderr, "timeout wrong\n");
201 exit(1);
202 }
203#endif
204 if (PR_Close(sock) == PR_FAILURE) {
205 fprintf(stderr, "PR_Close failed\n");
206 exit(1);
207 }
208 if (debug_mode) {
209 fprintf(stderr, "Accept thread (scope %d) done\n",
210 PR_GetThreadScope(PR_GetCurrentThread()));
211 }
212}
213
214static void PollThread(void *arg)
215{
216 PRIntervalTime timeout = (PRIntervalTime) arg;
217 PRIntervalTime elapsed;
218#if defined(XP_UNIX) || defined(WIN32)
219 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
220 PRInt32 elapsed_msecs;
221#endif
222#if defined(XP_UNIX)
223 struct timeval end_time_tv;
224#endif
225#if defined(WIN32)
226 struct _timeb end_time_tb;
227#endif
228 PRFileDesc *sock;
229 PRNetAddr addr;
230 PRPollDesc pd;
231 PRIntn rv;
232
233 sock = PR_NewTCPSocket();
234 if (sock == NULL) {
235 fprintf(stderr, "PR_NewTCPSocket failed\n");
236 exit(1);
237 }
238 memset(&addr, 0, sizeof(addr));
239 addr.inet.family = PR_AF_INET;
240 addr.inet.port = 0;
241 addr.inet.ip = PR_htonl(PR_INADDR_ANY);
242 if (PR_Bind(sock, &addr) == PR_FAILURE) {
243 fprintf(stderr, "PR_Bind failed\n");
244 exit(1);
245 }
246 if (PR_Listen(sock, 5) == PR_FAILURE) {
247 fprintf(stderr, "PR_Listen failed\n");
248 exit(1);
249 }
250 pd.fd = sock;
251 pd.in_flags = PR_POLL_READ;
252 rv = PR_Poll(&pd, 1, timeout);
253 if (rv != 0) {
254 fprintf(stderr, "PR_Poll did not time out\n");
255 exit(1);
256 }
257 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
258 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
259 fprintf(stderr, "timeout wrong\n");
260 exit(1);
261 }
262#if defined(XP_UNIX)
263 gettimeofday(&end_time_tv, NULL);
264 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
265 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
266#endif
267#if defined(WIN32)
268 _ftime(&end_time_tb);
269 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
270 + (end_time_tb.millitm - start_time_tb.millitm);
271#endif
272#if defined(XP_UNIX) || defined(WIN32)
273 if (elapsed_msecs + tolerance_msecs < timeout_msecs
274 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
275 fprintf(stderr, "timeout wrong\n");
276 exit(1);
277 }
278#endif
279 if (PR_Close(sock) == PR_FAILURE) {
280 fprintf(stderr, "PR_Close failed\n");
281 exit(1);
282 }
283 if (debug_mode) {
284 fprintf(stderr, "Poll thread (scope %d) done\n",
285 PR_GetThreadScope(PR_GetCurrentThread()));
286 }
287}
288
289static void WaitCondVarThread(void *arg)
290{
291 PRIntervalTime timeout = (PRIntervalTime) arg;
292 PRIntervalTime elapsed;
293#if defined(XP_UNIX) || defined(WIN32)
294 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
295 PRInt32 elapsed_msecs;
296#endif
297#if defined(XP_UNIX)
298 struct timeval end_time_tv;
299#endif
300#if defined(WIN32)
301 struct _timeb end_time_tb;
302#endif
303 PRLock *ml;
304 PRCondVar *cv;
305
306 ml = PR_NewLock();
307 if (ml == NULL) {
308 fprintf(stderr, "PR_NewLock failed\n");
309 exit(1);
310 }
311 cv = PR_NewCondVar(ml);
312 if (cv == NULL) {
313 fprintf(stderr, "PR_NewCondVar failed\n");
314 exit(1);
315 }
316 PR_Lock(ml);
317 PR_WaitCondVar(cv, timeout);
318 PR_Unlock(ml);
319 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
320 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
321 fprintf(stderr, "timeout wrong\n");
322 exit(1);
323 }
324#if defined(XP_UNIX)
325 gettimeofday(&end_time_tv, NULL);
326 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
327 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
328#endif
329#if defined(WIN32)
330 _ftime(&end_time_tb);
331 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
332 + (end_time_tb.millitm - start_time_tb.millitm);
333#endif
334#if defined(XP_UNIX) || defined(WIN32)
335 if (elapsed_msecs + tolerance_msecs < timeout_msecs
336 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
337 fprintf(stderr, "timeout wrong\n");
338 exit(1);
339 }
340#endif
341 PR_DestroyCondVar(cv);
342 PR_DestroyLock(ml);
343 if (debug_mode) {
344 fprintf(stderr, "wait cond var thread (scope %d) done\n",
345 PR_GetThreadScope(PR_GetCurrentThread()));
346 }
347}
348
349static void WaitMonitorThread(void *arg)
350{
351 PRIntervalTime timeout = (PRIntervalTime) arg;
352 PRIntervalTime elapsed;
353#if defined(XP_UNIX) || defined(WIN32)
354 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
355 PRInt32 elapsed_msecs;
356#endif
357#if defined(XP_UNIX)
358 struct timeval end_time_tv;
359#endif
360#if defined(WIN32)
361 struct _timeb end_time_tb;
362#endif
363 PRMonitor *mon;
364
365 mon = PR_NewMonitor();
366 if (mon == NULL) {
367 fprintf(stderr, "PR_NewMonitor failed\n");
368 exit(1);
369 }
370 PR_EnterMonitor(mon);
371 PR_Wait(mon, timeout);
372 PR_ExitMonitor(mon);
373 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
374 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
375 fprintf(stderr, "timeout wrong\n");
376 exit(1);
377 }
378#if defined(XP_UNIX)
379 gettimeofday(&end_time_tv, NULL);
380 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
381 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
382#endif
383#if defined(WIN32)
384 _ftime(&end_time_tb);
385 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
386 + (end_time_tb.millitm - start_time_tb.millitm);
387#endif
388#if defined(XP_UNIX) || defined(WIN32)
389 if (elapsed_msecs + tolerance_msecs < timeout_msecs
390 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
391 fprintf(stderr, "timeout wrong\n");
392 exit(1);
393 }
394#endif
395 PR_DestroyMonitor(mon);
396 if (debug_mode) {
397 fprintf(stderr, "wait monitor thread (scope %d) done\n",
398 PR_GetThreadScope(PR_GetCurrentThread()));
399 }
400}
401
402static void WaitCMonitorThread(void *arg)
403{
404 PRIntervalTime timeout = (PRIntervalTime) arg;
405 PRIntervalTime elapsed;
406#if defined(XP_UNIX) || defined(WIN32)
407 PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
408 PRInt32 elapsed_msecs;
409#endif
410#if defined(XP_UNIX)
411 struct timeval end_time_tv;
412#endif
413#if defined(WIN32)
414 struct _timeb end_time_tb;
415#endif
416 int dummy;
417
418 PR_CEnterMonitor(&dummy);
419 PR_CWait(&dummy, timeout);
420 PR_CExitMonitor(&dummy);
421 elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
422 if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
423 fprintf(stderr, "timeout wrong\n");
424 exit(1);
425 }
426#if defined(XP_UNIX)
427 gettimeofday(&end_time_tv, NULL);
428 elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
429 + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
430#endif
431#if defined(WIN32)
432 _ftime(&end_time_tb);
433 elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
434 + (end_time_tb.millitm - start_time_tb.millitm);
435#endif
436#if defined(XP_UNIX) || defined(WIN32)
437 if (elapsed_msecs + tolerance_msecs < timeout_msecs
438 || elapsed_msecs > timeout_msecs + tolerance_msecs) {
439 fprintf(stderr, "timeout wrong\n");
440 exit(1);
441 }
442#endif
443 if (debug_mode) {
444 fprintf(stderr, "wait cached monitor thread (scope %d) done\n",
445 PR_GetThreadScope(PR_GetCurrentThread()));
446 }
447}
448
449typedef void (*NSPRThreadFunc)(void*);
450
451static NSPRThreadFunc threadFuncs[] = {
452 SleepThread, AcceptThread, PollThread,
453 WaitCondVarThread, WaitMonitorThread, WaitCMonitorThread};
454
455static PRThreadScope threadScopes[] = {
456 PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD};
457
458static void Help(void)
459{
460 fprintf(stderr, "y2ktmo test program usage:\n");
461 fprintf(stderr, "\t-d debug mode (FALSE)\n");
462 fprintf(stderr, "\t-l <secs> lead time (%d)\n",
463 DEFAULT_LEAD_TIME_SECS);
464 fprintf(stderr, "\t-t <msecs> tolerance (%d)\n",
465 DEFAULT_TOLERANCE_MSECS);
466 fprintf(stderr, "\t-h this message\n");
467} /* Help */
468
469int main(int argc, char **argv)
470{
471 PRThread **threads;
472 int num_thread_funcs = sizeof(threadFuncs)/sizeof(NSPRThreadFunc);
473 int num_thread_scopes = sizeof(threadScopes)/sizeof(PRThreadScope);
474 int i, j;
475 int idx;
476 PRInt32 secs;
477 PLOptStatus os;
478 PLOptState *opt = PL_CreateOptState(argc, argv, "dl:t:h");
479
480 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
481 if (PL_OPT_BAD == os) continue;
482 switch (opt->option) {
483 case 'd': /* debug mode */
484 debug_mode = PR_TRUE;
485 break;
486 case 'l': /* lead time */
487 lead_time_secs = atoi(opt->value);
488 break;
489 case 't': /* tolerance */
490 tolerance_msecs = atoi(opt->value);
491 break;
492 case 'h':
493 default:
494 Help();
495 return 2;
496 }
497 }
498 PL_DestroyOptState(opt);
499
500 if (debug_mode) {
501 fprintf(stderr, "lead time: %d secs\n", lead_time_secs);
502 fprintf(stderr, "tolerance: %d msecs\n", tolerance_msecs);
503 }
504
505 start_time = PR_IntervalNow();
506#if defined(XP_UNIX)
507 gettimeofday(&start_time_tv, NULL);
508#endif
509#if defined(WIN32)
510 _ftime(&start_time_tb);
511#endif
512 tolerance = PR_MillisecondsToInterval(tolerance_msecs);
513
514 threads = PR_Malloc(
515 num_thread_scopes * num_thread_funcs * sizeof(PRThread*));
516 if (threads == NULL) {
517 fprintf(stderr, "PR_Malloc failed\n");
518 exit(1);
519 }
520
521 /* start to time out 5 seconds after a rollover date */
522 secs = lead_time_secs + 5;
523 idx = 0;
524 for (i = 0; i < num_thread_scopes; i++) {
525 for (j = 0; j < num_thread_funcs; j++) {
526 threads[idx] = PR_CreateThread(PR_USER_THREAD, threadFuncs[j],
527 (void*)PR_SecondsToInterval(secs), PR_PRIORITY_NORMAL,
528 threadScopes[i], PR_JOINABLE_THREAD, 0);
529 if (threads[idx] == NULL) {
530 fprintf(stderr, "PR_CreateThread failed\n");
531 exit(1);
532 }
533 secs++;
534 idx++;
535 }
536 }
537 for (idx = 0; idx < num_thread_scopes*num_thread_funcs; idx++) {
538 if (PR_JoinThread(threads[idx]) == PR_FAILURE) {
539 fprintf(stderr, "PR_JoinThread failed\n");
540 exit(1);
541 }
542 }
543 PR_Free(threads);
544 printf("PASS\n");
545 return 0;
546}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette